diff --git a/.gitattributes b/.gitattributes
index c7d9f3332a950355d5a77d85000f05e6f45435ea..d38d7be0506e2d1a757af17a17ba239256c2233a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -32,3 +32,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text
*tfevents* filter=lfs diff=lfs merge=lfs -text
+gradio/templates/cdn/assets/index.3c2bfbb6.js.map filter=lfs diff=lfs merge=lfs -text
+gradio/templates/frontend/assets/index.756cf7e0.js.map filter=lfs diff=lfs merge=lfs -text
diff --git a/gradio/.dockerignore b/gradio/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..450a3af270f5d285eb3a59a03593d06078b145eb
--- /dev/null
+++ b/gradio/.dockerignore
@@ -0,0 +1,2 @@
+templates/frontend
+templates/frontend/**/*
diff --git a/gradio/__init__.py b/gradio/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..da895876cb9e224f08d6a788f4c348af514f4527
--- /dev/null
+++ b/gradio/__init__.py
@@ -0,0 +1,93 @@
+import pkgutil
+
+import gradio.components as components
+import gradio.inputs as inputs
+import gradio.outputs as outputs
+import gradio.processing_utils
+import gradio.templates
+import gradio.themes as themes
+from gradio.blocks import Blocks
+from gradio.components import (
+ HTML,
+ JSON,
+ Audio,
+ BarPlot,
+ Button,
+ Carousel,
+ Chatbot,
+ Checkbox,
+ Checkboxgroup,
+ CheckboxGroup,
+ Code,
+ ColorPicker,
+ DataFrame,
+ Dataframe,
+ Dataset,
+ Dropdown,
+ File,
+ Gallery,
+ Highlight,
+ Highlightedtext,
+ HighlightedText,
+ Image,
+ Interpretation,
+ Json,
+ Label,
+ LinePlot,
+ Markdown,
+ Model3D,
+ Number,
+ Plot,
+ Radio,
+ ScatterPlot,
+ Slider,
+ State,
+ StatusTracker,
+ Text,
+ Textbox,
+ TimeSeries,
+ Timeseries,
+ UploadButton,
+ Variable,
+ Video,
+ component,
+)
+from gradio.events import SelectData
+from gradio.exceptions import Error
+from gradio.flagging import (
+ CSVLogger,
+ FlaggingCallback,
+ HuggingFaceDatasetJSONSaver,
+ HuggingFaceDatasetSaver,
+ SimpleCSVLogger,
+)
+from gradio.helpers import EventData, Progress
+from gradio.helpers import create_examples as Examples
+from gradio.helpers import make_waveform, skip, update
+from gradio.interface import Interface, TabbedInterface, close_all
+from gradio.ipython_ext import load_ipython_extension
+from gradio.layouts import Accordion, Box, Column, Group, Row, Tab, TabItem, Tabs
+from gradio.mix import Parallel, Series
+from gradio.routes import Request, mount_gradio_app
+from gradio.templates import (
+ Files,
+ ImageMask,
+ ImagePaint,
+ List,
+ Matrix,
+ Mic,
+ Microphone,
+ Numpy,
+ Paint,
+ Pil,
+ PlayableVideo,
+ Sketchpad,
+ TextArea,
+ Webcam,
+)
+from gradio.themes import Base as Theme
+
+current_pkg_version = (
+ (pkgutil.get_data(__name__, "version.txt") or b"").decode("ascii").strip()
+)
+__version__ = current_pkg_version
diff --git a/gradio/__pycache__/__init__.cpython-38.pyc b/gradio/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..36c63ed06c63350d868142f28bca800b0629c72a
Binary files /dev/null and b/gradio/__pycache__/__init__.cpython-38.pyc differ
diff --git a/gradio/__pycache__/blocks.cpython-38.pyc b/gradio/__pycache__/blocks.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..163732506b02a6d1dd977f518060cecbe3084020
Binary files /dev/null and b/gradio/__pycache__/blocks.cpython-38.pyc differ
diff --git a/gradio/__pycache__/components.cpython-38.pyc b/gradio/__pycache__/components.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9c25314efacc9dfe176515f66769b7465a9ae4dd
Binary files /dev/null and b/gradio/__pycache__/components.cpython-38.pyc differ
diff --git a/gradio/__pycache__/context.cpython-38.pyc b/gradio/__pycache__/context.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..837eb3c40c0e37f167bc114a75e613eaabc31f15
Binary files /dev/null and b/gradio/__pycache__/context.cpython-38.pyc differ
diff --git a/gradio/__pycache__/data_classes.cpython-38.pyc b/gradio/__pycache__/data_classes.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..97e07d13638589831241cdc6bab7fa7c0f00b9af
Binary files /dev/null and b/gradio/__pycache__/data_classes.cpython-38.pyc differ
diff --git a/gradio/__pycache__/deprecation.cpython-38.pyc b/gradio/__pycache__/deprecation.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c66f312e9ebf8988c0232cc9815af2fa4377c7ea
Binary files /dev/null and b/gradio/__pycache__/deprecation.cpython-38.pyc differ
diff --git a/gradio/__pycache__/documentation.cpython-38.pyc b/gradio/__pycache__/documentation.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a4722cc5ef8881eb8fba01ea1aa293a061c7c1a4
Binary files /dev/null and b/gradio/__pycache__/documentation.cpython-38.pyc differ
diff --git a/gradio/__pycache__/events.cpython-38.pyc b/gradio/__pycache__/events.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4f173a327e48c19aadbeaaf0516c3fe257517f96
Binary files /dev/null and b/gradio/__pycache__/events.cpython-38.pyc differ
diff --git a/gradio/__pycache__/exceptions.cpython-38.pyc b/gradio/__pycache__/exceptions.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2ca80bba8c6faa998572109e69f90c2ef38d18e4
Binary files /dev/null and b/gradio/__pycache__/exceptions.cpython-38.pyc differ
diff --git a/gradio/__pycache__/external.cpython-38.pyc b/gradio/__pycache__/external.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ae20730c1ca1a9169285cfbb015f19c212e4e506
Binary files /dev/null and b/gradio/__pycache__/external.cpython-38.pyc differ
diff --git a/gradio/__pycache__/external_utils.cpython-38.pyc b/gradio/__pycache__/external_utils.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5989c56953ece25d45bde50fdfceb242e85424f9
Binary files /dev/null and b/gradio/__pycache__/external_utils.cpython-38.pyc differ
diff --git a/gradio/__pycache__/flagging.cpython-38.pyc b/gradio/__pycache__/flagging.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3ed4bff0d958687f0e8303e74ac6a46aac1732d1
Binary files /dev/null and b/gradio/__pycache__/flagging.cpython-38.pyc differ
diff --git a/gradio/__pycache__/helpers.cpython-38.pyc b/gradio/__pycache__/helpers.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4346d821d46cf15e2db2f87d9fedce7ccc854d7e
Binary files /dev/null and b/gradio/__pycache__/helpers.cpython-38.pyc differ
diff --git a/gradio/__pycache__/inputs.cpython-38.pyc b/gradio/__pycache__/inputs.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ee1b10d7648eda9400cf604285e5ac31ec7499e1
Binary files /dev/null and b/gradio/__pycache__/inputs.cpython-38.pyc differ
diff --git a/gradio/__pycache__/interface.cpython-38.pyc b/gradio/__pycache__/interface.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6fbd275b4366f82348045f6e2143c3716c0aaaa7
Binary files /dev/null and b/gradio/__pycache__/interface.cpython-38.pyc differ
diff --git a/gradio/__pycache__/interpretation.cpython-38.pyc b/gradio/__pycache__/interpretation.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..09939a435874bef40baa6143830430dd5cf35a00
Binary files /dev/null and b/gradio/__pycache__/interpretation.cpython-38.pyc differ
diff --git a/gradio/__pycache__/ipython_ext.cpython-38.pyc b/gradio/__pycache__/ipython_ext.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6d02d3742a4dda56a64c3aa2717dded8850fbe7d
Binary files /dev/null and b/gradio/__pycache__/ipython_ext.cpython-38.pyc differ
diff --git a/gradio/__pycache__/layouts.cpython-38.pyc b/gradio/__pycache__/layouts.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fc77131d977a3f79b3e4b37c7ecb63de311cea50
Binary files /dev/null and b/gradio/__pycache__/layouts.cpython-38.pyc differ
diff --git a/gradio/__pycache__/media_data.cpython-38.pyc b/gradio/__pycache__/media_data.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..006b0b3c7f0a5a192c65884bff26d6f3ff18b408
Binary files /dev/null and b/gradio/__pycache__/media_data.cpython-38.pyc differ
diff --git a/gradio/__pycache__/mix.cpython-38.pyc b/gradio/__pycache__/mix.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9b09933c3b61c7ee578aa8a267e7cc976dab78cb
Binary files /dev/null and b/gradio/__pycache__/mix.cpython-38.pyc differ
diff --git a/gradio/__pycache__/networking.cpython-38.pyc b/gradio/__pycache__/networking.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..44493433820d0816addbe0305686523afc0c0195
Binary files /dev/null and b/gradio/__pycache__/networking.cpython-38.pyc differ
diff --git a/gradio/__pycache__/outputs.cpython-38.pyc b/gradio/__pycache__/outputs.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ed68ebd88e6d9f390a8a4bea326ba012bfc04d9c
Binary files /dev/null and b/gradio/__pycache__/outputs.cpython-38.pyc differ
diff --git a/gradio/__pycache__/pipelines.cpython-38.pyc b/gradio/__pycache__/pipelines.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ec3a297b8117680fd936b2a980bacb0f74d1d456
Binary files /dev/null and b/gradio/__pycache__/pipelines.cpython-38.pyc differ
diff --git a/gradio/__pycache__/processing_utils.cpython-38.pyc b/gradio/__pycache__/processing_utils.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..72e232b1d3301588a887f7aae54a35f3373820dc
Binary files /dev/null and b/gradio/__pycache__/processing_utils.cpython-38.pyc differ
diff --git a/gradio/__pycache__/queueing.cpython-38.pyc b/gradio/__pycache__/queueing.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b734636765c4616c0132f1bc49922908728e42e1
Binary files /dev/null and b/gradio/__pycache__/queueing.cpython-38.pyc differ
diff --git a/gradio/__pycache__/ranged_response.cpython-38.pyc b/gradio/__pycache__/ranged_response.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..84f22cc16d33d6c2a861d560ca29152e848083c0
Binary files /dev/null and b/gradio/__pycache__/ranged_response.cpython-38.pyc differ
diff --git a/gradio/__pycache__/reload.cpython-38.pyc b/gradio/__pycache__/reload.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bf341ce901ef21962d10e674d5d55e855d1ef218
Binary files /dev/null and b/gradio/__pycache__/reload.cpython-38.pyc differ
diff --git a/gradio/__pycache__/routes.cpython-38.pyc b/gradio/__pycache__/routes.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..23196514cd7b1a80f683d8fefe4add7c52c2f14c
Binary files /dev/null and b/gradio/__pycache__/routes.cpython-38.pyc differ
diff --git a/gradio/__pycache__/serializing.cpython-38.pyc b/gradio/__pycache__/serializing.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..38b15d897772eafe759488cb029059986ee33994
Binary files /dev/null and b/gradio/__pycache__/serializing.cpython-38.pyc differ
diff --git a/gradio/__pycache__/strings.cpython-38.pyc b/gradio/__pycache__/strings.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3a22c94a4b4d0ffba1000ddd9b2482df989eef2f
Binary files /dev/null and b/gradio/__pycache__/strings.cpython-38.pyc differ
diff --git a/gradio/__pycache__/templates.cpython-38.pyc b/gradio/__pycache__/templates.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d3af51a70946f6f2cf9d3b2eb64a859f74651bdc
Binary files /dev/null and b/gradio/__pycache__/templates.cpython-38.pyc differ
diff --git a/gradio/__pycache__/tunneling.cpython-38.pyc b/gradio/__pycache__/tunneling.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5fb5d3edf6b6e1bd41399d4b2f21765d0328cb41
Binary files /dev/null and b/gradio/__pycache__/tunneling.cpython-38.pyc differ
diff --git a/gradio/__pycache__/utils.cpython-38.pyc b/gradio/__pycache__/utils.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fe3af4581b19b74ef1c3f2d30a4341545f12483b
Binary files /dev/null and b/gradio/__pycache__/utils.cpython-38.pyc differ
diff --git a/gradio/blocks.py b/gradio/blocks.py
new file mode 100644
index 0000000000000000000000000000000000000000..ad009cf57f01d54c84f401b7469bccad0bf2daba
--- /dev/null
+++ b/gradio/blocks.py
@@ -0,0 +1,1779 @@
+from __future__ import annotations
+
+import copy
+import inspect
+import json
+import os
+import random
+import secrets
+import sys
+import time
+import warnings
+import webbrowser
+from abc import abstractmethod
+from types import ModuleType
+from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, List, Set, Tuple, Type
+
+import anyio
+import requests
+from anyio import CapacityLimiter
+from typing_extensions import Literal
+
+from gradio import components, external, networking, queueing, routes, strings, utils
+from gradio.context import Context
+from gradio.deprecation import check_deprecated_parameters
+from gradio.documentation import document, set_documentation_group
+from gradio.exceptions import DuplicateBlockError, InvalidApiName
+from gradio.helpers import EventData, create_tracker, skip, special_args
+from gradio.themes import Default as DefaultTheme
+from gradio.themes import ThemeClass as Theme
+from gradio.tunneling import CURRENT_TUNNELS
+from gradio.utils import (
+ GRADIO_VERSION,
+ TupleNoPrint,
+ check_function_inputs_match,
+ component_or_layout_class,
+ delete_none,
+ get_cancel_function,
+ get_continuous_fn,
+)
+
+set_documentation_group("blocks")
+
+if TYPE_CHECKING: # Only import for type checking (is False at runtime).
+ import comet_ml
+ from fastapi.applications import FastAPI
+
+ from gradio.components import Component
+
+
+class Block:
+ def __init__(
+ self,
+ *,
+ render: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ visible: bool = True,
+ root_url: str | None = None, # URL that is prepended to all file paths
+ _skip_init_processing: bool = False, # Used for loading from Spaces
+ **kwargs,
+ ):
+ self._id = Context.id
+ Context.id += 1
+ self.visible = visible
+ self.elem_id = elem_id
+ self.elem_classes = (
+ [elem_classes] if isinstance(elem_classes, str) else elem_classes
+ )
+ self.root_url = root_url
+ self.share_token = secrets.token_urlsafe(32)
+ self._skip_init_processing = _skip_init_processing
+ self._style = {}
+ self.parent: BlockContext | None = None
+ self.root = ""
+
+ if render:
+ self.render()
+ check_deprecated_parameters(self.__class__.__name__, **kwargs)
+
+ def render(self):
+ """
+ Adds self into appropriate BlockContext
+ """
+ if Context.root_block is not None and self._id in Context.root_block.blocks:
+ raise DuplicateBlockError(
+ f"A block with id: {self._id} has already been rendered in the current Blocks."
+ )
+ if Context.block is not None:
+ Context.block.add(self)
+ if Context.root_block is not None:
+ Context.root_block.blocks[self._id] = self
+ if isinstance(self, components.TempFileManager):
+ Context.root_block.temp_file_sets.append(self.temp_files)
+ return self
+
+ def unrender(self):
+ """
+ Removes self from BlockContext if it has been rendered (otherwise does nothing).
+ Removes self from the layout and collection of blocks, but does not delete any event triggers.
+ """
+ if Context.block is not None:
+ try:
+ Context.block.children.remove(self)
+ except ValueError:
+ pass
+ if Context.root_block is not None:
+ try:
+ del Context.root_block.blocks[self._id]
+ except KeyError:
+ pass
+ return self
+
+ def get_block_name(self) -> str:
+ """
+ Gets block's class name.
+
+ If it is template component it gets the parent's class name.
+
+ @return: class name
+ """
+ return (
+ self.__class__.__base__.__name__.lower()
+ if hasattr(self, "is_template")
+ else self.__class__.__name__.lower()
+ )
+
+ def get_expected_parent(self) -> Type[BlockContext] | None:
+ return None
+
+ def set_event_trigger(
+ self,
+ event_name: str,
+ fn: Callable | None,
+ inputs: Component | List[Component] | Set[Component] | None,
+ outputs: Component | List[Component] | None,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ scroll_to_output: bool = False,
+ show_progress: bool = True,
+ api_name: str | None = None,
+ js: str | None = None,
+ no_target: bool = False,
+ queue: bool | None = None,
+ batch: bool = False,
+ max_batch_size: int = 4,
+ cancels: List[int] | None = None,
+ every: float | None = None,
+ collects_event_data: bool | None = None,
+ trigger_after: int | None = None,
+ trigger_only_on_success: bool = False,
+ ) -> Tuple[Dict[str, Any], int]:
+ """
+ Adds an event to the component's dependencies.
+ Parameters:
+ event_name: event name
+ fn: Callable function
+ inputs: input list
+ outputs: output list
+ preprocess: whether to run the preprocess methods of components
+ postprocess: whether to run the postprocess methods of components
+ scroll_to_output: whether to scroll to output of dependency on trigger
+ show_progress: whether to show progress animation while running.
+ api_name: Defining this parameter exposes the endpoint in the api docs
+ js: Optional frontend js method to run before running 'fn'. Input arguments for js method are values of 'inputs' and 'outputs', return should be a list of values for output components
+ no_target: if True, sets "targets" to [], used for Blocks "load" event
+ batch: whether this function takes in a batch of inputs
+ max_batch_size: the maximum batch size to send to the function
+ cancels: a list of other events to cancel when this event is triggered. For example, setting cancels=[click_event] will cancel the click_event, where click_event is the return value of another components .click method.
+ every: Run this event 'every' number of seconds while the client connection is open. Interpreted in seconds. Queue must be enabled.
+ collects_event_data: whether to collect event data for this event
+ trigger_after: if set, this event will be triggered after 'trigger_after' function index
+ trigger_only_on_success: if True, this event will only be triggered if the previous event was successful (only applies if `trigger_after` is set)
+ Returns: dependency information, dependency index
+ """
+ # Support for singular parameter
+ if isinstance(inputs, set):
+ inputs_as_dict = True
+ inputs = sorted(inputs, key=lambda x: x._id)
+ else:
+ inputs_as_dict = False
+ if inputs is None:
+ inputs = []
+ elif not isinstance(inputs, list):
+ inputs = [inputs]
+
+ if isinstance(outputs, set):
+ outputs = sorted(outputs, key=lambda x: x._id)
+ else:
+ if outputs is None:
+ outputs = []
+ elif not isinstance(outputs, list):
+ outputs = [outputs]
+
+ if fn is not None and not cancels:
+ check_function_inputs_match(fn, inputs, inputs_as_dict)
+
+ if Context.root_block is None:
+ raise AttributeError(
+ f"{event_name}() and other events can only be called within a Blocks context."
+ )
+ if every is not None and every <= 0:
+ raise ValueError("Parameter every must be positive or None")
+ if every and batch:
+ raise ValueError(
+ f"Cannot run {event_name} event in a batch and every {every} seconds. "
+ "Either batch is True or every is non-zero but not both."
+ )
+
+ if every and fn:
+ fn = get_continuous_fn(fn, every)
+ elif every:
+ raise ValueError("Cannot set a value for `every` without a `fn`.")
+
+ _, progress_index, event_data_index = (
+ special_args(fn) if fn else (None, None, None)
+ )
+ Context.root_block.fns.append(
+ BlockFunction(
+ fn,
+ inputs,
+ outputs,
+ preprocess,
+ postprocess,
+ inputs_as_dict,
+ progress_index is not None,
+ )
+ )
+ if api_name is not None:
+ api_name_ = utils.append_unique_suffix(
+ api_name, [dep["api_name"] for dep in Context.root_block.dependencies]
+ )
+ if not (api_name == api_name_):
+ warnings.warn(
+ "api_name {} already exists, using {}".format(api_name, api_name_)
+ )
+ api_name = api_name_
+
+ if collects_event_data is None:
+ collects_event_data = event_data_index is not None
+
+ dependency = {
+ "targets": [self._id] if not no_target else [],
+ "trigger": event_name,
+ "inputs": [block._id for block in inputs],
+ "outputs": [block._id for block in outputs],
+ "backend_fn": fn is not None,
+ "js": js,
+ "queue": False if fn is None else queue,
+ "api_name": api_name,
+ "scroll_to_output": scroll_to_output,
+ "show_progress": show_progress,
+ "every": every,
+ "batch": batch,
+ "max_batch_size": max_batch_size,
+ "cancels": cancels or [],
+ "types": {
+ "continuous": bool(every),
+ "generator": inspect.isgeneratorfunction(fn) or bool(every),
+ },
+ "collects_event_data": collects_event_data,
+ "trigger_after": trigger_after,
+ "trigger_only_on_success": trigger_only_on_success,
+ }
+ Context.root_block.dependencies.append(dependency)
+ return dependency, len(Context.root_block.dependencies) - 1
+
+ def get_config(self):
+ return {
+ "visible": self.visible,
+ "elem_id": self.elem_id,
+ "elem_classes": self.elem_classes,
+ "style": self._style,
+ "root_url": self.root_url,
+ }
+
+ @staticmethod
+ @abstractmethod
+ def update(**kwargs) -> Dict:
+ return {}
+
+ @classmethod
+ def get_specific_update(cls, generic_update: Dict[str, Any]) -> Dict:
+ generic_update = generic_update.copy()
+ del generic_update["__type__"]
+ specific_update = cls.update(**generic_update)
+ return specific_update
+
+
+class BlockContext(Block):
+ def __init__(
+ self,
+ visible: bool = True,
+ render: bool = True,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ visible: If False, this will be hidden but included in the Blocks config file (its visibility can later be updated).
+ render: If False, this will not be included in the Blocks config file at all.
+ """
+ self.children: List[Block] = []
+ Block.__init__(self, visible=visible, render=render, **kwargs)
+
+ def __enter__(self):
+ self.parent = Context.block
+ Context.block = self
+ return self
+
+ def add(self, child: Block):
+ child.parent = self
+ self.children.append(child)
+
+ def fill_expected_parents(self):
+ children = []
+ pseudo_parent = None
+ for child in self.children:
+ expected_parent = child.get_expected_parent()
+ if not expected_parent or isinstance(self, expected_parent):
+ pseudo_parent = None
+ children.append(child)
+ else:
+ if pseudo_parent is not None and isinstance(
+ pseudo_parent, expected_parent
+ ):
+ pseudo_parent.children.append(child)
+ else:
+ pseudo_parent = expected_parent(render=False)
+ children.append(pseudo_parent)
+ pseudo_parent.children = [child]
+ if Context.root_block:
+ Context.root_block.blocks[pseudo_parent._id] = pseudo_parent
+ child.parent = pseudo_parent
+ self.children = children
+
+ def __exit__(self, *args):
+ if getattr(self, "allow_expected_parents", True):
+ self.fill_expected_parents()
+ Context.block = self.parent
+
+ def postprocess(self, y):
+ """
+ Any postprocessing needed to be performed on a block context.
+ """
+ return y
+
+
+class BlockFunction:
+ def __init__(
+ self,
+ fn: Callable | None,
+ inputs: List[Component],
+ outputs: List[Component],
+ preprocess: bool,
+ postprocess: bool,
+ inputs_as_dict: bool,
+ tracks_progress: bool = False,
+ ):
+ self.fn = fn
+ self.inputs = inputs
+ self.outputs = outputs
+ self.preprocess = preprocess
+ self.postprocess = postprocess
+ self.tracks_progress = tracks_progress
+ self.total_runtime = 0
+ self.total_runs = 0
+ self.inputs_as_dict = inputs_as_dict
+ self.name = getattr(fn, "__name__", "fn") if fn is not None else None
+
+ def __str__(self):
+ return str(
+ {
+ "fn": self.name,
+ "preprocess": self.preprocess,
+ "postprocess": self.postprocess,
+ }
+ )
+
+ def __repr__(self):
+ return str(self)
+
+
+class class_or_instancemethod(classmethod):
+ def __get__(self, instance, type_):
+ descr_get = super().__get__ if instance is None else self.__func__.__get__
+ return descr_get(instance, type_)
+
+
+def postprocess_update_dict(block: Block, update_dict: Dict, postprocess: bool = True):
+ """
+ Converts a dictionary of updates into a format that can be sent to the frontend.
+ E.g. {"__type__": "generic_update", "value": "2", "interactive": False}
+ Into -> {"__type__": "update", "value": 2.0, "mode": "static"}
+
+ Parameters:
+ block: The Block that is being updated with this update dictionary.
+ update_dict: The original update dictionary
+ postprocess: Whether to postprocess the "value" key of the update dictionary.
+ """
+ if update_dict.get("__type__", "") == "generic_update":
+ update_dict = block.get_specific_update(update_dict)
+ if update_dict.get("value") is components._Keywords.NO_VALUE:
+ update_dict.pop("value")
+ interactive = update_dict.pop("interactive", None)
+ if interactive is not None:
+ update_dict["mode"] = "dynamic" if interactive else "static"
+ prediction_value = delete_none(update_dict, skip_value=True)
+ if "value" in prediction_value and postprocess:
+ assert isinstance(
+ block, components.IOComponent
+ ), f"Component {block.__class__} does not support value"
+ prediction_value["value"] = block.postprocess(prediction_value["value"])
+ return prediction_value
+
+
+def convert_component_dict_to_list(
+ outputs_ids: List[int], predictions: Dict
+) -> List | Dict:
+ """
+ Converts a dictionary of component updates into a list of updates in the order of
+ the outputs_ids and including every output component. Leaves other types of dictionaries unchanged.
+ E.g. {"textbox": "hello", "number": {"__type__": "generic_update", "value": "2"}}
+ Into -> ["hello", {"__type__": "generic_update"}, {"__type__": "generic_update", "value": "2"}]
+ """
+ keys_are_blocks = [isinstance(key, Block) for key in predictions.keys()]
+ if all(keys_are_blocks):
+ reordered_predictions = [skip() for _ in outputs_ids]
+ for component, value in predictions.items():
+ if component._id not in outputs_ids:
+ raise ValueError(
+ f"Returned component {component} not specified as output of function."
+ )
+ output_index = outputs_ids.index(component._id)
+ reordered_predictions[output_index] = value
+ predictions = utils.resolve_singleton(reordered_predictions)
+ elif any(keys_are_blocks):
+ raise ValueError(
+ "Returned dictionary included some keys as Components. Either all keys must be Components to assign Component values, or return a List of values to assign output values in order."
+ )
+ return predictions
+
+
+@document("launch", "queue", "integrate", "load")
+class Blocks(BlockContext):
+ """
+ Blocks is Gradio's low-level API that allows you to create more custom web
+ applications and demos than Interfaces (yet still entirely in Python).
+
+
+ Compared to the Interface class, Blocks offers more flexibility and control over:
+ (1) the layout of components (2) the events that
+ trigger the execution of functions (3) data flows (e.g. inputs can trigger outputs,
+ which can trigger the next level of outputs). Blocks also offers ways to group
+ together related demos such as with tabs.
+
+
+ The basic usage of Blocks is as follows: create a Blocks object, then use it as a
+ context (with the "with" statement), and then define layouts, components, or events
+ within the Blocks context. Finally, call the launch() method to launch the demo.
+
+ Example:
+ import gradio as gr
+ def update(name):
+ return f"Welcome to Gradio, {name}!"
+
+ with gr.Blocks() as demo:
+ gr.Markdown("Start typing below and then click **Run** to see the output.")
+ with gr.Row():
+ inp = gr.Textbox(placeholder="What is your name?")
+ out = gr.Textbox()
+ btn = gr.Button("Run")
+ btn.click(fn=update, inputs=inp, outputs=out)
+
+ demo.launch()
+ Demos: blocks_hello, blocks_flipper, blocks_speech_text_sentiment, generate_english_german, sound_alert
+ Guides: blocks_and_event_listeners, controlling_layout, state_in_blocks, custom_CSS_and_JS, custom_interpretations_with_blocks, using_blocks_like_functions
+ """
+
+ def __init__(
+ self,
+ theme: Theme | str | None = None,
+ analytics_enabled: bool | None = None,
+ mode: str = "blocks",
+ title: str = "Gradio",
+ css: str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ analytics_enabled: whether to allow basic telemetry. If None, will use GRADIO_ANALYTICS_ENABLED environment variable or default to True.
+ mode: a human-friendly name for the kind of Blocks or Interface being created.
+ title: The tab title to display when this is opened in a browser window.
+ css: custom css or path to custom css file to apply to entire Blocks
+ """
+ # Cleanup shared parameters with Interface #TODO: is this part still necessary after Interface with Blocks?
+ self.limiter = None
+ self.save_to = None
+ if theme is None:
+ theme = DefaultTheme()
+ elif isinstance(theme, str):
+ try:
+ theme = Theme.from_hub(theme)
+ except Exception as e:
+ warnings.warn(f"Cannot load {theme}. Caught Exception: {str(e)}")
+ theme = DefaultTheme()
+ if not isinstance(theme, Theme):
+ warnings.warn("Theme should be a class loaded from gradio.themes")
+ theme = DefaultTheme()
+ self.theme = theme
+ self.theme_css = theme._get_theme_css()
+ self.stylesheets = theme._stylesheets
+ self.encrypt = False
+ self.share = False
+ self.enable_queue = None
+ self.max_threads = 40
+ self.show_error = True
+ if css is not None and os.path.exists(css):
+ with open(css) as css_file:
+ self.css = css_file.read()
+ else:
+ self.css = css
+
+ # For analytics_enabled and allow_flagging: (1) first check for
+ # parameter, (2) check for env variable, (3) default to True/"manual"
+ self.analytics_enabled = (
+ analytics_enabled
+ if analytics_enabled is not None
+ else os.getenv("GRADIO_ANALYTICS_ENABLED", "True") == "True"
+ )
+ if not self.analytics_enabled:
+ os.environ["HF_HUB_DISABLE_TELEMETRY"] = "True"
+ super().__init__(render=False, **kwargs)
+ self.blocks: Dict[int, Block] = {}
+ self.fns: List[BlockFunction] = []
+ self.dependencies = []
+ self.mode = mode
+
+ self.is_running = False
+ self.local_url = None
+ self.share_url = None
+ self.width = None
+ self.height = None
+ self.api_open = True
+
+ self.is_space = True if os.getenv("SYSTEM") == "spaces" else False
+ self.favicon_path = None
+ self.auth = None
+ self.dev_mode = True
+ self.app_id = random.getrandbits(64)
+ self.temp_file_sets = []
+ self.title = title
+ self.show_api = True
+
+ # Only used when an Interface is loaded from a config
+ self.predict = None
+ self.input_components = None
+ self.output_components = None
+ self.__name__ = None
+ self.api_mode = None
+ self.progress_tracking = None
+
+ self.file_directories = []
+
+ if self.analytics_enabled:
+ data = {
+ "mode": self.mode,
+ "custom_css": self.css is not None,
+ "theme": self.theme,
+ "version": GRADIO_VERSION,
+ }
+ utils.initiated_analytics(data)
+
+ @classmethod
+ def from_config(
+ cls,
+ config: dict,
+ fns: List[Callable],
+ root_url: str | None = None,
+ ) -> Blocks:
+ """
+ Factory method that creates a Blocks from a config and list of functions.
+
+ Parameters:
+ config: a dictionary containing the configuration of the Blocks.
+ fns: a list of functions that are used in the Blocks. Must be in the same order as the dependencies in the config.
+ root_url: an optional root url to use for the components in the Blocks. Allows serving files from an external URL.
+ """
+ config = copy.deepcopy(config)
+ components_config = config["components"]
+ original_mapping: Dict[int, Block] = {}
+
+ def get_block_instance(id: int) -> Block:
+ for block_config in components_config:
+ if block_config["id"] == id:
+ break
+ else:
+ raise ValueError("Cannot find block with id {}".format(id))
+ cls = component_or_layout_class(block_config["type"])
+ block_config["props"].pop("type", None)
+ block_config["props"].pop("name", None)
+ style = block_config["props"].pop("style", None)
+ if block_config["props"].get("root_url") is None and root_url:
+ block_config["props"]["root_url"] = root_url + "/"
+ # Any component has already processed its initial value, so we skip that step here
+ block = cls(**block_config["props"], _skip_init_processing=True)
+ if style and isinstance(block, components.IOComponent):
+ block.style(**style)
+ return block
+
+ def iterate_over_children(children_list):
+ for child_config in children_list:
+ id = child_config["id"]
+ block = get_block_instance(id)
+
+ original_mapping[id] = block
+
+ children = child_config.get("children")
+ if children is not None:
+ assert isinstance(
+ block, BlockContext
+ ), f"Invalid config, Block with id {id} has children but is not a BlockContext."
+ with block:
+ iterate_over_children(children)
+
+ derived_fields = ["types"]
+
+ with Blocks() as blocks:
+ # ID 0 should be the root Blocks component
+ original_mapping[0] = Context.root_block or blocks
+
+ iterate_over_children(config["layout"]["children"])
+
+ first_dependency = None
+
+ # add the event triggers
+ for dependency, fn in zip(config["dependencies"], fns):
+ # We used to add a "fake_event" to the config to cache examples
+ # without removing it. This was causing bugs in calling gr.Interface.load
+ # We fixed the issue by removing "fake_event" from the config in examples.py
+ # but we still need to skip these events when loading the config to support
+ # older demos
+ if dependency["trigger"] == "fake_event":
+ continue
+ for field in derived_fields:
+ dependency.pop(field, None)
+ targets = dependency.pop("targets")
+ trigger = dependency.pop("trigger")
+ dependency.pop("backend_fn")
+ dependency.pop("documentation", None)
+ dependency["inputs"] = [
+ original_mapping[i] for i in dependency["inputs"]
+ ]
+ dependency["outputs"] = [
+ original_mapping[o] for o in dependency["outputs"]
+ ]
+ dependency.pop("status_tracker", None)
+ dependency["preprocess"] = False
+ dependency["postprocess"] = False
+
+ for target in targets:
+ dependency = original_mapping[target].set_event_trigger(
+ event_name=trigger, fn=fn, **dependency
+ )[0]
+ if first_dependency is None:
+ first_dependency = dependency
+
+ # Allows some use of Interface-specific methods with loaded Spaces
+ if first_dependency and Context.root_block:
+ blocks.predict = [fns[0]]
+ blocks.input_components = [
+ Context.root_block.blocks[i] for i in first_dependency["inputs"]
+ ]
+ blocks.output_components = [
+ Context.root_block.blocks[o] for o in first_dependency["outputs"]
+ ]
+ blocks.__name__ = "Interface"
+ blocks.api_mode = True
+
+ return blocks
+
+ def __str__(self):
+ return self.__repr__()
+
+ def __repr__(self):
+ num_backend_fns = len([d for d in self.dependencies if d["backend_fn"]])
+ repr = f"Gradio Blocks instance: {num_backend_fns} backend functions"
+ repr += "\n" + "-" * len(repr)
+ for d, dependency in enumerate(self.dependencies):
+ if dependency["backend_fn"]:
+ repr += f"\nfn_index={d}"
+ repr += "\n inputs:"
+ for input_id in dependency["inputs"]:
+ block = self.blocks[input_id]
+ repr += "\n |-{}".format(str(block))
+ repr += "\n outputs:"
+ for output_id in dependency["outputs"]:
+ block = self.blocks[output_id]
+ repr += "\n |-{}".format(str(block))
+ return repr
+
+ def render(self):
+ if Context.root_block is not None:
+ if self._id in Context.root_block.blocks:
+ raise DuplicateBlockError(
+ f"A block with id: {self._id} has already been rendered in the current Blocks."
+ )
+ if not set(Context.root_block.blocks).isdisjoint(self.blocks):
+ raise DuplicateBlockError(
+ "At least one block in this Blocks has already been rendered."
+ )
+
+ Context.root_block.blocks.update(self.blocks)
+ Context.root_block.fns.extend(self.fns)
+ dependency_offset = len(Context.root_block.dependencies)
+ for i, dependency in enumerate(self.dependencies):
+ api_name = dependency["api_name"]
+ if api_name is not None:
+ api_name_ = utils.append_unique_suffix(
+ api_name,
+ [dep["api_name"] for dep in Context.root_block.dependencies],
+ )
+ if not (api_name == api_name_):
+ warnings.warn(
+ "api_name {} already exists, using {}".format(
+ api_name, api_name_
+ )
+ )
+ dependency["api_name"] = api_name_
+ dependency["cancels"] = [
+ c + dependency_offset for c in dependency["cancels"]
+ ]
+ if dependency.get("trigger_after") is not None:
+ dependency["trigger_after"] += dependency_offset
+ # Recreate the cancel function so that it has the latest
+ # dependency fn indices. This is necessary to properly cancel
+ # events in the backend
+ if dependency["cancels"]:
+ updated_cancels = [
+ Context.root_block.dependencies[i]
+ for i in dependency["cancels"]
+ ]
+ new_fn = BlockFunction(
+ get_cancel_function(updated_cancels)[0],
+ [],
+ [],
+ False,
+ True,
+ False,
+ )
+ Context.root_block.fns[dependency_offset + i] = new_fn
+ Context.root_block.dependencies.append(dependency)
+ Context.root_block.temp_file_sets.extend(self.temp_file_sets)
+
+ if Context.block is not None:
+ Context.block.children.extend(self.children)
+ return self
+
+ def is_callable(self, fn_index: int = 0) -> bool:
+ """Checks if a particular Blocks function is callable (i.e. not stateful or a generator)."""
+ block_fn = self.fns[fn_index]
+ dependency = self.dependencies[fn_index]
+
+ if inspect.isasyncgenfunction(block_fn.fn):
+ return False
+ if inspect.isgeneratorfunction(block_fn.fn):
+ return False
+ for input_id in dependency["inputs"]:
+ block = self.blocks[input_id]
+ if getattr(block, "stateful", False):
+ return False
+ for output_id in dependency["outputs"]:
+ block = self.blocks[output_id]
+ if getattr(block, "stateful", False):
+ return False
+
+ return True
+
+ def __call__(self, *inputs, fn_index: int = 0, api_name: str | None = None):
+ """
+ Allows Blocks objects to be called as functions. Supply the parameters to the
+ function as positional arguments. To choose which function to call, use the
+ fn_index parameter, which must be a keyword argument.
+
+ Parameters:
+ *inputs: the parameters to pass to the function
+ fn_index: the index of the function to call (defaults to 0, which for Interfaces, is the default prediction function)
+ api_name: The api_name of the dependency to call. Will take precedence over fn_index.
+ """
+ if api_name is not None:
+ inferred_fn_index = next(
+ (
+ i
+ for i, d in enumerate(self.dependencies)
+ if d.get("api_name") == api_name
+ ),
+ None,
+ )
+ if inferred_fn_index is None:
+ raise InvalidApiName(f"Cannot find a function with api_name {api_name}")
+ fn_index = inferred_fn_index
+ if not (self.is_callable(fn_index)):
+ raise ValueError(
+ "This function is not callable because it is either stateful or is a generator. Please use the .launch() method instead to create an interactive user interface."
+ )
+
+ inputs = list(inputs)
+ processed_inputs = self.serialize_data(fn_index, inputs)
+ batch = self.dependencies[fn_index]["batch"]
+ if batch:
+ processed_inputs = [[inp] for inp in processed_inputs]
+
+ outputs = utils.synchronize_async(
+ self.process_api,
+ fn_index=fn_index,
+ inputs=processed_inputs,
+ request=None,
+ state={},
+ )
+ outputs = outputs["data"]
+
+ if batch:
+ outputs = [out[0] for out in outputs]
+
+ processed_outputs = self.deserialize_data(fn_index, outputs)
+ processed_outputs = utils.resolve_singleton(processed_outputs)
+
+ return processed_outputs
+
+ async def call_function(
+ self,
+ fn_index: int,
+ processed_input: List[Any],
+ iterator: Iterator[Any] | None = None,
+ requests: routes.Request | List[routes.Request] | None = None,
+ event_id: str | None = None,
+ event_data: EventData | None = None,
+ ):
+ """
+ Calls function with given index and preprocessed input, and measures process time.
+ Parameters:
+ fn_index: index of function to call
+ processed_input: preprocessed input to pass to function
+ iterator: iterator to use if function is a generator
+ requests: requests to pass to function
+ event_id: id of event in queue
+ event_data: data associated with event trigger
+ """
+ block_fn = self.fns[fn_index]
+ assert block_fn.fn, f"function with index {fn_index} not defined."
+ is_generating = False
+
+ if block_fn.inputs_as_dict:
+ processed_input = [
+ {
+ input_component: data
+ for input_component, data in zip(block_fn.inputs, processed_input)
+ }
+ ]
+
+ if isinstance(requests, list):
+ request = requests[0]
+ else:
+ request = requests
+ processed_input, progress_index, _ = special_args(
+ block_fn.fn, processed_input, request, event_data
+ )
+ progress_tracker = (
+ processed_input[progress_index] if progress_index is not None else None
+ )
+
+ start = time.time()
+
+ if iterator is None: # If not a generator function that has already run
+ if progress_tracker is not None and progress_index is not None:
+ progress_tracker, fn = create_tracker(
+ self, event_id, block_fn.fn, progress_tracker.track_tqdm
+ )
+ processed_input[progress_index] = progress_tracker
+ else:
+ fn = block_fn.fn
+
+ if inspect.iscoroutinefunction(fn):
+ prediction = await fn(*processed_input)
+ else:
+ prediction = await anyio.to_thread.run_sync(
+ fn, *processed_input, limiter=self.limiter
+ )
+ else:
+ prediction = None
+
+ if inspect.isasyncgenfunction(block_fn.fn):
+ raise ValueError("Gradio does not support async generators.")
+ if inspect.isgeneratorfunction(block_fn.fn):
+ if not self.enable_queue:
+ raise ValueError("Need to enable queue to use generators.")
+ try:
+ if iterator is None:
+ iterator = prediction
+ prediction = await anyio.to_thread.run_sync(
+ utils.async_iteration, iterator, limiter=self.limiter
+ )
+ is_generating = True
+ except StopAsyncIteration:
+ n_outputs = len(self.dependencies[fn_index].get("outputs"))
+ prediction = (
+ components._Keywords.FINISHED_ITERATING
+ if n_outputs == 1
+ else (components._Keywords.FINISHED_ITERATING,) * n_outputs
+ )
+ iterator = None
+
+ duration = time.time() - start
+
+ return {
+ "prediction": prediction,
+ "duration": duration,
+ "is_generating": is_generating,
+ "iterator": iterator,
+ }
+
+ def serialize_data(self, fn_index: int, inputs: List[Any]) -> List[Any]:
+ dependency = self.dependencies[fn_index]
+ processed_input = []
+
+ for i, input_id in enumerate(dependency["inputs"]):
+ block = self.blocks[input_id]
+ assert isinstance(
+ block, components.IOComponent
+ ), f"{block.__class__} Component with id {input_id} not a valid input component."
+ serialized_input = block.serialize(inputs[i])
+ processed_input.append(serialized_input)
+
+ return processed_input
+
+ def deserialize_data(self, fn_index: int, outputs: List[Any]) -> List[Any]:
+ dependency = self.dependencies[fn_index]
+ predictions = []
+
+ for o, output_id in enumerate(dependency["outputs"]):
+ block = self.blocks[output_id]
+ assert isinstance(
+ block, components.IOComponent
+ ), f"{block.__class__} Component with id {output_id} not a valid output component."
+ deserialized = block.deserialize(outputs[o], root_url=block.root_url)
+ predictions.append(deserialized)
+
+ return predictions
+
+ def preprocess_data(self, fn_index: int, inputs: List[Any], state: Dict[int, Any]):
+ block_fn = self.fns[fn_index]
+ dependency = self.dependencies[fn_index]
+
+ if block_fn.preprocess:
+ processed_input = []
+ for i, input_id in enumerate(dependency["inputs"]):
+ block = self.blocks[input_id]
+ assert isinstance(
+ block, components.Component
+ ), f"{block.__class__} Component with id {input_id} not a valid input component."
+ if getattr(block, "stateful", False):
+ processed_input.append(state.get(input_id))
+ else:
+ processed_input.append(block.preprocess(inputs[i]))
+ else:
+ processed_input = inputs
+ return processed_input
+
+ def postprocess_data(
+ self, fn_index: int, predictions: List | Dict, state: Dict[int, Any]
+ ):
+ block_fn = self.fns[fn_index]
+ dependency = self.dependencies[fn_index]
+ batch = dependency["batch"]
+
+ if type(predictions) is dict and len(predictions) > 0:
+ predictions = convert_component_dict_to_list(
+ dependency["outputs"], predictions
+ )
+
+ if len(dependency["outputs"]) == 1 and not (batch):
+ predictions = [
+ predictions,
+ ]
+
+ output = []
+ for i, output_id in enumerate(dependency["outputs"]):
+ try:
+ if predictions[i] is components._Keywords.FINISHED_ITERATING:
+ output.append(None)
+ continue
+ except (IndexError, KeyError):
+ raise ValueError(
+ f"Number of output components does not match number of values returned from from function {block_fn.name}"
+ )
+ block = self.blocks[output_id]
+ if getattr(block, "stateful", False):
+ if not utils.is_update(predictions[i]):
+ state[output_id] = predictions[i]
+ output.append(None)
+ else:
+ prediction_value = predictions[i]
+ if utils.is_update(prediction_value):
+ assert isinstance(prediction_value, dict)
+ prediction_value = postprocess_update_dict(
+ block=block,
+ update_dict=prediction_value,
+ postprocess=block_fn.postprocess,
+ )
+ elif block_fn.postprocess:
+ assert isinstance(
+ block, components.Component
+ ), f"{block.__class__} Component with id {output_id} not a valid output component."
+ prediction_value = block.postprocess(prediction_value)
+ output.append(prediction_value)
+
+ return output
+
+ async def process_api(
+ self,
+ fn_index: int,
+ inputs: List[Any],
+ state: Dict[int, Any],
+ request: routes.Request | List[routes.Request] | None = None,
+ iterators: Dict[int, Any] | None = None,
+ event_id: str | None = None,
+ event_data: EventData | None = None,
+ ) -> Dict[str, Any]:
+ """
+ Processes API calls from the frontend. First preprocesses the data,
+ then runs the relevant function, then postprocesses the output.
+ Parameters:
+ fn_index: Index of function to run.
+ inputs: input data received from the frontend
+ username: name of user if authentication is set up (not used)
+ state: data stored from stateful components for session (key is input block id)
+ iterators: the in-progress iterators for each generator function (key is function index)
+ event_id: id of event that triggered this API call
+ event_data: data associated with the event trigger itself
+ Returns: None
+ """
+ block_fn = self.fns[fn_index]
+ batch = self.dependencies[fn_index]["batch"]
+
+ if batch:
+ max_batch_size = self.dependencies[fn_index]["max_batch_size"]
+ batch_sizes = [len(inp) for inp in inputs]
+ batch_size = batch_sizes[0]
+ if inspect.isasyncgenfunction(block_fn.fn) or inspect.isgeneratorfunction(
+ block_fn.fn
+ ):
+ raise ValueError("Gradio does not support generators in batch mode.")
+ if not all(x == batch_size for x in batch_sizes):
+ raise ValueError(
+ f"All inputs to a batch function must have the same length but instead have sizes: {batch_sizes}."
+ )
+ if batch_size > max_batch_size:
+ raise ValueError(
+ f"Batch size ({batch_size}) exceeds the max_batch_size for this function ({max_batch_size})"
+ )
+
+ inputs = [
+ self.preprocess_data(fn_index, list(i), state) for i in zip(*inputs)
+ ]
+ result = await self.call_function(
+ fn_index, list(zip(*inputs)), None, request, event_id, event_data
+ )
+ preds = result["prediction"]
+ data = [
+ self.postprocess_data(fn_index, list(o), state) for o in zip(*preds)
+ ]
+ data = list(zip(*data))
+ is_generating, iterator = None, None
+ else:
+ inputs = self.preprocess_data(fn_index, inputs, state)
+ iterator = iterators.get(fn_index, None) if iterators else None
+ result = await self.call_function(
+ fn_index, inputs, iterator, request, event_id, event_data
+ )
+ data = self.postprocess_data(fn_index, result["prediction"], state)
+ is_generating, iterator = result["is_generating"], result["iterator"]
+
+ block_fn.total_runtime += result["duration"]
+ block_fn.total_runs += 1
+
+ return {
+ "data": data,
+ "is_generating": is_generating,
+ "iterator": iterator,
+ "duration": result["duration"],
+ "average_duration": block_fn.total_runtime / block_fn.total_runs,
+ }
+
+ async def create_limiter(self):
+ self.limiter = (
+ None
+ if self.max_threads == 40
+ else CapacityLimiter(total_tokens=self.max_threads)
+ )
+
+ def get_config(self):
+ return {"type": "column"}
+
+ def get_config_file(self):
+ config = {
+ "version": routes.VERSION,
+ "mode": self.mode,
+ "dev_mode": self.dev_mode,
+ "analytics_enabled": self.analytics_enabled,
+ "components": [],
+ "css": self.css,
+ "title": self.title or "Gradio",
+ "is_space": self.is_space,
+ "enable_queue": getattr(self, "enable_queue", False), # launch attributes
+ "show_error": getattr(self, "show_error", False),
+ "show_api": self.show_api,
+ "is_colab": utils.colab_check(),
+ "stylesheets": self.stylesheets,
+ "root": self.root,
+ }
+
+ def getLayout(block):
+ if not isinstance(block, BlockContext):
+ return {"id": block._id}
+ children_layout = []
+ for child in block.children:
+ children_layout.append(getLayout(child))
+ return {"id": block._id, "children": children_layout}
+
+ config["layout"] = getLayout(self)
+
+ for _id, block in self.blocks.items():
+ config["components"].append(
+ {
+ "id": _id,
+ "type": (block.get_block_name()),
+ "props": utils.delete_none(block.get_config())
+ if hasattr(block, "get_config")
+ else {},
+ }
+ )
+ config["dependencies"] = self.dependencies
+ return config
+
+ def __enter__(self):
+ if Context.block is None:
+ Context.root_block = self
+ self.parent = Context.block
+ Context.block = self
+ return self
+
+ def __exit__(self, *args):
+ super().fill_expected_parents()
+ Context.block = self.parent
+ # Configure the load events before root_block is reset
+ self.attach_load_events()
+ if self.parent is None:
+ Context.root_block = None
+ else:
+ self.parent.children.extend(self.children)
+ self.config = self.get_config_file()
+ self.app = routes.App.create_app(self)
+ self.progress_tracking = any(block_fn.tracks_progress for block_fn in self.fns)
+
+ @class_or_instancemethod
+ def load(
+ self_or_cls,
+ fn: Callable | None = None,
+ inputs: List[Component] | None = None,
+ outputs: List[Component] | None = None,
+ api_name: str | None = None,
+ scroll_to_output: bool = False,
+ show_progress: bool = True,
+ queue=None,
+ batch: bool = False,
+ max_batch_size: int = 4,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ every: float | None = None,
+ _js: str | None = None,
+ *,
+ name: str | None = None,
+ src: str | None = None,
+ api_key: str | None = None,
+ alias: str | None = None,
+ **kwargs,
+ ) -> Blocks | Dict[str, Any] | None:
+ """
+ For reverse compatibility reasons, this is both a class method and an instance
+ method, the two of which, confusingly, do two completely different things.
+
+
+ Class method: loads a demo from a Hugging Face Spaces repo and creates it locally and returns a block instance. Equivalent to gradio.Interface.load()
+
+
+ Instance method: adds event that runs as soon as the demo loads in the browser. Example usage below.
+ Parameters:
+ name: Class Method - the name of the model (e.g. "gpt2" or "facebook/bart-base") or space (e.g. "flax-community/spanish-gpt2"), can include the `src` as prefix (e.g. "models/facebook/bart-base")
+ src: Class Method - the source of the model: `models` or `spaces` (or leave empty if source is provided as a prefix in `name`)
+ api_key: Class Method - optional access token for loading private Hugging Face Hub models or spaces. Find your token here: https://huggingface.co/settings/tokens
+ alias: Class Method - optional string used as the name of the loaded model instead of the default name (only applies if loading a Space running Gradio 2.x)
+ fn: Instance Method - the function to wrap an interface around. Often a machine learning model's prediction function. Each parameter of the function corresponds to one input component, and the function should return a single value or a tuple of values, with each element in the tuple corresponding to one output component.
+ inputs: Instance Method - List of gradio.components to use as inputs. If the function takes no inputs, this should be an empty list.
+ outputs: Instance Method - List of gradio.components to use as inputs. If the function returns no outputs, this should be an empty list.
+ api_name: Instance Method - Defining this parameter exposes the endpoint in the api docs
+ scroll_to_output: Instance Method - If True, will scroll to output component on completion
+ show_progress: Instance Method - If True, will show progress animation while pending
+ queue: Instance Method - If True, will place the request on the queue, if the queue exists
+ batch: Instance Method - If True, then the function should process a batch of inputs, meaning that it should accept a list of input values for each parameter. The lists should be of equal length (and be up to length `max_batch_size`). The function is then *required* to return a tuple of lists (even if there is only 1 output component), with each list in the tuple corresponding to one output component.
+ max_batch_size: Instance Method - Maximum number of inputs to batch together if this is called from the queue (only relevant if batch=True)
+ preprocess: Instance Method - If False, will not run preprocessing of component data before running 'fn' (e.g. leaving it as a base64 string if this method is called with the `Image` component).
+ postprocess: Instance Method - If False, will not run postprocessing of component data before returning 'fn' output to the browser.
+ every: Instance Method - Run this event 'every' number of seconds. Interpreted in seconds. Queue must be enabled.
+ Example:
+ import gradio as gr
+ import datetime
+ with gr.Blocks() as demo:
+ def get_time():
+ return datetime.datetime.now().time()
+ dt = gr.Textbox(label="Current time")
+ demo.load(get_time, inputs=None, outputs=dt)
+ demo.launch()
+ """
+ # _js: Optional frontend js method to run before running 'fn'. Input arguments for js method are values of 'inputs' and 'outputs', return should be a list of values for output components.
+ if isinstance(self_or_cls, type):
+ if name is None:
+ raise ValueError(
+ "Blocks.load() requires passing parameters as keyword arguments"
+ )
+ return external.load_blocks_from_repo(name, src, api_key, alias, **kwargs)
+ else:
+ return self_or_cls.set_event_trigger(
+ event_name="load",
+ fn=fn,
+ inputs=inputs,
+ outputs=outputs,
+ api_name=api_name,
+ preprocess=preprocess,
+ postprocess=postprocess,
+ scroll_to_output=scroll_to_output,
+ show_progress=show_progress,
+ js=_js,
+ queue=queue,
+ batch=batch,
+ max_batch_size=max_batch_size,
+ every=every,
+ no_target=True,
+ )[0]
+
+ def clear(self):
+ """Resets the layout of the Blocks object."""
+ self.blocks = {}
+ self.fns = []
+ self.dependencies = []
+ self.children = []
+ return self
+
+ @document()
+ def queue(
+ self,
+ concurrency_count: int = 1,
+ status_update_rate: float | Literal["auto"] = "auto",
+ client_position_to_load_data: int | None = None,
+ default_enabled: bool | None = None,
+ api_open: bool = True,
+ max_size: int | None = None,
+ ):
+ """
+ You can control the rate of processed requests by creating a queue. This will allow you to set the number of requests to be processed at one time, and will let users know their position in the queue.
+ Parameters:
+ concurrency_count: Number of worker threads that will be processing requests from the queue concurrently. Increasing this number will increase the rate at which requests are processed, but will also increase the memory usage of the queue.
+ status_update_rate: If "auto", Queue will send status estimations to all clients whenever a job is finished. Otherwise Queue will send status at regular intervals set by this parameter as the number of seconds.
+ client_position_to_load_data: DEPRECATED. This parameter is deprecated and has no effect.
+ default_enabled: Deprecated and has no effect.
+ api_open: If True, the REST routes of the backend will be open, allowing requests made directly to those endpoints to skip the queue.
+ max_size: The maximum number of events the queue will store at any given moment. If the queue is full, new events will not be added and a user will receive a message saying that the queue is full. If None, the queue size will be unlimited.
+ Example: (Blocks)
+ with gr.Blocks() as demo:
+ button = gr.Button(label="Generate Image")
+ button.click(fn=image_generator, inputs=gr.Textbox(), outputs=gr.Image())
+ demo.queue(concurrency_count=3)
+ demo.launch()
+ Example: (Interface)
+ demo = gr.Interface(image_generator, gr.Textbox(), gr.Image())
+ demo.queue(concurrency_count=3)
+ demo.launch()
+ """
+ if default_enabled is not None:
+ warnings.warn(
+ "The default_enabled parameter of queue has no effect and will be removed "
+ "in a future version of gradio."
+ )
+ self.enable_queue = True
+ self.api_open = api_open
+ if client_position_to_load_data is not None:
+ warnings.warn("The client_position_to_load_data parameter is deprecated.")
+ self._queue = queueing.Queue(
+ live_updates=status_update_rate == "auto",
+ concurrency_count=concurrency_count,
+ update_intervals=status_update_rate if status_update_rate != "auto" else 1,
+ max_size=max_size,
+ blocks_dependencies=self.dependencies,
+ )
+ self.config = self.get_config_file()
+ self.app = routes.App.create_app(self)
+ return self
+
+ def launch(
+ self,
+ inline: bool | None = None,
+ inbrowser: bool = False,
+ share: bool | None = None,
+ debug: bool = False,
+ enable_queue: bool | None = None,
+ max_threads: int = 40,
+ auth: Callable | Tuple[str, str] | List[Tuple[str, str]] | None = None,
+ auth_message: str | None = None,
+ prevent_thread_lock: bool = False,
+ show_error: bool = False,
+ server_name: str | None = None,
+ server_port: int | None = None,
+ show_tips: bool = False,
+ height: int = 500,
+ width: int | str = "100%",
+ encrypt: bool | None = None,
+ favicon_path: str | None = None,
+ ssl_keyfile: str | None = None,
+ ssl_certfile: str | None = None,
+ ssl_keyfile_password: str | None = None,
+ quiet: bool = False,
+ show_api: bool = True,
+ file_directories: List[str] | None = None,
+ _frontend: bool = True,
+ ) -> Tuple[FastAPI, str, str]:
+ """
+ Launches a simple web server that serves the demo. Can also be used to create a
+ public link used by anyone to access the demo from their browser by setting share=True.
+
+ Parameters:
+ inline: whether to display in the interface inline in an iframe. Defaults to True in python notebooks; False otherwise.
+ inbrowser: whether to automatically launch the interface in a new tab on the default browser.
+ share: whether to create a publicly shareable link for the interface. Creates an SSH tunnel to make your UI accessible from anywhere. If not provided, it is set to False by default every time, except when running in Google Colab. When localhost is not accessible (e.g. Google Colab), setting share=False is not supported.
+ debug: if True, blocks the main thread from running. If running in Google Colab, this is needed to print the errors in the cell output.
+ auth: If provided, username and password (or list of username-password tuples) required to access interface. Can also provide function that takes username and password and returns True if valid login.
+ auth_message: If provided, HTML message provided on login page.
+ prevent_thread_lock: If True, the interface will block the main thread while the server is running.
+ show_error: If True, any errors in the interface will be displayed in an alert modal and printed in the browser console log
+ server_port: will start gradio app on this port (if available). Can be set by environment variable GRADIO_SERVER_PORT. If None, will search for an available port starting at 7860.
+ server_name: to make app accessible on local network, set this to "0.0.0.0". Can be set by environment variable GRADIO_SERVER_NAME. If None, will use "127.0.0.1".
+ show_tips: if True, will occasionally show tips about new Gradio features
+ enable_queue: DEPRECATED (use .queue() method instead.) if True, inference requests will be served through a queue instead of with parallel threads. Required for longer inference times (> 1min) to prevent timeout. The default option in HuggingFace Spaces is True. The default option elsewhere is False.
+ max_threads: the maximum number of total threads that the Gradio app can generate in parallel. The default is inherited from the starlette library (currently 40). Applies whether the queue is enabled or not. But if queuing is enabled, this parameter is increaseed to be at least the concurrency_count of the queue.
+ width: The width in pixels of the iframe element containing the interface (used if inline=True)
+ height: The height in pixels of the iframe element containing the interface (used if inline=True)
+ encrypt: DEPRECATED. Has no effect.
+ favicon_path: If a path to a file (.png, .gif, or .ico) is provided, it will be used as the favicon for the web page.
+ ssl_keyfile: If a path to a file is provided, will use this as the private key file to create a local server running on https.
+ ssl_certfile: If a path to a file is provided, will use this as the signed certificate for https. Needs to be provided if ssl_keyfile is provided.
+ ssl_keyfile_password: If a password is provided, will use this with the ssl certificate for https.
+ quiet: If True, suppresses most print statements.
+ show_api: If True, shows the api docs in the footer of the app. Default True. If the queue is enabled, then api_open parameter of .queue() will determine if the api docs are shown, independent of the value of show_api.
+ file_directories: List of directories that gradio is allowed to serve files from (in addition to the directory containing the gradio python file). Must be absolute paths. Warning: any files in these directories or its children are potentially accessible to all users of your app.
+ Returns:
+ app: FastAPI app object that is running the demo
+ local_url: Locally accessible link to the demo
+ share_url: Publicly accessible link to the demo (if share=True, otherwise None)
+ Example: (Blocks)
+ import gradio as gr
+ def reverse(text):
+ return text[::-1]
+ with gr.Blocks() as demo:
+ button = gr.Button(value="Reverse")
+ button.click(reverse, gr.Textbox(), gr.Textbox())
+ demo.launch(share=True, auth=("username", "password"))
+ Example: (Interface)
+ import gradio as gr
+ def reverse(text):
+ return text[::-1]
+ demo = gr.Interface(reverse, "text", "text")
+ demo.launch(share=True, auth=("username", "password"))
+ """
+ self.dev_mode = False
+ if (
+ auth
+ and not callable(auth)
+ and not isinstance(auth[0], tuple)
+ and not isinstance(auth[0], list)
+ ):
+ self.auth = [auth]
+ else:
+ self.auth = auth
+ self.auth_message = auth_message
+ self.show_tips = show_tips
+ self.show_error = show_error
+ self.height = height
+ self.width = width
+ self.favicon_path = favicon_path
+
+ if enable_queue is not None:
+ self.enable_queue = enable_queue
+ warnings.warn(
+ "The `enable_queue` parameter has been deprecated. Please use the `.queue()` method instead.",
+ DeprecationWarning,
+ )
+ if encrypt is not None:
+ warnings.warn(
+ "The `encrypt` parameter has been deprecated and has no effect.",
+ DeprecationWarning,
+ )
+
+ if self.is_space:
+ self.enable_queue = self.enable_queue is not False
+ else:
+ self.enable_queue = self.enable_queue is True
+ if self.enable_queue and not hasattr(self, "_queue"):
+ self.queue()
+ self.show_api = self.api_open if self.enable_queue else show_api
+
+ self.file_directories = file_directories if file_directories is not None else []
+ if not isinstance(self.file_directories, list):
+ raise ValueError("file_directories must be a list of directories.")
+
+ if not self.enable_queue and self.progress_tracking:
+ raise ValueError("Progress tracking requires queuing to be enabled.")
+
+ for dep in self.dependencies:
+ for i in dep["cancels"]:
+ if not self.queue_enabled_for_fn(i):
+ raise ValueError(
+ "In order to cancel an event, the queue for that event must be enabled! "
+ "You may get this error by either 1) passing a function that uses the yield keyword "
+ "into an interface without enabling the queue or 2) defining an event that cancels "
+ "another event without enabling the queue. Both can be solved by calling .queue() "
+ "before .launch()"
+ )
+ if dep["batch"] and (
+ dep["queue"] is False
+ or (dep["queue"] is None and not self.enable_queue)
+ ):
+ raise ValueError("In order to use batching, the queue must be enabled.")
+
+ self.config = self.get_config_file()
+ self.max_threads = max(
+ self._queue.max_thread_count if self.enable_queue else 0, max_threads
+ )
+
+ if self.is_running:
+ assert isinstance(
+ self.local_url, str
+ ), f"Invalid local_url: {self.local_url}"
+ if not (quiet):
+ print(
+ "Rerunning server... use `close()` to stop if you need to change `launch()` parameters.\n----"
+ )
+ else:
+ server_name, server_port, local_url, app, server = networking.start_server(
+ self,
+ server_name,
+ server_port,
+ ssl_keyfile,
+ ssl_certfile,
+ ssl_keyfile_password,
+ )
+ self.server_name = server_name
+ self.local_url = local_url
+ self.server_port = server_port
+ self.server_app = app
+ self.server = server
+ self.is_running = True
+ self.is_colab = utils.colab_check()
+ self.is_kaggle = utils.kaggle_check()
+ self.is_sagemaker = utils.sagemaker_check()
+
+ self.protocol = (
+ "https"
+ if self.local_url.startswith("https") or self.is_colab
+ else "http"
+ )
+
+ if self.enable_queue:
+ self._queue.set_url(self.local_url)
+
+ # Cannot run async functions in background other than app's scope.
+ # Workaround by triggering the app endpoint
+ requests.get(f"{self.local_url}startup-events")
+
+ utils.launch_counter()
+
+ if share is None:
+ if self.is_colab and self.enable_queue:
+ if not quiet:
+ print(
+ "Setting queue=True in a Colab notebook requires sharing enabled. Setting `share=True` (you can turn this off by setting `share=False` in `launch()` explicitly).\n"
+ )
+ self.share = True
+ elif self.is_kaggle:
+ if not quiet:
+ print(
+ "Kaggle notebooks require sharing enabled. Setting `share=True` (you can turn this off by setting `share=False` in `launch()` explicitly).\n"
+ )
+ self.share = True
+ elif self.is_sagemaker:
+ if not quiet:
+ print(
+ "Sagemaker notebooks may require sharing enabled. Setting `share=True` (you can turn this off by setting `share=False` in `launch()` explicitly).\n"
+ )
+ self.share = True
+ else:
+ self.share = False
+ else:
+ self.share = share
+
+ # If running in a colab or not able to access localhost,
+ # a shareable link must be created.
+ if _frontend and (not networking.url_ok(self.local_url)) and (not self.share):
+ raise ValueError(
+ "When localhost is not accessible, a shareable link must be created. Please set share=True."
+ )
+
+ if self.is_colab:
+ if not quiet:
+ if debug:
+ print(strings.en["COLAB_DEBUG_TRUE"])
+ else:
+ print(strings.en["COLAB_DEBUG_FALSE"])
+ if not self.share:
+ print(strings.en["COLAB_WARNING"].format(self.server_port))
+ if self.enable_queue and not self.share:
+ raise ValueError(
+ "When using queueing in Colab, a shareable link must be created. Please set share=True."
+ )
+ else:
+ print(
+ strings.en["RUNNING_LOCALLY_SEPARATED"].format(
+ self.protocol, self.server_name, self.server_port
+ )
+ )
+
+ if self.share:
+ if self.is_space:
+ raise RuntimeError("Share is not supported when you are in Spaces")
+ try:
+ if self.share_url is None:
+ self.share_url = networking.setup_tunnel(
+ self.server_name, self.server_port, self.share_token
+ )
+ print(strings.en["SHARE_LINK_DISPLAY"].format(self.share_url))
+ if not (quiet):
+ print(strings.en["SHARE_LINK_MESSAGE"])
+ except (RuntimeError, requests.exceptions.ConnectionError):
+ if self.analytics_enabled:
+ utils.error_analytics("Not able to set up tunnel")
+ self.share_url = None
+ self.share = False
+ print(strings.en["COULD_NOT_GET_SHARE_LINK"])
+ else:
+ if not (quiet):
+ print(strings.en["PUBLIC_SHARE_TRUE"])
+ self.share_url = None
+
+ if inbrowser:
+ link = self.share_url if self.share and self.share_url else self.local_url
+ webbrowser.open(link)
+
+ # Check if running in a Python notebook in which case, display inline
+ if inline is None:
+ inline = utils.ipython_check() and (self.auth is None)
+ if inline:
+ if self.auth is not None:
+ print(
+ "Warning: authentication is not supported inline. Please"
+ "click the link to access the interface in a new tab."
+ )
+ try:
+ from IPython.display import HTML, Javascript, display # type: ignore
+
+ if self.share and self.share_url:
+ while not networking.url_ok(self.share_url):
+ time.sleep(0.25)
+ display(
+ HTML(
+ f'
+ `;
+ element.appendChild(external_link);
+
+ const iframe = document.createElement('iframe');
+ iframe.src = new URL(path, url).toString();
+ iframe.height = height;
+ iframe.allow = "autoplay; camera; microphone; clipboard-read; clipboard-write;"
+ iframe.width = width;
+ iframe.style.border = 0;
+ element.appendChild(iframe);
+ })""" + "({port}, {path}, {width}, {height}, {cache}, window.element)".format(
+ port=json.dumps(self.server_port),
+ path=json.dumps("/"),
+ width=json.dumps(self.width),
+ height=json.dumps(self.height),
+ cache=json.dumps(False),
+ )
+
+ display(Javascript(code))
+ else:
+ display(
+ HTML(
+ f''
+ )
+ )
+ except ImportError:
+ pass
+
+ if getattr(self, "analytics_enabled", False):
+ data = {
+ "launch_method": "browser" if inbrowser else "inline",
+ "is_google_colab": self.is_colab,
+ "is_sharing_on": self.share,
+ "share_url": self.share_url,
+ "enable_queue": self.enable_queue,
+ "show_tips": self.show_tips,
+ "server_name": server_name,
+ "server_port": server_port,
+ "is_spaces": self.is_space,
+ "mode": self.mode,
+ }
+ utils.launch_analytics(data)
+ utils.launched_telemetry(self, data)
+
+ utils.show_tip(self)
+
+ # Block main thread if debug==True
+ if debug or int(os.getenv("GRADIO_DEBUG", 0)) == 1:
+ self.block_thread()
+ # Block main thread if running in a script to stop script from exiting
+ is_in_interactive_mode = bool(getattr(sys, "ps1", sys.flags.interactive))
+
+ if not prevent_thread_lock and not is_in_interactive_mode:
+ self.block_thread()
+
+ return TupleNoPrint((self.server_app, self.local_url, self.share_url))
+
+ def integrate(
+ self,
+ comet_ml: comet_ml.Experiment | None = None,
+ wandb: ModuleType | None = None,
+ mlflow: ModuleType | None = None,
+ ) -> None:
+ """
+ A catch-all method for integrating with other libraries. This method should be run after launch()
+ Parameters:
+ comet_ml: If a comet_ml Experiment object is provided, will integrate with the experiment and appear on Comet dashboard
+ wandb: If the wandb module is provided, will integrate with it and appear on WandB dashboard
+ mlflow: If the mlflow module is provided, will integrate with the experiment and appear on ML Flow dashboard
+ """
+ analytics_integration = ""
+ if comet_ml is not None:
+ analytics_integration = "CometML"
+ comet_ml.log_other("Created from", "Gradio")
+ if self.share_url is not None:
+ comet_ml.log_text("gradio: " + self.share_url)
+ comet_ml.end()
+ elif self.local_url:
+ comet_ml.log_text("gradio: " + self.local_url)
+ comet_ml.end()
+ else:
+ raise ValueError("Please run `launch()` first.")
+ if wandb is not None:
+ analytics_integration = "WandB"
+ if self.share_url is not None:
+ wandb.log(
+ {
+ "Gradio panel": wandb.Html(
+ ''
+ )
+ }
+ )
+ else:
+ print(
+ "The WandB integration requires you to "
+ "`launch(share=True)` first."
+ )
+ if mlflow is not None:
+ analytics_integration = "MLFlow"
+ if self.share_url is not None:
+ mlflow.log_param("Gradio Interface Share Link", self.share_url)
+ else:
+ mlflow.log_param("Gradio Interface Local Link", self.local_url)
+ if self.analytics_enabled and analytics_integration:
+ data = {"integration": analytics_integration}
+ utils.integration_analytics(data)
+
+ def close(self, verbose: bool = True) -> None:
+ """
+ Closes the Interface that was launched and frees the port.
+ """
+ try:
+ if self.enable_queue:
+ self._queue.close()
+ self.server.close()
+ self.is_running = False
+ # So that the startup events (starting the queue)
+ # happen the next time the app is launched
+ self.app.startup_events_triggered = False
+ if verbose:
+ print("Closing server running on port: {}".format(self.server_port))
+ except (AttributeError, OSError): # can't close if not running
+ pass
+
+ def block_thread(
+ self,
+ ) -> None:
+ """Block main thread until interrupted by user."""
+ try:
+ while True:
+ time.sleep(0.1)
+ except (KeyboardInterrupt, OSError):
+ print("Keyboard interruption in main thread... closing server.")
+ self.server.close()
+ for tunnel in CURRENT_TUNNELS:
+ tunnel.kill()
+
+ def attach_load_events(self):
+ """Add a load event for every component whose initial value should be randomized."""
+ if Context.root_block:
+ for component in Context.root_block.blocks.values():
+ if (
+ isinstance(component, components.IOComponent)
+ and component.load_event_to_attach
+ ):
+ load_fn, every = component.load_event_to_attach
+ # Use set_event_trigger to avoid ambiguity between load class/instance method
+ dep = self.set_event_trigger(
+ "load",
+ load_fn,
+ None,
+ component,
+ no_target=True,
+ # If every is None, for sure skip the queue
+ # else, let the enable_queue parameter take precedence
+ # this will raise a nice error message is every is used
+ # without queue
+ queue=False if every is None else None,
+ every=every,
+ )[0]
+ component.load_event = dep
+
+ def startup_events(self):
+ """Events that should be run when the app containing this block starts up."""
+
+ if self.enable_queue:
+ utils.run_coro_in_background(self._queue.start, (self.progress_tracking,))
+ # So that processing can resume in case the queue was stopped
+ self._queue.stopped = False
+ utils.run_coro_in_background(self.create_limiter)
+
+ def queue_enabled_for_fn(self, fn_index: int):
+ if self.dependencies[fn_index]["queue"] is None:
+ return self.enable_queue
+ return self.dependencies[fn_index]["queue"]
diff --git a/gradio/components.py b/gradio/components.py
new file mode 100644
index 0000000000000000000000000000000000000000..c3264c46ca5be895faeab7a26f548bf3be5a3117
--- /dev/null
+++ b/gradio/components.py
@@ -0,0 +1,5837 @@
+"""Contains all of the components that can be used with Gradio Interface / Blocks.
+Along with the docs for each component, you can find the names of example demos that use
+each component. These demos are located in the `demo` directory."""
+
+from __future__ import annotations
+
+import inspect
+import json
+import math
+import operator
+import random
+import tempfile
+import uuid
+import warnings
+from copy import deepcopy
+from enum import Enum
+from pathlib import Path
+from types import ModuleType
+from typing import TYPE_CHECKING, Any, Callable, Dict, List, Tuple, Type
+
+import altair as alt
+import matplotlib.figure
+import numpy as np
+import pandas as pd
+import PIL
+import PIL.ImageOps
+from ffmpy import FFmpeg
+from pandas.api.types import is_numeric_dtype
+from PIL import Image as _Image # using _ to minimize namespace pollution
+from typing_extensions import Literal
+
+from gradio import media_data, processing_utils, utils
+from gradio.blocks import Block, BlockContext
+from gradio.documentation import document, set_documentation_group
+from gradio.events import (
+ Blurrable,
+ Changeable,
+ Clearable,
+ Clickable,
+ Editable,
+ EventListener,
+ EventListenerMethod,
+ Playable,
+ Releaseable,
+ Selectable,
+ Streamable,
+ Submittable,
+ Uploadable,
+)
+from gradio.interpretation import NeighborInterpretable, TokenInterpretable
+from gradio.layouts import Column, Form, Row
+from gradio.processing_utils import TempFileManager
+from gradio.serializing import (
+ FileSerializable,
+ ImgSerializable,
+ JSONSerializable,
+ Serializable,
+ SimpleSerializable,
+)
+
+if TYPE_CHECKING:
+ from typing import TypedDict
+
+ class DataframeData(TypedDict):
+ headers: List[str]
+ data: List[List[str | int | bool]]
+
+
+set_documentation_group("component")
+_Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843
+
+
+class _Keywords(Enum):
+ NO_VALUE = "NO_VALUE" # Used as a sentinel to determine if nothing is provided as a argument for `value` in `Component.update()`
+ FINISHED_ITERATING = "FINISHED_ITERATING" # Used to skip processing of a component's value (needed for generators + state)
+
+
+class Component(Block):
+ """
+ A base class for defining the methods that all gradio components should have.
+ """
+
+ def __init__(self, *args, **kwargs):
+ Block.__init__(self, *args, **kwargs)
+ EventListener.__init__(self)
+
+ def __str__(self):
+ return self.__repr__()
+
+ def __repr__(self):
+ return f"{self.get_block_name()}"
+
+ def get_config(self):
+ """
+ :return: a dictionary with context variables for the javascript file associated with the context
+ """
+ return {
+ "name": self.get_block_name(),
+ **super().get_config(),
+ }
+
+ def preprocess(self, x: Any) -> Any:
+ """
+ Any preprocessing needed to be performed on function input.
+ """
+ return x
+
+ def postprocess(self, y):
+ """
+ Any postprocessing needed to be performed on function output.
+ """
+ return y
+
+ def style(
+ self,
+ *,
+ container: bool | None = None,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the component.
+ Parameters:
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ """
+ put_deprecated_params_in_box = False
+ if "rounded" in kwargs:
+ warnings.warn(
+ "'rounded' styling is no longer supported. To round adjacent components together, place them in a Column(variant='box')."
+ )
+ if isinstance(kwargs["rounded"], list) or isinstance(
+ kwargs["rounded"], tuple
+ ):
+ put_deprecated_params_in_box = True
+ kwargs.pop("rounded")
+ if "margin" in kwargs:
+ warnings.warn(
+ "'margin' styling is no longer supported. To place adjacent components together without margin, place them in a Column(variant='box')."
+ )
+ if isinstance(kwargs["margin"], list) or isinstance(
+ kwargs["margin"], tuple
+ ):
+ put_deprecated_params_in_box = True
+ kwargs.pop("margin")
+ if "border" in kwargs:
+ warnings.warn(
+ "'border' styling is no longer supported. To place adjacent components in a shared border, place them in a Column(variant='box')."
+ )
+ kwargs.pop("border")
+ if container is not None:
+ self._style["container"] = container
+ if len(kwargs):
+ for key in kwargs:
+ warnings.warn(f"Unknown style parameter: {key}")
+ if put_deprecated_params_in_box and isinstance(self.parent, (Row, Column)):
+ if self.parent.variant == "default":
+ self.parent.variant = "compact"
+ return self
+
+
+class IOComponent(Component, Serializable):
+ """
+ A base class for defining methods that all input/output components should have.
+ """
+
+ def __init__(
+ self,
+ *,
+ value: Any = None,
+ label: str | None = None,
+ info: str | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ load_fn: Callable | None = None,
+ every: float | None = None,
+ **kwargs,
+ ):
+ Component.__init__(
+ self, elem_id=elem_id, elem_classes=elem_classes, visible=visible, **kwargs
+ )
+
+ self.label = label
+ self.info = info
+ self.show_label = show_label
+ self.interactive = interactive
+
+ # load_event is set in the Blocks.attach_load_events method
+ self.load_event: None | Dict[str, Any] = None
+ self.load_event_to_attach = None
+ load_fn, initial_value = self.get_load_fn_and_initial_value(value)
+ self.value = (
+ initial_value
+ if self._skip_init_processing
+ else self.postprocess(initial_value)
+ )
+ if callable(load_fn):
+ self.attach_load_event(load_fn, every)
+
+ def get_config(self):
+ config = {
+ "label": self.label,
+ "show_label": self.show_label,
+ "interactive": self.interactive,
+ **super().get_config(),
+ }
+ if self.info:
+ config["info"] = self.info
+ return config
+
+ @staticmethod
+ def get_load_fn_and_initial_value(value):
+ if callable(value):
+ initial_value = value()
+ load_fn = value
+ else:
+ initial_value = value
+ load_fn = None
+ return load_fn, initial_value
+
+ def attach_load_event(self, callable: Callable, every: float | None):
+ """Add a load event that runs `callable`, optionally every `every` seconds."""
+ self.load_event_to_attach = (callable, every)
+
+ def as_example(self, input_data):
+ """Return the input data in a way that can be displayed by the examples dataset component in the front-end."""
+ return input_data
+
+
+class FormComponent:
+ def get_expected_parent(self) -> Type[Form]:
+ return Form
+
+
+@document("style")
+class Textbox(
+ FormComponent,
+ Changeable,
+ Selectable,
+ Submittable,
+ Blurrable,
+ IOComponent,
+ SimpleSerializable,
+ TokenInterpretable,
+):
+ """
+ Creates a textarea for user to enter string input or display string output.
+ Preprocessing: passes textarea value as a {str} into the function.
+ Postprocessing: expects a {str} returned from function and sets textarea value to it.
+ Examples-format: a {str} representing the textbox input.
+
+ Demos: hello_world, diff_texts, sentence_builder
+ Guides: creating_a_chatbot, real_time_speech_recognition
+ """
+
+ def __init__(
+ self,
+ value: str | Callable | None = "",
+ *,
+ lines: int = 1,
+ max_lines: int = 20,
+ placeholder: str | None = None,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ type: str = "text",
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: default text to provide in textarea. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ lines: minimum number of line rows to provide in textarea.
+ max_lines: maximum number of line rows to provide in textarea.
+ placeholder: placeholder hint to provide behind textarea.
+ label: component name in interface.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, will be rendered as an editable textbox; if False, editing will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ type: The type of textbox. One of: 'text', 'password', 'email', Default is 'text'.
+ """
+ if type not in ["text", "password", "email"]:
+ raise ValueError('`type` must be one of "text", "password", or "email".')
+
+ #
+ self.lines = lines
+ self.max_lines = max_lines if type == "text" else 1
+ self.placeholder = placeholder
+ self.select: EventListenerMethod
+ """
+ Event listener for when the user selects text in the Textbox.
+ Uses event data gradio.SelectData to carry `value` referring to selected subtring, and `index` tuple referring to selected range endpoints.
+ See EventData documentation on how to use this event data.
+ """
+ IOComponent.__init__(
+ self,
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+ TokenInterpretable.__init__(self)
+ self.cleared_value = ""
+ self.test_input = value
+ self.type = type
+
+ def get_config(self):
+ return {
+ "lines": self.lines,
+ "max_lines": self.max_lines,
+ "placeholder": self.placeholder,
+ "value": self.value,
+ "type": self.type,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: str | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ lines: int | None = None,
+ max_lines: int | None = None,
+ placeholder: str | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ interactive: bool | None = None,
+ type: str | None = None,
+ ):
+ return {
+ "lines": lines,
+ "max_lines": max_lines,
+ "placeholder": placeholder,
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "type": type,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(self, x: str | None) -> str | None:
+ """
+ Preprocesses input (converts it to a string) before passing it to the function.
+ Parameters:
+ x: text
+ Returns:
+ text
+ """
+ return None if x is None else str(x)
+
+ def postprocess(self, y: str | None) -> str | None:
+ """
+ Postproccess the function output y by converting it to a str before passing it to the frontend.
+ Parameters:
+ y: function output to postprocess.
+ Returns:
+ text
+ """
+ return None if y is None else str(y)
+
+ def set_interpret_parameters(
+ self, separator: str = " ", replacement: str | None = None
+ ):
+ """
+ Calculates interpretation score of characters in input by splitting input into tokens, then using a "leave one out" method to calculate the score of each token by removing each token and measuring the delta of the output value.
+ Parameters:
+ separator: Separator to use to split input into tokens.
+ replacement: In the "leave one out" step, the text that the token should be replaced with. If None, the token is removed altogether.
+ """
+ self.interpretation_separator = separator
+ self.interpretation_replacement = replacement
+ return self
+
+ def tokenize(self, x: str) -> Tuple[List[str], List[str], None]:
+ """
+ Tokenizes an input string by dividing into "words" delimited by self.interpretation_separator
+ """
+ tokens = x.split(self.interpretation_separator)
+ leave_one_out_strings = []
+ for index in range(len(tokens)):
+ leave_one_out_set = list(tokens)
+ if self.interpretation_replacement is None:
+ leave_one_out_set.pop(index)
+ else:
+ leave_one_out_set[index] = self.interpretation_replacement
+ leave_one_out_strings.append(
+ self.interpretation_separator.join(leave_one_out_set)
+ )
+ return tokens, leave_one_out_strings, None
+
+ def get_masked_inputs(
+ self, tokens: List[str], binary_mask_matrix: List[List[int]]
+ ) -> List[str]:
+ """
+ Constructs partially-masked sentences for SHAP interpretation
+ """
+ masked_inputs = []
+ for binary_mask_vector in binary_mask_matrix:
+ masked_input = np.array(tokens)[np.array(binary_mask_vector, dtype=bool)]
+ masked_inputs.append(self.interpretation_separator.join(masked_input))
+ return masked_inputs
+
+ def get_interpretation_scores(
+ self, x, neighbors, scores: List[float], tokens: List[str], masks=None, **kwargs
+ ) -> List[Tuple[str, float]]:
+ """
+ Returns:
+ Each tuple set represents a set of characters and their corresponding interpretation score.
+ """
+ result = []
+ for token, score in zip(tokens, scores):
+ result.append((token, score))
+ result.append((self.interpretation_separator, 0))
+ return result
+
+ def style(
+ self,
+ *,
+ show_copy_button: bool | None = None,
+ container: bool | None = None,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the Textbox component.
+ Parameters:
+ show_copy_button: If True, includes a copy button to copy the text in the textbox. Only applies if show_label is True.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ """
+ if show_copy_button is not None:
+ self._style["show_copy_button"] = show_copy_button
+
+ return Component.style(self, container=container, **kwargs)
+
+
+@document("style")
+class Number(
+ FormComponent,
+ Changeable,
+ Submittable,
+ Blurrable,
+ IOComponent,
+ SimpleSerializable,
+ NeighborInterpretable,
+):
+ """
+ Creates a numeric field for user to enter numbers as input or display numeric output.
+ Preprocessing: passes field value as a {float} or {int} into the function, depending on `precision`.
+ Postprocessing: expects an {int} or {float} returned from the function and sets field value to it.
+ Examples-format: a {float} or {int} representing the number's value.
+
+ Demos: tax_calculator, titanic_survival, blocks_simple_squares
+ """
+
+ def __init__(
+ self,
+ value: float | Callable | None = None,
+ *,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ precision: int | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: default value. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: component name in interface.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, will be editable; if False, editing will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ precision: Precision to round input/output to. If set to 0, will round to nearest integer and convert type to int. If None, no rounding happens.
+ """
+ self.precision = precision
+ IOComponent.__init__(
+ self,
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+ NeighborInterpretable.__init__(self)
+ self.test_input = self.value if self.value is not None else 1
+
+ @staticmethod
+ def _round_to_precision(num: float | int, precision: int | None) -> float | int:
+ """
+ Round to a given precision.
+
+ If precision is None, no rounding happens. If 0, num is converted to int.
+
+ Parameters:
+ num: Number to round.
+ precision: Precision to round to.
+ Returns:
+ rounded number
+ """
+ if precision is None:
+ return float(num)
+ elif precision == 0:
+ return int(round(num, precision))
+ else:
+ return round(num, precision)
+
+ def get_config(self):
+ return {
+ "value": self.value,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: float | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(self, x: float | None) -> float | None:
+ """
+ Parameters:
+ x: numeric input
+ Returns:
+ number representing function input
+ """
+ if x is None:
+ return None
+ return self._round_to_precision(x, self.precision)
+
+ def postprocess(self, y: float | None) -> float | None:
+ """
+ Any postprocessing needed to be performed on function output.
+
+ Parameters:
+ y: numeric output
+ Returns:
+ number representing function output
+ """
+ if y is None:
+ return None
+ return self._round_to_precision(y, self.precision)
+
+ def set_interpret_parameters(
+ self, steps: int = 3, delta: float = 1, delta_type: str = "percent"
+ ):
+ """
+ Calculates interpretation scores of numeric values close to the input number.
+ Parameters:
+ steps: Number of nearby values to measure in each direction (above and below the input number).
+ delta: Size of step in each direction between nearby values.
+ delta_type: "percent" if delta step between nearby values should be a calculated as a percent, or "absolute" if delta should be a constant step change.
+ """
+ self.interpretation_steps = steps
+ self.interpretation_delta = delta
+ self.interpretation_delta_type = delta_type
+ return self
+
+ def get_interpretation_neighbors(self, x: float | int) -> Tuple[List[float], Dict]:
+ x = self._round_to_precision(x, self.precision)
+ if self.interpretation_delta_type == "percent":
+ delta = 1.0 * self.interpretation_delta * x / 100
+ elif self.interpretation_delta_type == "absolute":
+ delta = self.interpretation_delta
+ else:
+ delta = self.interpretation_delta
+ if self.precision == 0 and math.floor(delta) != delta:
+ raise ValueError(
+ f"Delta value {delta} is not an integer and precision=0. Cannot generate valid set of neighbors. "
+ "If delta_type='percent', pick a value of delta such that x * delta is an integer. "
+ "If delta_type='absolute', pick a value of delta that is an integer."
+ )
+ # run_interpretation will preprocess the neighbors so no need to convert to int here
+ negatives = (
+ np.array(x) + np.arange(-self.interpretation_steps, 0) * delta
+ ).tolist()
+ positives = (
+ np.array(x) + np.arange(1, self.interpretation_steps + 1) * delta
+ ).tolist()
+ return negatives + positives, {}
+
+ def get_interpretation_scores(
+ self, x: float, neighbors: List[float], scores: List[float | None], **kwargs
+ ) -> List[Tuple[float, float | None]]:
+ """
+ Returns:
+ Each tuple set represents a numeric value near the input and its corresponding interpretation score.
+ """
+ interpretation = list(zip(neighbors, scores))
+ interpretation.insert(int(len(interpretation) / 2), (x, None))
+ return interpretation
+
+
+@document("style")
+class Slider(
+ FormComponent,
+ Changeable,
+ Releaseable,
+ IOComponent,
+ SimpleSerializable,
+ NeighborInterpretable,
+):
+ """
+ Creates a slider that ranges from `minimum` to `maximum` with a step size of `step`.
+ Preprocessing: passes slider value as a {float} into the function.
+ Postprocessing: expects an {int} or {float} returned from function and sets slider value to it as long as it is within range.
+ Examples-format: A {float} or {int} representing the slider's value.
+
+ Demos: sentence_builder, slider_release, generate_tone, titanic_survival, interface_random_slider, blocks_random_slider
+ Guides: create_your_own_friends_with_a_gan
+ """
+
+ def __init__(
+ self,
+ minimum: float = 0,
+ maximum: float = 100,
+ value: float | Callable | None = None,
+ *,
+ step: float | None = None,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ randomize: bool = False,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ minimum: minimum value for slider.
+ maximum: maximum value for slider.
+ value: default value. If callable, the function will be called whenever the app loads to set the initial value of the component. Ignored if randomized=True.
+ step: increment between slider values.
+ label: component name in interface.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, slider will be adjustable; if False, adjusting will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ randomize: If True, the value of the slider when the app loads is taken uniformly at random from the range given by the minimum and maximum.
+ """
+ self.minimum = minimum
+ self.maximum = maximum
+ if step is None:
+ difference = maximum - minimum
+ power = math.floor(math.log10(difference) - 2)
+ self.step = 10**power
+ else:
+ self.step = step
+ if randomize:
+ value = self.get_random_value
+ IOComponent.__init__(
+ self,
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+ NeighborInterpretable.__init__(self)
+ self.cleared_value = self.value
+ self.test_input = self.value
+
+ def get_config(self):
+ return {
+ "minimum": self.minimum,
+ "maximum": self.maximum,
+ "step": self.step,
+ "value": self.value,
+ **IOComponent.get_config(self),
+ }
+
+ def get_random_value(self):
+ n_steps = int((self.maximum - self.minimum) / self.step)
+ step = random.randint(0, n_steps)
+ value = self.minimum + step * self.step
+ # Round to number of decimals in step so that UI doesn't display long decimals
+ n_decimals = max(str(self.step)[::-1].find("."), 0)
+ if n_decimals:
+ value = round(value, n_decimals)
+ return value
+
+ @staticmethod
+ def update(
+ value: float | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ minimum: float | None = None,
+ maximum: float | None = None,
+ step: float | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "minimum": minimum,
+ "maximum": maximum,
+ "step": step,
+ "label": label,
+ "show_label": show_label,
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def postprocess(self, y: float | None) -> float | None:
+ """
+ Any postprocessing needed to be performed on function output.
+ Parameters:
+ y: numeric output
+ Returns:
+ numeric output or minimum number if None
+ """
+ return self.minimum if y is None else y
+
+ def set_interpret_parameters(self, steps: int = 8) -> "Slider":
+ """
+ Calculates interpretation scores of numeric values ranging between the minimum and maximum values of the slider.
+ Parameters:
+ steps: Number of neighboring values to measure between the minimum and maximum values of the slider range.
+ """
+ self.interpretation_steps = steps
+ return self
+
+ def get_interpretation_neighbors(self, x) -> Tuple[object, dict]:
+ return (
+ np.linspace(self.minimum, self.maximum, self.interpretation_steps).tolist(),
+ {},
+ )
+
+ def style(
+ self,
+ *,
+ container: bool | None = None,
+ ):
+ """
+ This method can be used to change the appearance of the slider.
+ Parameters:
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ """
+ Component.style(
+ self,
+ container=container,
+ )
+ return self
+
+
+@document("style")
+class Checkbox(
+ FormComponent,
+ Changeable,
+ Selectable,
+ IOComponent,
+ SimpleSerializable,
+ NeighborInterpretable,
+):
+ """
+ Creates a checkbox that can be set to `True` or `False`.
+
+ Preprocessing: passes the status of the checkbox as a {bool} into the function.
+ Postprocessing: expects a {bool} returned from the function and, if it is True, checks the checkbox.
+ Examples-format: a {bool} representing whether the box is checked.
+ Demos: sentence_builder, titanic_survival
+ """
+
+ def __init__(
+ self,
+ value: bool | Callable = False,
+ *,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: if True, checked by default. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: component name in interface.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, this checkbox can be checked; if False, checking will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.test_input = True
+ self.select: EventListenerMethod
+ """
+ Event listener for when the user selects or deselects Checkbox.
+ Uses event data gradio.SelectData to carry `value` referring to label of checkbox, and `selected` to refer to state of checkbox.
+ See EventData documentation on how to use this event data.
+ """
+ IOComponent.__init__(
+ self,
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+ NeighborInterpretable.__init__(self)
+
+ def get_config(self):
+ return {
+ "value": self.value,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: bool | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "label": label,
+ "show_label": show_label,
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def get_interpretation_neighbors(self, x):
+ return [not x], {}
+
+ def get_interpretation_scores(self, x, neighbors, scores, **kwargs):
+ """
+ Returns:
+ The first value represents the interpretation score if the input is False, and the second if the input is True.
+ """
+ if x:
+ return scores[0], None
+ else:
+ return None, scores[0]
+
+
+@document("style")
+class CheckboxGroup(
+ FormComponent,
+ Changeable,
+ Selectable,
+ IOComponent,
+ SimpleSerializable,
+ NeighborInterpretable,
+):
+ """
+ Creates a set of checkboxes of which a subset can be checked.
+ Preprocessing: passes the list of checked checkboxes as a {List[str]} or their indices as a {List[int]} into the function, depending on `type`.
+ Postprocessing: expects a {List[str]}, each element of which becomes a checked checkbox.
+ Examples-format: a {List[str]} representing the values to be checked.
+ Demos: sentence_builder, titanic_survival
+ """
+
+ def __init__(
+ self,
+ choices: List[str] | None = None,
+ *,
+ value: List[str] | str | Callable | None = None,
+ type: str = "value",
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ choices: list of options to select from.
+ value: default selected list of options. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ type: Type of value to be returned by component. "value" returns the list of strings of the choices selected, "index" returns the list of indicies of the choices selected.
+ label: component name in interface.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, choices in this checkbox group will be checkable; if False, checking will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.choices = choices or []
+ self.cleared_value = []
+ valid_types = ["value", "index"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ self.test_input = self.choices
+ self.select: EventListenerMethod
+ """
+ Event listener for when the user selects or deselects within CheckboxGroup.
+ Uses event data gradio.SelectData to carry `value` referring to label of selected checkbox, `index` to refer to index, and `selected` to refer to state of checkbox.
+ See EventData documentation on how to use this event data.
+ """
+ IOComponent.__init__(
+ self,
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+ NeighborInterpretable.__init__(self)
+
+ def get_config(self):
+ return {
+ "choices": self.choices,
+ "value": self.value,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: List[str]
+ | str
+ | Literal[_Keywords.NO_VALUE]
+ | None = _Keywords.NO_VALUE,
+ choices: List[str] | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "choices": choices,
+ "label": label,
+ "show_label": show_label,
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(self, x: List[str]) -> List[str] | List[int]:
+ """
+ Parameters:
+ x: list of selected choices
+ Returns:
+ list of selected choices as strings or indices within choice list
+ """
+ if self.type == "value":
+ return x
+ elif self.type == "index":
+ return [self.choices.index(choice) for choice in x]
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(self.type)
+ + ". Please choose from: 'value', 'index'."
+ )
+
+ def postprocess(self, y: List[str] | str | None) -> List[str]:
+ """
+ Any postprocessing needed to be performed on function output.
+ Parameters:
+ y: List of selected choices. If a single choice is selected, it can be passed in as a string
+ Returns:
+ List of selected choices
+ """
+ if y is None:
+ return []
+ if not isinstance(y, list):
+ y = [y]
+ return y
+
+ def get_interpretation_neighbors(self, x):
+ leave_one_out_sets = []
+ for choice in self.choices:
+ leave_one_out_set = list(x)
+ if choice in leave_one_out_set:
+ leave_one_out_set.remove(choice)
+ else:
+ leave_one_out_set.append(choice)
+ leave_one_out_sets.append(leave_one_out_set)
+ return leave_one_out_sets, {}
+
+ def get_interpretation_scores(self, x, neighbors, scores, **kwargs):
+ """
+ Returns:
+ For each tuple in the list, the first value represents the interpretation score if the input is False, and the second if the input is True.
+ """
+ final_scores = []
+ for choice, score in zip(self.choices, scores):
+ if choice in x:
+ score_set = [score, None]
+ else:
+ score_set = [None, score]
+ final_scores.append(score_set)
+ return final_scores
+
+ def style(
+ self,
+ *,
+ item_container: bool | None = None,
+ container: bool | None = None,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the CheckboxGroup.
+ Parameters:
+ item_container: If True, will place the items in a container.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ """
+ if item_container is not None:
+ self._style["item_container"] = item_container
+
+ Component.style(self, container=container, **kwargs)
+ return self
+
+
+@document("style")
+class Radio(
+ FormComponent,
+ Selectable,
+ Changeable,
+ IOComponent,
+ SimpleSerializable,
+ NeighborInterpretable,
+):
+ """
+ Creates a set of radio buttons of which only one can be selected.
+ Preprocessing: passes the value of the selected radio button as a {str} or its index as an {int} into the function, depending on `type`.
+ Postprocessing: expects a {str} corresponding to the value of the radio button to be selected.
+ Examples-format: a {str} representing the radio option to select.
+
+ Demos: sentence_builder, titanic_survival, blocks_essay
+ """
+
+ def __init__(
+ self,
+ choices: List[str] | None = None,
+ *,
+ value: str | Callable | None = None,
+ type: str = "value",
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ choices: list of options to select from.
+ value: the button selected by default. If None, no button is selected by default. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ type: Type of value to be returned by component. "value" returns the string of the choice selected, "index" returns the index of the choice selected.
+ label: component name in interface.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, choices in this radio group will be selectable; if False, selection will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.choices = choices or []
+ valid_types = ["value", "index"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ self.test_input = self.choices[0] if len(self.choices) else None
+ self.select: EventListenerMethod
+ """
+ Event listener for when the user selects Radio option.
+ Uses event data gradio.SelectData to carry `value` referring to label of selected option, and `index` to refer to index.
+ See EventData documentation on how to use this event data.
+ """
+ IOComponent.__init__(
+ self,
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+ NeighborInterpretable.__init__(self)
+ self.cleared_value = self.value
+
+ def get_config(self):
+ return {
+ "choices": self.choices,
+ "value": self.value,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ choices: List[str] | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "choices": choices,
+ "label": label,
+ "show_label": show_label,
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(self, x: str | None) -> str | int | None:
+ """
+ Parameters:
+ x: selected choice
+ Returns:
+ selected choice as string or index within choice list
+ """
+ if self.type == "value":
+ return x
+ elif self.type == "index":
+ if x is None:
+ return None
+ else:
+ return self.choices.index(x)
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(self.type)
+ + ". Please choose from: 'value', 'index'."
+ )
+
+ def get_interpretation_neighbors(self, x):
+ choices = list(self.choices)
+ choices.remove(x)
+ return choices, {}
+
+ def get_interpretation_scores(
+ self, x, neighbors, scores: List[float | None], **kwargs
+ ) -> List:
+ """
+ Returns:
+ Each value represents the interpretation score corresponding to each choice.
+ """
+ scores.insert(self.choices.index(x), None)
+ return scores
+
+ def style(
+ self,
+ *,
+ item_container: bool | None = None,
+ container: bool | None = None,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the radio component.
+ Parameters:
+ item_container: If True, will place items in a container.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ """
+ if item_container is not None:
+ self._style["item_container"] = item_container
+
+ Component.style(self, container=container, **kwargs)
+ return self
+
+
+@document("style")
+class Dropdown(Changeable, Selectable, IOComponent, SimpleSerializable, FormComponent):
+ """
+ Creates a dropdown of choices from which entries can be selected.
+ Preprocessing: passes the value of the selected dropdown entry as a {str} or its index as an {int} into the function, depending on `type`.
+ Postprocessing: expects a {str} corresponding to the value of the dropdown entry to be selected.
+ Examples-format: a {str} representing the drop down value to select.
+ Demos: sentence_builder, titanic_survival
+ """
+
+ def __init__(
+ self,
+ choices: str | List[str] | None = None,
+ *,
+ value: str | List[str] | Callable | None = None,
+ type: str = "value",
+ multiselect: bool | None = None,
+ max_choices: int | None = None,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ choices: list of options to select from.
+ value: default value(s) selected in dropdown. If None, no value is selected by default. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ type: Type of value to be returned by component. "value" returns the string of the choice selected, "index" returns the index of the choice selected.
+ multiselect: if True, multiple choices can be selected.
+ max_choices: maximum number of choices that can be selected. If None, no limit is enforced.
+ label: component name in interface.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, choices in this dropdown will be selectable; if False, selection will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.choices = choices or []
+ valid_types = ["value", "index"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ self.multiselect = multiselect
+ if multiselect:
+ if isinstance(value, str):
+ value = [value]
+ if not multiselect and max_choices is not None:
+ warnings.warn(
+ "The `max_choices` parameter is ignored when `multiselect` is False."
+ )
+ self.max_choices = max_choices
+ self.test_input = self.choices[0] if len(self.choices) else None
+ self.interpret_by_tokens = False
+ self.select: EventListenerMethod
+ """
+ Event listener for when the user selects Dropdown option.
+ Uses event data gradio.SelectData to carry `value` referring to label of selected option, and `index` to refer to index.
+ See EventData documentation on how to use this event data.
+ """
+ IOComponent.__init__(
+ self,
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ self.cleared_value = self.value or ([] if multiselect else "")
+
+ def get_config(self):
+ return {
+ "choices": self.choices,
+ "value": self.value,
+ "multiselect": self.multiselect,
+ "max_choices": self.max_choices,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ choices: str | List[str] | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "choices": choices,
+ "label": label,
+ "show_label": show_label,
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(
+ self, x: str | List[str]
+ ) -> str | int | List[str] | List[int] | None:
+ """
+ Parameters:
+ x: selected choice(s)
+ Returns:
+ selected choice(s) as string or index within choice list or list of string or indices
+ """
+ if self.type == "value":
+ return x
+ elif self.type == "index":
+ if x is None:
+ return None
+ elif self.multiselect:
+ return [self.choices.index(c) for c in x]
+ else:
+ if isinstance(x, str):
+ return self.choices.index(x)
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(self.type)
+ + ". Please choose from: 'value', 'index'."
+ )
+
+ def set_interpret_parameters(self):
+ """
+ Calculates interpretation score of each choice by comparing the output against each of the outputs when alternative choices are selected.
+ """
+ return self
+
+ def get_interpretation_neighbors(self, x):
+ choices = list(self.choices)
+ choices.remove(x)
+ return choices, {}
+
+ def get_interpretation_scores(
+ self, x, neighbors, scores: List[float | None], **kwargs
+ ) -> List:
+ """
+ Returns:
+ Each value represents the interpretation score corresponding to each choice.
+ """
+ scores.insert(self.choices.index(x), None)
+ return scores
+
+ def style(self, *, container: bool | None = None, **kwargs):
+ """
+ This method can be used to change the appearance of the Dropdown.
+ Parameters:
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ """
+ Component.style(self, container=container, **kwargs)
+ return self
+
+
+@document("style")
+class Image(
+ Editable,
+ Clearable,
+ Changeable,
+ Streamable,
+ Uploadable,
+ IOComponent,
+ ImgSerializable,
+ TokenInterpretable,
+):
+ """
+ Creates an image component that can be used to upload/draw images (as an input) or display images (as an output).
+ Preprocessing: passes the uploaded image as a {numpy.array}, {PIL.Image} or {str} filepath depending on `type` -- unless `tool` is `sketch` AND source is one of `upload` or `webcam`. In these cases, a {dict} with keys `image` and `mask` is passed, and the format of the corresponding values depends on `type`.
+ Postprocessing: expects a {numpy.array}, {PIL.Image} or {str} or {pathlib.Path} filepath to an image and displays the image.
+ Examples-format: a {str} filepath to a local file that contains the image.
+ Demos: image_mod, image_mod_default_image
+ Guides: Gradio_and_ONNX_on_Hugging_Face, image_classification_in_pytorch, image_classification_in_tensorflow, image_classification_with_vision_transformers, building_a_pictionary_app, create_your_own_friends_with_a_gan
+ """
+
+ def __init__(
+ self,
+ value: str | _Image.Image | np.ndarray | None = None,
+ *,
+ shape: Tuple[int, int] | None = None,
+ image_mode: str = "RGB",
+ invert_colors: bool = False,
+ source: str = "upload",
+ tool: str | None = None,
+ type: str = "numpy",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ streaming: bool = False,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ mirror_webcam: bool = True,
+ brush_radius: int | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: A PIL Image, numpy array, path or URL for the default value that Image component is going to take. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ shape: (width, height) shape to crop and resize image to; if None, matches input image size. Pass None for either width or height to only crop and resize the other.
+ image_mode: "RGB" if color, or "L" if black and white.
+ invert_colors: whether to invert the image as a preprocessing step.
+ source: Source of image. "upload" creates a box where user can drop an image file, "webcam" allows user to take snapshot from their webcam, "canvas" defaults to a white image that can be edited and drawn upon with tools.
+ tool: Tools used for editing. "editor" allows a full screen editor (and is the default if source is "upload" or "webcam"), "select" provides a cropping and zoom tool, "sketch" allows you to create a binary sketch (and is the default if source="canvas"), and "color-sketch" allows you to created a sketch in different colors. "color-sketch" can be used with source="upload" or "webcam" to allow sketching on an image. "sketch" can also be used with "upload" or "webcam" to create a mask over an image and in that case both the image and mask are passed into the function as a dictionary with keys "image" and "mask" respectively.
+ type: The format the image is converted to before being passed into the prediction function. "numpy" converts the image to a numpy array with shape (width, height, 3) and values from 0 to 255, "pil" converts the image to a PIL image object, "filepath" passes a str path to a temporary file containing the image.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, will allow users to upload and edit an image; if False, can only be used to display images. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ streaming: If True when used in a `live` interface, will automatically stream webcam feed. Only valid is source is 'webcam'.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ mirror_webcam: If True webcam will be mirrored. Default is True.
+ brush_radius: Size of the brush for Sketch. Default is None which chooses a sensible default
+ """
+ self.brush_radius = brush_radius
+ self.mirror_webcam = mirror_webcam
+ valid_types = ["numpy", "pil", "filepath"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ self.shape = shape
+ self.image_mode = image_mode
+ valid_sources = ["upload", "webcam", "canvas"]
+ if source not in valid_sources:
+ raise ValueError(
+ f"Invalid value for parameter `source`: {source}. Please choose from one of: {valid_sources}"
+ )
+ self.source = source
+ if tool is None:
+ self.tool = "sketch" if source == "canvas" else "editor"
+ else:
+ self.tool = tool
+ self.invert_colors = invert_colors
+ self.test_input = deepcopy(media_data.BASE64_IMAGE)
+ self.streaming = streaming
+ if streaming and source != "webcam":
+ raise ValueError("Image streaming only available if source is 'webcam'.")
+
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+ TokenInterpretable.__init__(self)
+
+ def get_config(self):
+ return {
+ "image_mode": self.image_mode,
+ "shape": self.shape,
+ "source": self.source,
+ "tool": self.tool,
+ "value": self.value,
+ "streaming": self.streaming,
+ "mirror_webcam": self.mirror_webcam,
+ "brush_radius": self.brush_radius,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ brush_radius: int | None = None,
+ ):
+ return {
+ "label": label,
+ "show_label": show_label,
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "brush_radius": brush_radius,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def _format_image(
+ self, im: _Image.Image | None
+ ) -> np.ndarray | _Image.Image | str | None:
+ """Helper method to format an image based on self.type"""
+ if im is None:
+ return im
+ fmt = im.format
+ if self.type == "pil":
+ return im
+ elif self.type == "numpy":
+ return np.array(im)
+ elif self.type == "filepath":
+ file_obj = tempfile.NamedTemporaryFile(
+ delete=False,
+ suffix=("." + fmt.lower() if fmt is not None else ".png"),
+ )
+ im.save(file_obj.name)
+ return file_obj.name
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(self.type)
+ + ". Please choose from: 'numpy', 'pil', 'filepath'."
+ )
+
+ def preprocess(
+ self, x: str | Dict[str, str]
+ ) -> np.ndarray | _Image.Image | str | Dict | None:
+ """
+ Parameters:
+ x: base64 url data, or (if tool == "sketch") a dict of image and mask base64 url data
+ Returns:
+ image in requested format, or (if tool == "sketch") a dict of image and mask in requested format
+ """
+ if x is None:
+ return x
+
+ mask = ""
+ if self.tool == "sketch" and self.source in ["upload", "webcam"]:
+ assert isinstance(x, dict)
+ x, mask = x["image"], x["mask"]
+
+ assert isinstance(x, str)
+ im = processing_utils.decode_base64_to_image(x)
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ im = im.convert(self.image_mode)
+ if self.shape is not None:
+ im = processing_utils.resize_and_crop(im, self.shape)
+ if self.invert_colors:
+ im = PIL.ImageOps.invert(im)
+ if (
+ self.source == "webcam"
+ and self.mirror_webcam is True
+ and self.tool != "color-sketch"
+ ):
+ im = PIL.ImageOps.mirror(im)
+
+ if self.tool == "sketch" and self.source in ["upload", "webcam"]:
+ mask_im = processing_utils.decode_base64_to_image(mask)
+ return {
+ "image": self._format_image(im),
+ "mask": self._format_image(mask_im),
+ }
+
+ return self._format_image(im)
+
+ def postprocess(
+ self, y: np.ndarray | _Image.Image | str | Path | None
+ ) -> str | None:
+ """
+ Parameters:
+ y: image as a numpy array, PIL Image, string/Path filepath, or string URL
+ Returns:
+ base64 url data
+ """
+ if y is None:
+ return None
+ if isinstance(y, np.ndarray):
+ return processing_utils.encode_array_to_base64(y)
+ elif isinstance(y, _Image.Image):
+ return processing_utils.encode_pil_to_base64(y)
+ elif isinstance(y, (str, Path)):
+ return processing_utils.encode_url_or_file_to_base64(y)
+ else:
+ raise ValueError("Cannot process this value as an Image")
+
+ def set_interpret_parameters(self, segments: int = 16):
+ """
+ Calculates interpretation score of image subsections by splitting the image into subsections, then using a "leave one out" method to calculate the score of each subsection by whiting out the subsection and measuring the delta of the output value.
+ Parameters:
+ segments: Number of interpretation segments to split image into.
+ """
+ self.interpretation_segments = segments
+ return self
+
+ def _segment_by_slic(self, x):
+ """
+ Helper method that segments an image into superpixels using slic.
+ Parameters:
+ x: base64 representation of an image
+ """
+ x = processing_utils.decode_base64_to_image(x)
+ if self.shape is not None:
+ x = processing_utils.resize_and_crop(x, self.shape)
+ resized_and_cropped_image = np.array(x)
+ try:
+ from skimage.segmentation import slic
+ except (ImportError, ModuleNotFoundError):
+ raise ValueError(
+ "Error: running this interpretation for images requires scikit-image, please install it first."
+ )
+ try:
+ segments_slic = slic(
+ resized_and_cropped_image,
+ self.interpretation_segments,
+ compactness=10,
+ sigma=1,
+ start_label=1,
+ )
+ except TypeError: # For skimage 0.16 and older
+ segments_slic = slic(
+ resized_and_cropped_image,
+ self.interpretation_segments,
+ compactness=10,
+ sigma=1,
+ )
+ return segments_slic, resized_and_cropped_image
+
+ def tokenize(self, x):
+ """
+ Segments image into tokens, masks, and leave-one-out-tokens
+ Parameters:
+ x: base64 representation of an image
+ Returns:
+ tokens: list of tokens, used by the get_masked_input() method
+ leave_one_out_tokens: list of left-out tokens, used by the get_interpretation_neighbors() method
+ masks: list of masks, used by the get_interpretation_neighbors() method
+ """
+ segments_slic, resized_and_cropped_image = self._segment_by_slic(x)
+ tokens, masks, leave_one_out_tokens = [], [], []
+ replace_color = np.mean(resized_and_cropped_image, axis=(0, 1))
+ for (i, segment_value) in enumerate(np.unique(segments_slic)):
+ mask = segments_slic == segment_value
+ image_screen = np.copy(resized_and_cropped_image)
+ image_screen[segments_slic == segment_value] = replace_color
+ leave_one_out_tokens.append(
+ processing_utils.encode_array_to_base64(image_screen)
+ )
+ token = np.copy(resized_and_cropped_image)
+ token[segments_slic != segment_value] = 0
+ tokens.append(token)
+ masks.append(mask)
+ return tokens, leave_one_out_tokens, masks
+
+ def get_masked_inputs(self, tokens, binary_mask_matrix):
+ masked_inputs = []
+ for binary_mask_vector in binary_mask_matrix:
+ masked_input = np.zeros_like(tokens[0], dtype=int)
+ for token, b in zip(tokens, binary_mask_vector):
+ masked_input = masked_input + token * int(b)
+ masked_inputs.append(processing_utils.encode_array_to_base64(masked_input))
+ return masked_inputs
+
+ def get_interpretation_scores(
+ self, x, neighbors, scores, masks, tokens=None, **kwargs
+ ) -> List[List[float]]:
+ """
+ Returns:
+ A 2D array representing the interpretation score of each pixel of the image.
+ """
+ x = processing_utils.decode_base64_to_image(x)
+ if self.shape is not None:
+ x = processing_utils.resize_and_crop(x, self.shape)
+ x = np.array(x)
+ output_scores = np.zeros((x.shape[0], x.shape[1]))
+
+ for score, mask in zip(scores, masks):
+ output_scores += score * mask
+
+ max_val, min_val = np.max(output_scores), np.min(output_scores)
+ if max_val > 0:
+ output_scores = (output_scores - min_val) / (max_val - min_val)
+ return output_scores.tolist()
+
+ def style(self, *, height: int | None = None, width: int | None = None, **kwargs):
+ """
+ This method can be used to change the appearance of the Image component.
+ Parameters:
+ height: Height of the image.
+ width: Width of the image.
+ """
+ self._style["height"] = height
+ self._style["width"] = width
+ Component.style(
+ self,
+ **kwargs,
+ )
+ return self
+
+ def stream(
+ self,
+ fn: Callable,
+ inputs: List[Component],
+ outputs: List[Component],
+ _js: str | None = None,
+ api_name: str | None = None,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ ):
+ """
+ This event is triggered when the user streams the component (e.g. a live webcam
+ component)
+ Parameters:
+ fn: Callable function
+ inputs: List of inputs
+ outputs: List of outputs
+ """
+ # js: Optional frontend js method to run before running 'fn'. Input arguments for js method are values of 'inputs' and 'outputs', return should be a list of values for output components.
+ if self.source != "webcam":
+ raise ValueError("Image streaming only available if source is 'webcam'.")
+ super().stream(
+ fn,
+ inputs,
+ outputs,
+ _js=_js,
+ api_name=api_name,
+ preprocess=preprocess,
+ postprocess=postprocess,
+ )
+
+ def as_example(self, input_data: str | None) -> str:
+ if input_data is None:
+ return ""
+ elif (
+ self.root_url
+ ): # If an externally hosted image, don't convert to absolute path
+ return input_data
+ return str(utils.abspath(input_data))
+
+
+@document("style")
+class Video(
+ Changeable,
+ Clearable,
+ Playable,
+ Uploadable,
+ IOComponent,
+ FileSerializable,
+ TempFileManager,
+):
+ """
+ Creates a video component that can be used to upload/record videos (as an input) or display videos (as an output).
+ For the video to be playable in the browser it must have a compatible container and codec combination. Allowed
+ combinations are .mp4 with h264 codec, .ogg with theora codec, and .webm with vp9 codec. If the component detects
+ that the output video would not be playable in the browser it will attempt to convert it to a playable mp4 video.
+ If the conversion fails, the original video is returned.
+ Preprocessing: passes the uploaded video as a {str} filepath or URL whose extension can be modified by `format`.
+ Postprocessing: expects a {str} filepath to a video which is displayed.
+ Examples-format: a {str} filepath to a local file that contains the video.
+ Demos: video_identity
+ """
+
+ def __init__(
+ self,
+ value: str | Callable | None = None,
+ *,
+ format: str | None = None,
+ source: str = "upload",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ mirror_webcam: bool = True,
+ include_audio: bool | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: A path or URL for the default value that Video component is going to take. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ format: Format of video format to be returned by component, such as 'avi' or 'mp4'. Use 'mp4' to ensure browser playability. If set to None, video will keep uploaded format.
+ source: Source of video. "upload" creates a box where user can drop an video file, "webcam" allows user to record a video from their webcam.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, will allow users to upload a video; if False, can only be used to display videos. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ mirror_webcam: If True webcam will be mirrored. Default is True.
+ include_audio: Whether the component should record/retain the audio track for a video. By default, audio is excluded for webcam videos and included for uploaded videos.
+ """
+ self.format = format
+ valid_sources = ["upload", "webcam"]
+ if source not in valid_sources:
+ raise ValueError(
+ f"Invalid value for parameter `source`: {source}. Please choose from one of: {valid_sources}"
+ )
+ self.source = source
+ self.mirror_webcam = mirror_webcam
+ self.include_audio = (
+ include_audio if include_audio is not None else source == "upload"
+ )
+ TempFileManager.__init__(self)
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "source": self.source,
+ "value": self.value,
+ "mirror_webcam": self.mirror_webcam,
+ "include_audio": self.include_audio,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ source: str | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "source": source,
+ "label": label,
+ "show_label": show_label,
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(self, x: Dict[str, str] | None) -> str | None:
+ """
+ Parameters:
+ x: a dictionary with the following keys: 'name' (containing the file path to a video), 'data' (with either the file URL or base64 representation of the video), and 'is_file` (True if `data` contains the file URL).
+ Returns:
+ a string file path to the preprocessed video
+ """
+ if x is None:
+ return x
+
+ file_name, file_data, is_file = (
+ x["name"],
+ x["data"],
+ x.get("is_file", False),
+ )
+ if is_file:
+ file_name = Path(self.make_temp_copy_if_needed(file_name))
+ else:
+ file_name = Path(self.base64_to_temp_file_if_needed(file_data, file_name))
+
+ uploaded_format = file_name.suffix.replace(".", "")
+ modify_format = self.format is not None and uploaded_format != self.format
+ flip = self.source == "webcam" and self.mirror_webcam
+ if modify_format or flip:
+ format = f".{self.format if modify_format else uploaded_format}"
+ output_options = ["-vf", "hflip", "-c:a", "copy"] if flip else []
+ output_options += ["-an"] if not self.include_audio else []
+ flip_suffix = "_flip" if flip else ""
+ output_file_name = str(
+ file_name.with_name(f"{file_name.stem}{flip_suffix}{format}")
+ )
+ if Path(output_file_name).exists():
+ return output_file_name
+ ff = FFmpeg(
+ inputs={str(file_name): None},
+ outputs={output_file_name: output_options},
+ )
+ ff.run()
+ return output_file_name
+ elif not self.include_audio:
+ output_file_name = str(file_name.with_name(f"muted_{file_name.name}"))
+ ff = FFmpeg(
+ inputs={str(file_name): None},
+ outputs={output_file_name: ["-an"]},
+ )
+ ff.run()
+ return output_file_name
+ else:
+ return str(file_name)
+
+ def postprocess(self, y: str | None) -> Dict[str, Any] | None:
+ """
+ Processes a video to ensure that it is in the correct format before
+ returning it to the front end.
+ Parameters:
+ y: a path or URL to the video file
+ Returns:
+ a dictionary with the following keys: 'name' (containing the file path
+ to a temporary copy of the video), 'data' (None), and 'is_file` (True).
+ """
+ if y is None:
+ return None
+
+ returned_format = y.split(".")[-1].lower()
+
+ if self.format is None or returned_format == self.format:
+ conversion_needed = False
+ else:
+ conversion_needed = True
+
+ # For cases where the video is a URL and does not need to be converted to another format, we can just return the URL
+ if utils.validate_url(y) and not (conversion_needed):
+ return {"name": y, "data": None, "is_file": True}
+
+ # For cases where the video needs to be converted to another format
+ if utils.validate_url(y):
+ y = self.download_temp_copy_if_needed(y)
+ if (
+ processing_utils.ffmpeg_installed()
+ and not processing_utils.video_is_playable(y)
+ ):
+ warnings.warn(
+ "Video does not have browser-compatible container or codec. Converting to mp4"
+ )
+ y = processing_utils.convert_video_to_playable_mp4(y)
+ if self.format is not None and returned_format != self.format:
+ output_file_name = y[0 : y.rindex(".") + 1] + self.format
+ ff = FFmpeg(inputs={y: None}, outputs={output_file_name: None})
+ ff.run()
+ y = output_file_name
+
+ y = self.make_temp_copy_if_needed(y)
+ return {"name": y, "data": None, "is_file": True}
+
+ def style(self, *, height: int | None = None, width: int | None = None, **kwargs):
+ """
+ This method can be used to change the appearance of the video component.
+ Parameters:
+ height: Height of the video.
+ width: Width of the video.
+ """
+ self._style["height"] = height
+ self._style["width"] = width
+ Component.style(
+ self,
+ **kwargs,
+ )
+ return self
+
+
+@document("style")
+class Audio(
+ Changeable,
+ Clearable,
+ Playable,
+ Streamable,
+ Uploadable,
+ IOComponent,
+ FileSerializable,
+ TempFileManager,
+ TokenInterpretable,
+):
+ """
+ Creates an audio component that can be used to upload/record audio (as an input) or display audio (as an output).
+ Preprocessing: passes the uploaded audio as a {Tuple(int, numpy.array)} corresponding to (sample rate, data) or as a {str} filepath, depending on `type`
+ Postprocessing: expects a {Tuple(int, numpy.array)} corresponding to (sample rate, data) or as a {str} filepath or URL to an audio file, which gets displayed
+ Examples-format: a {str} filepath to a local file that contains audio.
+ Demos: main_note, generate_tone, reverse_audio
+ Guides: real_time_speech_recognition
+ """
+
+ def __init__(
+ self,
+ value: str | Tuple[int, np.ndarray] | Callable | None = None,
+ *,
+ source: str = "upload",
+ type: str = "numpy",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ streaming: bool = False,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: A path, URL, or [sample_rate, numpy array] tuple for the default value that Audio component is going to take. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ source: Source of audio. "upload" creates a box where user can drop an audio file, "microphone" creates a microphone input.
+ type: The format the audio file is converted to before being passed into the prediction function. "numpy" converts the audio to a tuple consisting of: (int sample rate, numpy.array for the data), "filepath" passes a str path to a temporary file containing the audio.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, will allow users to upload and edit a audio file; if False, can only be used to play audio. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ streaming: If set to True when used in a `live` interface, will automatically stream webcam feed. Only valid is source is 'microphone'.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ valid_sources = ["upload", "microphone"]
+ if source not in valid_sources:
+ raise ValueError(
+ f"Invalid value for parameter `source`: {source}. Please choose from one of: {valid_sources}"
+ )
+ self.source = source
+ valid_types = ["numpy", "filepath"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ self.test_input = deepcopy(media_data.BASE64_AUDIO)
+ self.streaming = streaming
+ if streaming and source != "microphone":
+ raise ValueError(
+ "Audio streaming only available if source is 'microphone'."
+ )
+ TempFileManager.__init__(self)
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+ TokenInterpretable.__init__(self)
+
+ def get_config(self):
+ return {
+ "source": self.source,
+ "value": self.value,
+ "streaming": self.streaming,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ source: str | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "source": source,
+ "label": label,
+ "show_label": show_label,
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(
+ self, x: Dict[str, Any] | None
+ ) -> Tuple[int, np.ndarray] | str | None:
+ """
+ Parameters:
+ x: dictionary with keys "name", "data", "is_file", "crop_min", "crop_max".
+ Returns:
+ audio in requested format
+ """
+ if x is None:
+ return x
+ file_name, file_data, is_file = (
+ x["name"],
+ x["data"],
+ x.get("is_file", False),
+ )
+ crop_min, crop_max = x.get("crop_min", 0), x.get("crop_max", 100)
+ if is_file:
+ if utils.validate_url(file_name):
+ temp_file_path = self.download_temp_copy_if_needed(file_name)
+ else:
+ temp_file_path = self.make_temp_copy_if_needed(file_name)
+ else:
+ temp_file_path = self.base64_to_temp_file_if_needed(file_data, file_name)
+
+ sample_rate, data = processing_utils.audio_from_file(
+ temp_file_path, crop_min=crop_min, crop_max=crop_max
+ )
+
+ # Need a unique name for the file to avoid re-using the same audio file if
+ # a user submits the same audio file twice, but with different crop min/max.
+ temp_file_path = Path(temp_file_path)
+ output_file_name = str(
+ temp_file_path.with_name(
+ f"{temp_file_path.stem}-{crop_min}-{crop_max}{temp_file_path.suffix}"
+ )
+ )
+
+ if self.type == "numpy":
+ return sample_rate, data
+ elif self.type == "filepath":
+ processing_utils.audio_to_file(sample_rate, data, output_file_name)
+ return output_file_name
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(self.type)
+ + ". Please choose from: 'numpy', 'filepath'."
+ )
+
+ def set_interpret_parameters(self, segments: int = 8):
+ """
+ Calculates interpretation score of audio subsections by splitting the audio into subsections, then using a "leave one out" method to calculate the score of each subsection by removing the subsection and measuring the delta of the output value.
+ Parameters:
+ segments: Number of interpretation segments to split audio into.
+ """
+ self.interpretation_segments = segments
+ return self
+
+ def tokenize(self, x):
+ if x.get("is_file"):
+ sample_rate, data = processing_utils.audio_from_file(x["name"])
+ else:
+ file_name = self.base64_to_temp_file_if_needed(x["data"])
+ sample_rate, data = processing_utils.audio_from_file(file_name)
+ leave_one_out_sets = []
+ tokens = []
+ masks = []
+ duration = data.shape[0]
+ boundaries = np.linspace(0, duration, self.interpretation_segments + 1).tolist()
+ boundaries = [round(boundary) for boundary in boundaries]
+ for index in range(len(boundaries) - 1):
+ start, stop = boundaries[index], boundaries[index + 1]
+ masks.append((start, stop))
+
+ # Handle the leave one outs
+ leave_one_out_data = np.copy(data)
+ leave_one_out_data[start:stop] = 0
+ file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
+ processing_utils.audio_to_file(sample_rate, leave_one_out_data, file.name)
+ out_data = processing_utils.encode_file_to_base64(file.name)
+ leave_one_out_sets.append(out_data)
+ file.close()
+ Path(file.name).unlink()
+
+ # Handle the tokens
+ token = np.copy(data)
+ token[0:start] = 0
+ token[stop:] = 0
+ file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
+ processing_utils.audio_to_file(sample_rate, token, file.name)
+ token_data = processing_utils.encode_file_to_base64(file.name)
+ file.close()
+ Path(file.name).unlink()
+
+ tokens.append(token_data)
+ tokens = [{"name": "token.wav", "data": token} for token in tokens]
+ leave_one_out_sets = [
+ {"name": "loo.wav", "data": loo_set} for loo_set in leave_one_out_sets
+ ]
+ return tokens, leave_one_out_sets, masks
+
+ def get_masked_inputs(self, tokens, binary_mask_matrix):
+ # create a "zero input" vector and get sample rate
+ x = tokens[0]["data"]
+ file_name = self.base64_to_temp_file_if_needed(x)
+ sample_rate, data = processing_utils.audio_from_file(file_name)
+ zero_input = np.zeros_like(data, dtype="int16")
+ # decode all of the tokens
+ token_data = []
+ for token in tokens:
+ file_name = self.base64_to_temp_file_if_needed(token["data"])
+ _, data = processing_utils.audio_from_file(file_name)
+ token_data.append(data)
+ # construct the masked version
+ masked_inputs = []
+ for binary_mask_vector in binary_mask_matrix:
+ masked_input = np.copy(zero_input)
+ for t, b in zip(token_data, binary_mask_vector):
+ masked_input = masked_input + t * int(b)
+ file = tempfile.NamedTemporaryFile(delete=False)
+ processing_utils.audio_to_file(sample_rate, masked_input, file.name)
+ masked_data = processing_utils.encode_file_to_base64(file.name)
+ file.close()
+ Path(file.name).unlink()
+ masked_inputs.append(masked_data)
+ return masked_inputs
+
+ def postprocess(self, y: Tuple[int, np.ndarray] | str | None) -> str | Dict | None:
+ """
+ Parameters:
+ y: audio data in either of the following formats: a tuple of (sample_rate, data), or a string filepath or URL to an audio file, or None.
+ Returns:
+ base64 url data
+ """
+ if y is None:
+ return None
+ if isinstance(y, str) and utils.validate_url(y):
+ return {"name": y, "data": None, "is_file": True}
+ if isinstance(y, tuple):
+ sample_rate, data = y
+ file = tempfile.NamedTemporaryFile(suffix=".wav", delete=False)
+ processing_utils.audio_to_file(sample_rate, data, file.name)
+ file_path = str(utils.abspath(file.name))
+ self.temp_files.add(file_path)
+ else:
+ file_path = self.make_temp_copy_if_needed(y)
+ return {"name": file_path, "data": None, "is_file": True}
+
+ def stream(
+ self,
+ fn: Callable,
+ inputs: List[Component],
+ outputs: List[Component],
+ _js: str | None = None,
+ api_name: str | None = None,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ ):
+ """
+ This event is triggered when the user streams the component (e.g. a live webcam
+ component)
+ Parameters:
+ fn: Callable function
+ inputs: List of inputs
+ outputs: List of outputs
+ """
+ # _js: Optional frontend js method to run before running 'fn'. Input arguments for js method are values of 'inputs' and 'outputs', return should be a list of values for output components.
+ if self.source != "microphone":
+ raise ValueError(
+ "Audio streaming only available if source is 'microphone'."
+ )
+ super().stream(
+ fn,
+ inputs,
+ outputs,
+ _js=_js,
+ api_name=api_name,
+ preprocess=preprocess,
+ postprocess=postprocess,
+ )
+
+ def style(
+ self,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the audio component.
+ """
+ Component.style(
+ self,
+ **kwargs,
+ )
+ return self
+
+ def as_example(self, input_data: str | None) -> str:
+ return Path(input_data).name if input_data else ""
+
+
+@document("style")
+class File(
+ Changeable,
+ Selectable,
+ Clearable,
+ Uploadable,
+ IOComponent,
+ FileSerializable,
+ TempFileManager,
+):
+ """
+ Creates a file component that allows uploading generic file (when used as an input) and or displaying generic files (output).
+ Preprocessing: passes the uploaded file as a {file-object} or {List[file-object]} depending on `file_count` (or a {bytes}/{List{bytes}} depending on `type`)
+ Postprocessing: expects function to return a {str} path to a file, or {List[str]} consisting of paths to files.
+ Examples-format: a {str} path to a local file that populates the component.
+ Demos: zip_to_json, zip_files
+ """
+
+ def __init__(
+ self,
+ value: str | List[str] | Callable | None = None,
+ *,
+ file_count: str = "single",
+ file_types: List[str] | None = None,
+ type: str = "file",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Default file to display, given as str file path. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ file_count: if single, allows user to upload one file. If "multiple", user uploads multiple files. If "directory", user uploads all files in selected directory. Return type will be list for each file in case of "multiple" or "directory".
+ file_types: List of file extensions or types of files to be uploaded (e.g. ['image', '.json', '.mp4']). "file" allows any file to be uploaded, "image" allows only image files to be uploaded, "audio" allows only audio files to be uploaded, "video" allows only video files to be uploaded, "text" allows only text files to be uploaded.
+ type: Type of value to be returned by component. "file" returns a temporary file object with the same base name as the uploaded file, whose full path can be retrieved by file_obj.name, "binary" returns an bytes object.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, will allow users to upload a file; if False, can only be used to display files. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.file_count = file_count
+ self.file_types = file_types
+ if file_types is not None and not isinstance(file_types, list):
+ raise ValueError(
+ f"Parameter file_types must be a list. Received {file_types.__class__.__name__}"
+ )
+ valid_types = [
+ "file",
+ "binary",
+ "bytes",
+ ] # "bytes" is included for backwards compatibility
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ if type == "bytes":
+ warnings.warn(
+ "The `bytes` type is deprecated and may not work as expected. Please use `binary` instead."
+ )
+ if file_count == "directory" and file_types is not None:
+ warnings.warn(
+ "The `file_types` parameter is ignored when `file_count` is 'directory'."
+ )
+ self.type = type
+ self.test_input = None
+ self.select: EventListenerMethod
+ """
+ Event listener for when the user selects file from list.
+ Uses event data gradio.SelectData to carry `value` referring to name of selected file, and `index` to refer to index.
+ See EventData documentation on how to use this event data.
+ """
+ TempFileManager.__init__(self)
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "file_count": self.file_count,
+ "file_types": self.file_types,
+ "value": self.value,
+ "selectable": self.selectable,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "label": label,
+ "show_label": show_label,
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(
+ self, x: List[Dict[str, Any]] | None
+ ) -> bytes | tempfile._TemporaryFileWrapper | List[
+ bytes | tempfile._TemporaryFileWrapper
+ ] | None:
+ """
+ Parameters:
+ x: List of JSON objects with filename as 'name' property and base64 data as 'data' property
+ Returns:
+ File objects in requested format
+ """
+ if x is None:
+ return None
+
+ def process_single_file(f) -> bytes | tempfile._TemporaryFileWrapper:
+ file_name, data, is_file = (
+ f["name"],
+ f["data"],
+ f.get("is_file", False),
+ )
+ if self.type == "file":
+ if is_file:
+ temp_file_path = self.make_temp_copy_if_needed(file_name)
+ file = tempfile.NamedTemporaryFile(delete=False)
+ file.name = temp_file_path
+ file.orig_name = file_name # type: ignore
+ else:
+ file = processing_utils.decode_base64_to_file(
+ data, file_path=file_name
+ )
+ file.orig_name = file_name # type: ignore
+ self.temp_files.add(str(utils.abspath(file.name)))
+ return file
+ elif (
+ self.type == "binary" or self.type == "bytes"
+ ): # "bytes" is included for backwards compatibility
+ if is_file:
+ with open(file_name, "rb") as file_data:
+ return file_data.read()
+ return processing_utils.decode_base64_to_binary(data)[0]
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(self.type)
+ + ". Please choose from: 'file', 'bytes'."
+ )
+
+ if self.file_count == "single":
+ if isinstance(x, list):
+ return process_single_file(x[0])
+ else:
+ return process_single_file(x)
+ else:
+ if isinstance(x, list):
+ return [process_single_file(f) for f in x]
+ else:
+ return process_single_file(x)
+
+ def postprocess(
+ self, y: str | List[str] | None
+ ) -> Dict[str, Any] | List[Dict[str, Any]] | None:
+ """
+ Parameters:
+ y: file path
+ Returns:
+ JSON object with key 'name' for filename, 'data' for base64 url, and 'size' for filesize in bytes
+ """
+ if y is None:
+ return None
+ if isinstance(y, list):
+ return [
+ {
+ "orig_name": Path(file).name,
+ "name": self.make_temp_copy_if_needed(file),
+ "size": Path(file).stat().st_size,
+ "data": None,
+ "is_file": True,
+ }
+ for file in y
+ ]
+ else:
+ return {
+ "orig_name": Path(y).name,
+ "name": self.make_temp_copy_if_needed(y),
+ "size": Path(y).stat().st_size,
+ "data": None,
+ "is_file": True,
+ }
+
+ def serialize(self, x: str | None, load_dir: str = "") -> Dict | None:
+ serialized = FileSerializable.serialize(self, x, load_dir)
+ if serialized is None:
+ return None
+ serialized["size"] = Path(serialized["name"]).stat().st_size
+ return serialized
+
+ def style(
+ self,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the file component.
+ """
+ Component.style(
+ self,
+ **kwargs,
+ )
+ return self
+
+ def as_example(self, input_data: str | List | None) -> str:
+ if input_data is None:
+ return ""
+ elif isinstance(input_data, list):
+ return ", ".join([Path(file).name for file in input_data])
+ else:
+ return Path(input_data).name
+
+
+@document("style")
+class Dataframe(Changeable, Selectable, IOComponent, JSONSerializable):
+ """
+ Accepts or displays 2D input through a spreadsheet-like component for dataframes.
+ Preprocessing: passes the uploaded spreadsheet data as a {pandas.DataFrame}, {numpy.array}, {List[List]}, or {List} depending on `type`
+ Postprocessing: expects a {pandas.DataFrame}, {numpy.array}, {List[List]}, {List}, a {Dict} with keys `data` (and optionally `headers`), or {str} path to a csv, which is rendered in the spreadsheet.
+ Examples-format: a {str} filepath to a csv with data, a pandas dataframe, or a list of lists (excluding headers) where each sublist is a row of data.
+ Demos: filter_records, matrix_transpose, tax_calculator
+ """
+
+ markdown_parser = None
+
+ def __init__(
+ self,
+ value: List[List[Any]] | Callable | None = None,
+ *,
+ headers: List[str] | None = None,
+ row_count: int | Tuple[int, str] = (1, "dynamic"),
+ col_count: int | Tuple[int, str] | None = None,
+ datatype: str | List[str] = "str",
+ type: str = "pandas",
+ max_rows: int | None = 20,
+ max_cols: int | None = None,
+ overflow_row_behaviour: str = "paginate",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ wrap: bool = False,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Default value as a 2-dimensional list of values. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ headers: List of str header names. If None, no headers are shown.
+ row_count: Limit number of rows for input and decide whether user can create new rows. The first element of the tuple is an `int`, the row count; the second should be 'fixed' or 'dynamic', the new row behaviour. If an `int` is passed the rows default to 'dynamic'
+ col_count: Limit number of columns for input and decide whether user can create new columns. The first element of the tuple is an `int`, the number of columns; the second should be 'fixed' or 'dynamic', the new column behaviour. If an `int` is passed the columns default to 'dynamic'
+ datatype: Datatype of values in sheet. Can be provided per column as a list of strings, or for the entire sheet as a single string. Valid datatypes are "str", "number", "bool", "date", and "markdown".
+ type: Type of value to be returned by component. "pandas" for pandas dataframe, "numpy" for numpy array, or "array" for a Python array.
+ label: component name in interface.
+ max_rows: Maximum number of rows to display at once. Set to None for infinite.
+ max_cols: Maximum number of columns to display at once. Set to None for infinite.
+ overflow_row_behaviour: If set to "paginate", will create pages for overflow rows. If set to "show_ends", will show initial and final rows and truncate middle rows.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, will allow users to edit the dataframe; if False, can only be used to display data. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ wrap: if True text in table cells will wrap when appropriate, if False the table will scroll horiztonally. Defaults to False.
+ """
+
+ self.wrap = wrap
+ self.row_count = self.__process_counts(row_count)
+ self.col_count = self.__process_counts(
+ col_count, len(headers) if headers else 3
+ )
+
+ self.__validate_headers(headers, self.col_count[0])
+
+ self.headers = (
+ headers if headers is not None else list(range(1, self.col_count[0] + 1))
+ )
+ self.datatype = (
+ datatype if isinstance(datatype, list) else [datatype] * self.col_count[0]
+ )
+ valid_types = ["pandas", "numpy", "array"]
+ if type not in valid_types:
+ raise ValueError(
+ f"Invalid value for parameter `type`: {type}. Please choose from one of: {valid_types}"
+ )
+ self.type = type
+ values = {
+ "str": "",
+ "number": 0,
+ "bool": False,
+ "date": "01/01/1970",
+ "markdown": "",
+ "html": "",
+ }
+ column_dtypes = (
+ [datatype] * self.col_count[0] if isinstance(datatype, str) else datatype
+ )
+ self.test_input = [
+ [values[c] for c in column_dtypes] for _ in range(self.row_count[0])
+ ]
+
+ self.max_rows = max_rows
+ self.max_cols = max_cols
+ self.overflow_row_behaviour = overflow_row_behaviour
+ self.select: EventListenerMethod
+ """
+ Event listener for when the user selects cell within Dataframe.
+ Uses event data gradio.SelectData to carry `value` referring to value of selected cell, and `index` tuple to refer to index row and column.
+ See EventData documentation on how to use this event data.
+ """
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "headers": self.headers,
+ "datatype": self.datatype,
+ "row_count": self.row_count,
+ "col_count": self.col_count,
+ "value": self.value,
+ "max_rows": self.max_rows,
+ "max_cols": self.max_cols,
+ "overflow_row_behaviour": self.overflow_row_behaviour,
+ "wrap": self.wrap,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ max_rows: int | None = None,
+ max_cols: str | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "max_rows": max_rows,
+ "max_cols": max_cols,
+ "label": label,
+ "show_label": show_label,
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(self, x: DataframeData):
+ """
+ Parameters:
+ x: 2D array of str, numeric, or bool data
+ Returns:
+ Dataframe in requested format
+ """
+ if self.type == "pandas":
+ if x.get("headers") is not None:
+ return pd.DataFrame(x["data"], columns=x.get("headers"))
+ else:
+ return pd.DataFrame(x["data"])
+ if self.type == "numpy":
+ return np.array(x["data"])
+ elif self.type == "array":
+ return x["data"]
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(self.type)
+ + ". Please choose from: 'pandas', 'numpy', 'array'."
+ )
+
+ def postprocess(
+ self, y: str | pd.DataFrame | np.ndarray | List[List[str | float]] | Dict
+ ) -> Dict:
+ """
+ Parameters:
+ y: dataframe in given format
+ Returns:
+ JSON object with key 'headers' for list of header names, 'data' for 2D array of string or numeric data
+ """
+ if y is None:
+ return self.postprocess(self.test_input)
+ if isinstance(y, dict):
+ return y
+ if isinstance(y, str):
+ dataframe = pd.read_csv(y)
+ return {
+ "headers": list(dataframe.columns),
+ "data": Dataframe.__process_markdown(
+ dataframe.to_dict(orient="split")["data"], self.datatype
+ ),
+ }
+ if isinstance(y, pd.DataFrame):
+ return {
+ "headers": list(y.columns), # type: ignore
+ "data": Dataframe.__process_markdown(
+ y.to_dict(orient="split")["data"], self.datatype # type: ignore
+ ),
+ }
+ if isinstance(y, (np.ndarray, list)):
+ if isinstance(y, np.ndarray):
+ y = y.tolist()
+ assert isinstance(y, list), "output cannot be converted to list"
+
+ _headers = self.headers
+
+ if len(self.headers) < len(y[0]):
+ _headers = [
+ *self.headers,
+ *list(range(len(self.headers) + 1, len(y[0]) + 1)),
+ ]
+ elif len(self.headers) > len(y[0]):
+ _headers = self.headers[: len(y[0])]
+
+ return {
+ "headers": _headers,
+ "data": Dataframe.__process_markdown(y, self.datatype),
+ }
+ raise ValueError("Cannot process value as a Dataframe")
+
+ @staticmethod
+ def __process_counts(count, default=3) -> Tuple[int, str]:
+ if count is None:
+ return (default, "dynamic")
+ if type(count) == int or type(count) == float:
+ return (int(count), "dynamic")
+ else:
+ return count
+
+ @staticmethod
+ def __validate_headers(headers: List[str] | None, col_count: int):
+ if headers is not None and len(headers) != col_count:
+ raise ValueError(
+ "The length of the headers list must be equal to the col_count int.\nThe column count is set to {cols} but `headers` has {headers} items. Check the values passed to `col_count` and `headers`.".format(
+ cols=col_count, headers=len(headers)
+ )
+ )
+
+ @classmethod
+ def __process_markdown(cls, data: List[List[Any]], datatype: List[str]):
+ if "markdown" not in datatype:
+ return data
+
+ if cls.markdown_parser is None:
+ cls.markdown_parser = utils.get_markdown_parser()
+
+ for i in range(len(data)):
+ for j in range(len(data[i])):
+ if datatype[j] == "markdown":
+ data[i][j] = cls.markdown_parser.render(data[i][j])
+
+ return data
+
+ def style(
+ self,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the DataFrame component.
+ """
+ Component.style(
+ self,
+ **kwargs,
+ )
+ return self
+
+ def as_example(self, input_data: pd.DataFrame | np.ndarray | str | None):
+ if input_data is None:
+ return ""
+ elif isinstance(input_data, pd.DataFrame):
+ return input_data.head(n=5).to_dict(orient="split")["data"] # type: ignore
+ elif isinstance(input_data, np.ndarray):
+ return input_data.tolist()
+ return input_data
+
+
+@document("style")
+class Timeseries(Changeable, IOComponent, JSONSerializable):
+ """
+ Creates a component that can be used to upload/preview timeseries csv files or display a dataframe consisting of a time series graphically.
+ Preprocessing: passes the uploaded timeseries data as a {pandas.DataFrame} into the function
+ Postprocessing: expects a {pandas.DataFrame} or {str} path to a csv to be returned, which is then displayed as a timeseries graph
+ Examples-format: a {str} filepath of csv data with time series data.
+ Demos: fraud_detector
+ """
+
+ def __init__(
+ self,
+ value: str | Callable | None = None,
+ *,
+ x: str | None = None,
+ y: str | List[str] | None = None,
+ colors: List[str] | None = None,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: File path for the timeseries csv file. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ x: Column name of x (time) series. None if csv has no headers, in which case first column is x series.
+ y: Column name of y series, or list of column names if multiple series. None if csv has no headers, in which case every column after first is a y series.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ colors: an ordered list of colors to use for each line plot
+ show_label: if True, will display label.
+ interactive: if True, will allow users to upload a timeseries csv; if False, can only be used to display timeseries data. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.x = x
+ if isinstance(y, str):
+ y = [y]
+ self.y = y
+ self.colors = colors
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "x": self.x,
+ "y": self.y,
+ "value": self.value,
+ "colors": self.colors,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ colors: List[str] | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "colors": colors,
+ "label": label,
+ "show_label": show_label,
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(self, x: Dict | None) -> pd.DataFrame | None:
+ """
+ Parameters:
+ x: Dict with keys 'data': 2D array of str, numeric, or bool data, 'headers': list of strings for header names, 'range': optional two element list designating start of end of subrange.
+ Returns:
+ Dataframe of timeseries data
+ """
+ if x is None:
+ return x
+ elif x.get("is_file"):
+ dataframe = pd.read_csv(x["name"])
+ else:
+ dataframe = pd.DataFrame(data=x["data"], columns=x["headers"])
+ if x.get("range") is not None:
+ dataframe = dataframe.loc[dataframe[self.x or 0] >= x["range"][0]]
+ dataframe = dataframe.loc[dataframe[self.x or 0] <= x["range"][1]]
+ return dataframe
+
+ def postprocess(self, y: str | pd.DataFrame | None) -> Dict | None:
+ """
+ Parameters:
+ y: csv or dataframe with timeseries data
+ Returns:
+ JSON object with key 'headers' for list of header names, 'data' for 2D array of string or numeric data
+ """
+ if y is None:
+ return None
+ if isinstance(y, str):
+ dataframe = pd.read_csv(y)
+ return {
+ "headers": dataframe.columns.values.tolist(),
+ "data": dataframe.values.tolist(),
+ }
+ if isinstance(y, pd.DataFrame):
+ return {"headers": y.columns.values.tolist(), "data": y.values.tolist()}
+ raise ValueError("Cannot process value as Timeseries data")
+
+ def style(
+ self,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the TimeSeries component.
+ """
+ Component.style(
+ self,
+ **kwargs,
+ )
+ return self
+
+ def as_example(self, input_data: str | None) -> str:
+ return Path(input_data).name if input_data else ""
+
+
+@document()
+class State(IOComponent, SimpleSerializable):
+ """
+ Special hidden component that stores session state across runs of the demo by the
+ same user. The value of the State variable is cleared when the user refreshes the page.
+
+ Preprocessing: No preprocessing is performed
+ Postprocessing: No postprocessing is performed
+ Demos: blocks_simple_squares
+ Guides: creating_a_chatbot, real_time_speech_recognition
+ """
+
+ allow_string_shortcut = False
+
+ def __init__(
+ self,
+ value: Any = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: the initial value of the state. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ """
+ self.stateful = True
+ IOComponent.__init__(self, value=deepcopy(value), **kwargs)
+
+
+class Variable(State):
+ """Variable was renamed to State. This class is kept for backwards compatibility."""
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ def get_block_name(self):
+ return "state"
+
+
+@document("style")
+class Button(Clickable, IOComponent, SimpleSerializable):
+ """
+ Used to create a button, that can be assigned arbitrary click() events. The label (value) of the button can be used as an input or set via the output of a function.
+
+ Preprocessing: passes the button value as a {str} into the function
+ Postprocessing: expects a {str} to be returned from a function, which is set as the label of the button
+ Demos: blocks_inputs, blocks_kinematics
+ """
+
+ def __init__(
+ self,
+ value: str | Callable = "Run",
+ *,
+ variant: str = "secondary",
+ visible: bool = True,
+ interactive: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Default text for the button to display. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ variant: 'primary' for main call-to-action, 'secondary' for a more subdued style, 'stop' for a stop button.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ IOComponent.__init__(
+ self,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ interactive=interactive,
+ **kwargs,
+ )
+ if variant == "plain":
+ warnings.warn("'plain' variant deprecated, using 'secondary' instead.")
+ variant = "secondary"
+ self.variant = variant
+
+ def get_config(self):
+ return {
+ "value": self.value,
+ "variant": self.variant,
+ "interactive": self.interactive,
+ **Component.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: str | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ variant: str | None = None,
+ visible: bool | None = None,
+ interactive: bool | None = None,
+ ):
+ return {
+ "variant": variant,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def style(
+ self,
+ *,
+ full_width: bool | None = None,
+ size: Literal["sm"] | Literal["lg"] | None = None,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the button component.
+ Parameters:
+ full_width: If True, will expand to fill parent container.
+ size: Size of the button. Can be "sm" or "lg".
+ """
+ if full_width is not None:
+ self._style["full_width"] = full_width
+ if size is not None:
+ self._style["size"] = size
+
+ Component.style(self, **kwargs)
+ return self
+
+
+@document("style")
+class UploadButton(
+ Clickable, Uploadable, IOComponent, FileSerializable, TempFileManager
+):
+ """
+ Used to create an upload button, when cicked allows a user to upload files that satisfy the specified file type or generic files (if file_type not set).
+ Preprocessing: passes the uploaded file as a {file-object} or {List[file-object]} depending on `file_count` (or a {bytes}/{List{bytes}} depending on `type`)
+ Postprocessing: expects function to return a {str} path to a file, or {List[str]} consisting of paths to files.
+ Examples-format: a {str} path to a local file that populates the component.
+ Demos: upload_button
+ """
+
+ def __init__(
+ self,
+ label: str = "Upload a File",
+ value: str | List[str] | Callable | None = None,
+ *,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ type: str = "file",
+ file_count: str = "single",
+ file_types: List[str] | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Default text for the button to display.
+ type: Type of value to be returned by component. "file" returns a temporary file object with the same base name as the uploaded file, whose full path can be retrieved by file_obj.name, "binary" returns an bytes object.
+ file_count: if single, allows user to upload one file. If "multiple", user uploads multiple files. If "directory", user uploads all files in selected directory. Return type will be list for each file in case of "multiple" or "directory".
+ file_types: List of type of files to be uploaded. "file" allows any file to be uploaded, "image" allows only image files to be uploaded, "audio" allows only audio files to be uploaded, "video" allows only video files to be uploaded, "text" allows only text files to be uploaded.
+ label: Text to display on the button. Defaults to "Upload a File".
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.type = type
+ self.file_count = file_count
+ if file_count == "directory" and file_types is not None:
+ warnings.warn(
+ "The `file_types` parameter is ignored when `file_count` is 'directory'."
+ )
+ if file_types is not None and not isinstance(file_types, list):
+ raise ValueError(
+ f"Parameter file_types must be a list. Received {file_types.__class__.__name__}"
+ )
+ self.file_types = file_types
+ self.label = label
+ TempFileManager.__init__(self)
+ IOComponent.__init__(
+ self,
+ label=label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "label": self.label,
+ "value": self.value,
+ "file_count": self.file_count,
+ "file_types": self.file_types,
+ **Component.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: str | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ interactive: bool | None = None,
+ visible: bool | None = None,
+ ):
+ return {
+ "interactive": interactive,
+ "visible": visible,
+ "value": value,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(
+ self, x: List[Dict[str, Any]] | None
+ ) -> bytes | tempfile._TemporaryFileWrapper | List[
+ bytes | tempfile._TemporaryFileWrapper
+ ] | None:
+ """
+ Parameters:
+ x: List of JSON objects with filename as 'name' property and base64 data as 'data' property
+ Returns:
+ File objects in requested format
+ """
+ if x is None:
+ return None
+
+ def process_single_file(f) -> bytes | tempfile._TemporaryFileWrapper:
+ file_name, data, is_file = (
+ f["name"],
+ f["data"],
+ f.get("is_file", False),
+ )
+ if self.type == "file":
+ if is_file:
+ temp_file_path = self.make_temp_copy_if_needed(file_name)
+ file = tempfile.NamedTemporaryFile(delete=False)
+ file.name = temp_file_path
+ file.orig_name = file_name # type: ignore
+ else:
+ file = processing_utils.decode_base64_to_file(
+ data, file_path=file_name
+ )
+ file.orig_name = file_name # type: ignore
+ self.temp_files.add(str(utils.abspath(file.name)))
+ return file
+ elif self.type == "bytes":
+ if is_file:
+ with open(file_name, "rb") as file_data:
+ return file_data.read()
+ return processing_utils.decode_base64_to_binary(data)[0]
+ else:
+ raise ValueError(
+ "Unknown type: "
+ + str(self.type)
+ + ". Please choose from: 'file', 'bytes'."
+ )
+
+ if self.file_count == "single":
+ if isinstance(x, list):
+ return process_single_file(x[0])
+ else:
+ return process_single_file(x)
+ else:
+ if isinstance(x, list):
+ return [process_single_file(f) for f in x]
+ else:
+ return process_single_file(x)
+
+ def serialize(self, x: str | None, load_dir: str = "") -> Dict | None:
+ serialized = FileSerializable.serialize(self, x, load_dir)
+ if serialized is None:
+ return None
+ serialized["size"] = Path(serialized["name"]).stat().st_size
+ return serialized
+
+ def style(
+ self,
+ *,
+ full_width: bool | None = None,
+ size: Literal["sm"] | Literal["lg"] | None = None,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the button component.
+ Parameters:
+ full_width: If True, will expand to fill parent container.
+ size: Size of the button. Can be "sm" or "lg".
+ """
+ if full_width is not None:
+ self._style["full_width"] = full_width
+ if size is not None:
+ self._style["size"] = size
+
+ Component.style(self, **kwargs)
+ return self
+
+
+@document("style")
+class ColorPicker(Changeable, Submittable, IOComponent, SimpleSerializable):
+ """
+ Creates a color picker for user to select a color as string input.
+ Preprocessing: passes selected color value as a {str} into the function.
+ Postprocessing: expects a {str} returned from function and sets color picker value to it.
+ Examples-format: a {str} with a hexadecimal representation of a color, e.g. "#ff0000" for red.
+ Demos: color_picker, color_generator
+ """
+
+ def __init__(
+ self,
+ value: str | Callable | None = None,
+ *,
+ label: str | None = None,
+ info: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ interactive: bool | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: default text to provide in color picker. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: component name in interface.
+ info: additional component description.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ interactive: if True, will be rendered as an editable color picker; if False, editing will be disabled. If not provided, this is inferred based on whether the component is used as an input or output.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.cleared_value = "#000000"
+ self.test_input = value
+ IOComponent.__init__(
+ self,
+ label=label,
+ info=info,
+ every=every,
+ show_label=show_label,
+ interactive=interactive,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "value": self.value,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: str | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ interactive: bool | None = None,
+ ):
+ return {
+ "value": value,
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def preprocess(self, x: str | None) -> str | None:
+ """
+ Any preprocessing needed to be performed on function input.
+ Parameters:
+ x: text
+ Returns:
+ text
+ """
+ if x is None:
+ return None
+ else:
+ return str(x)
+
+ def postprocess(self, y: str | None) -> str | None:
+ """
+ Any postprocessing needed to be performed on function output.
+ Parameters:
+ y: text
+ Returns:
+ text
+ """
+ if y is None:
+ return None
+ else:
+ return str(y)
+
+
+############################
+# Only Output Components
+############################
+
+
+@document("style")
+class Label(Changeable, Selectable, IOComponent, JSONSerializable):
+ """
+ Displays a classification label, along with confidence scores of top categories, if provided.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a {Dict[str, float]} of classes and confidences, or {str} with just the class or an {int}/{float} for regression outputs, or a {str} path to a .json file containing a json dictionary in the structure produced by Label.postprocess().
+
+ Demos: main_note, titanic_survival
+ Guides: Gradio_and_ONNX_on_Hugging_Face, image_classification_in_pytorch, image_classification_in_tensorflow, image_classification_with_vision_transformers, building_a_pictionary_app
+ """
+
+ CONFIDENCES_KEY = "confidences"
+
+ def __init__(
+ self,
+ value: Dict[str, float] | str | float | Callable | None = None,
+ *,
+ num_top_classes: int | None = None,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ color: str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Default value to show in the component. If a str or number is provided, simply displays the string or number. If a {Dict[str, float]} of classes and confidences is provided, displays the top class on top and the `num_top_classes` below, along with their confidence bars. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ num_top_classes: number of most confident classes to show.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ color: The background color of the label (either a valid css color name or hexadecimal string).
+ """
+ self.num_top_classes = num_top_classes
+ self.color = color
+ self.select: EventListenerMethod
+ """
+ Event listener for when the user selects a category from Label.
+ Uses event data gradio.SelectData to carry `value` referring to name of selected category, and `index` to refer to index.
+ See EventData documentation on how to use this event data.
+ """
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "num_top_classes": self.num_top_classes,
+ "value": self.value,
+ "color": self.color,
+ "selectable": self.selectable,
+ **IOComponent.get_config(self),
+ }
+
+ def postprocess(self, y: Dict[str, float] | str | float | None) -> Dict | None:
+ """
+ Parameters:
+ y: a dictionary mapping labels to confidence value, or just a string/numerical label by itself
+ Returns:
+ Object with key 'label' representing primary label, and key 'confidences' representing a list of label-confidence pairs
+ """
+ if y is None or y == {}:
+ return None
+ if isinstance(y, str) and y.endswith(".json") and Path(y).exists():
+ return self.serialize(y)
+ if isinstance(y, (str, float, int)):
+ return {"label": str(y)}
+ if isinstance(y, dict):
+ if "confidences" in y and isinstance(y["confidences"], dict):
+ y = y["confidences"]
+ y = {c["label"]: c["confidence"] for c in y}
+ sorted_pred = sorted(y.items(), key=operator.itemgetter(1), reverse=True)
+ if self.num_top_classes is not None:
+ sorted_pred = sorted_pred[: self.num_top_classes]
+ return {
+ "label": sorted_pred[0][0],
+ "confidences": [
+ {"label": pred[0], "confidence": pred[1]} for pred in sorted_pred
+ ],
+ }
+ raise ValueError(
+ "The `Label` output interface expects one of: a string label, or an int label, a "
+ "float label, or a dictionary whose keys are labels and values are confidences. "
+ "Instead, got a {}".format(type(y))
+ )
+
+ @staticmethod
+ def update(
+ value: Dict[str, float]
+ | str
+ | float
+ | Literal[_Keywords.NO_VALUE]
+ | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ color: str | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ ):
+ # If color is not specified (NO_VALUE) map it to None so that
+ # it gets filtered out in postprocess. This will mean the color
+ # will not be updated in the front-end
+ if color is _Keywords.NO_VALUE:
+ color = None
+ # If the color was specified by the developer as None
+ # Map is so that the color is updated to be transparent,
+ # e.g. no background default state.
+ elif color is None:
+ color = "transparent"
+ return {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "color": color,
+ "__type__": "update",
+ }
+
+ def style(
+ self,
+ *,
+ container: bool | None = None,
+ ):
+ """
+ This method can be used to change the appearance of the label component.
+ Parameters:
+ container: If True, will add a container to the label - providing some extra padding around the border.
+ """
+ Component.style(self, container=container)
+ return self
+
+
+@document("style")
+class HighlightedText(Changeable, Selectable, IOComponent, JSONSerializable):
+ """
+ Displays text that contains spans that are highlighted by category or numerical value.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a {List[Tuple[str, float | str]]]} consisting of spans of text and their associated labels, or a {Dict} with two keys: (1) "text" whose value is the complete text, and "entities", which is a list of dictionaries, each of which have the keys: "entity" (consisting of the entity label), "start" (the character index where the label starts), and "end" (the character index where the label ends). Entities should not overlap.
+
+ Demos: diff_texts, text_analysis
+ Guides: named_entity_recognition
+ """
+
+ def __init__(
+ self,
+ value: List[Tuple[str, str | float | None]] | Dict | Callable | None = None,
+ *,
+ color_map: Dict[str, str]
+ | None = None, # Parameter moved to HighlightedText.style()
+ show_legend: bool = False,
+ combine_adjacent: bool = False,
+ adjacent_separator: str = "",
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Default value to show. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ show_legend: whether to show span categories in a separate legend or inline.
+ combine_adjacent: If True, will merge the labels of adjacent tokens belonging to the same category.
+ adjacent_separator: Specifies the separator to be used between tokens if combine_adjacent is True.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.color_map = color_map
+ if color_map is not None:
+ warnings.warn(
+ "The 'color_map' parameter has been moved from the constructor to `HighlightedText.style()` ",
+ )
+ self.show_legend = show_legend
+ self.combine_adjacent = combine_adjacent
+ self.adjacent_separator = adjacent_separator
+ self.select: EventListenerMethod
+ """
+ Event listener for when the user selects Highlighted text span.
+ Uses event data gradio.SelectData to carry `value` referring to selected [text, label] tuple, and `index` to refer to span index.
+ See EventData documentation on how to use this event data.
+ """
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "color_map": self.color_map,
+ "show_legend": self.show_legend,
+ "value": self.value,
+ "selectable": self.selectable,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: List[Tuple[str, str | float | None]]
+ | Dict
+ | Literal[_Keywords.NO_VALUE]
+ | None = _Keywords.NO_VALUE,
+ color_map: Dict[str, str] | None = None,
+ show_legend: bool | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ ):
+ updated_config = {
+ "color_map": color_map,
+ "show_legend": show_legend,
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "__type__": "update",
+ }
+ return updated_config
+
+ def postprocess(
+ self, y: List[Tuple[str, str | float | None]] | Dict | None
+ ) -> List[Tuple[str, str | float | None]] | None:
+ """
+ Parameters:
+ y: List of (word, category) tuples
+ Returns:
+ List of (word, category) tuples
+ """
+ if y is None:
+ return None
+ if isinstance(y, dict):
+ try:
+ text = y["text"]
+ entities = y["entities"]
+ except KeyError:
+ raise ValueError(
+ "Expected a dictionary with keys 'text' and 'entities' for the value of the HighlightedText component."
+ )
+ if len(entities) == 0:
+ y = [(text, None)]
+ else:
+ list_format = []
+ index = 0
+ entities = sorted(entities, key=lambda x: x["start"])
+ for entity in entities:
+ list_format.append((text[index : entity["start"]], None))
+ list_format.append(
+ (text[entity["start"] : entity["end"]], entity["entity"])
+ )
+ index = entity["end"]
+ list_format.append((text[index:], None))
+ y = list_format
+ if self.combine_adjacent:
+ output = []
+ running_text, running_category = None, None
+ for text, category in y:
+ if running_text is None:
+ running_text = text
+ running_category = category
+ elif category == running_category:
+ running_text += self.adjacent_separator + text
+ elif not text:
+ # Skip fully empty item, these get added in processing
+ # of dictionaries.
+ pass
+ else:
+ output.append((running_text, running_category))
+ running_text = text
+ running_category = category
+ if running_text is not None:
+ output.append((running_text, running_category))
+ return output
+ else:
+ return y
+
+ def style(
+ self,
+ *,
+ color_map: Dict[str, str] | None = None,
+ container: bool | None = None,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the HighlightedText component.
+ Parameters:
+ color_map: Map between category and respective colors.
+ container: If True, will place the component in a container - providing some extra padding around the border.
+ """
+ if color_map is not None:
+ self._style["color_map"] = color_map
+
+ Component.style(self, container=container, **kwargs)
+ return self
+
+
+@document("style")
+class JSON(Changeable, IOComponent, JSONSerializable):
+ """
+ Used to display arbitrary JSON output prettily.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a {str} filepath to a file containing valid JSON -- or a {list} or {dict} that is valid JSON
+
+ Demos: zip_to_json, blocks_xray
+ """
+
+ def __init__(
+ self,
+ value: str | Dict | List | Callable | None = None,
+ *,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Default value. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "value": self.value,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ ):
+ updated_config = {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "__type__": "update",
+ }
+ return updated_config
+
+ def postprocess(self, y: Dict | List | str | None) -> Dict | List | None:
+ """
+ Parameters:
+ y: either a string filepath to a JSON file, or a Python list or dict that can be converted to JSON
+ Returns:
+ JSON output in Python list or dict format
+ """
+ if y is None:
+ return None
+ if isinstance(y, str):
+ return json.loads(y)
+ else:
+ return y
+
+ def style(self, *, container: bool | None = None, **kwargs):
+ """
+ This method can be used to change the appearance of the JSON component.
+ Parameters:
+ container: If True, will place the JSON in a container - providing some extra padding around the border.
+ """
+ Component.style(self, container=container, **kwargs)
+ return self
+
+
+@document()
+class HTML(Changeable, IOComponent, SimpleSerializable):
+ """
+ Used to display arbitrary HTML output.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a valid HTML {str}.
+
+ Demos: text_analysis
+ Guides: key_features
+ """
+
+ def __init__(
+ self,
+ value: str | Callable = "",
+ *,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Default value. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "value": self.value,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ ):
+ updated_config = {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "__type__": "update",
+ }
+ return updated_config
+
+ def style(self):
+ return self
+
+
+@document("style")
+class Gallery(IOComponent, TempFileManager, FileSerializable, Selectable):
+ """
+ Used to display a list of images as a gallery that can be scrolled through.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a list of images in any format, {List[numpy.array | PIL.Image | str]}, or a {List} of (image, {str} caption) tuples and displays them.
+
+ Demos: fake_gan
+ """
+
+ def __init__(
+ self,
+ value: List[np.ndarray | _Image.Image | str | Tuple] | Callable | None = None,
+ *,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: List of images to display in the gallery by default. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.select: EventListenerMethod
+ """
+ Event listener for when the user selects image within Gallery.
+ Uses event data gradio.SelectData to carry `value` referring to caption of selected image, and `index` to refer to index.
+ See EventData documentation on how to use this event data.
+ """
+ TempFileManager.__init__(self)
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ ):
+ updated_config = {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "__type__": "update",
+ }
+ return updated_config
+
+ def get_config(self):
+ return {
+ "value": self.value,
+ **IOComponent.get_config(self),
+ }
+
+ def postprocess(
+ self,
+ y: List[np.ndarray | _Image.Image | str]
+ | List[Tuple[np.ndarray | _Image.Image | str, str]]
+ | None,
+ ) -> List[str]:
+ """
+ Parameters:
+ y: list of images, or list of (image, caption) tuples
+ Returns:
+ list of string file paths to images in temp directory
+ """
+ if y is None:
+ return []
+ output = []
+ for img in y:
+ caption = None
+ if isinstance(img, tuple) or isinstance(img, list):
+ img, caption = img
+ if isinstance(img, np.ndarray):
+ file = processing_utils.save_array_to_file(img)
+ file_path = str(utils.abspath(file.name))
+ self.temp_files.add(file_path)
+ elif isinstance(img, _Image.Image):
+ file = processing_utils.save_pil_to_file(img)
+ file_path = str(utils.abspath(file.name))
+ self.temp_files.add(file_path)
+ elif isinstance(img, str):
+ if utils.validate_url(img):
+ file_path = img
+ else:
+ file_path = self.make_temp_copy_if_needed(img)
+ else:
+ raise ValueError(f"Cannot process type as image: {type(img)}")
+
+ if caption is not None:
+ output.append(
+ [{"name": file_path, "data": None, "is_file": True}, caption]
+ )
+ else:
+ output.append({"name": file_path, "data": None, "is_file": True})
+
+ return output
+
+ def style(
+ self,
+ *,
+ grid: int | Tuple | None = None,
+ height: str | None = None,
+ container: bool | None = None,
+ preview: bool | None = None,
+ **kwargs,
+ ):
+ """
+ This method can be used to change the appearance of the gallery component.
+ Parameters:
+ grid: Represents the number of images that should be shown in one row, for each of the six standard screen sizes (<576px, <768px, <992px, <1200px, <1400px, >1400px). if fewer that 6 are given then the last will be used for all subsequent breakpoints
+ height: Height of the gallery.
+ container: If True, will place gallery in a container - providing some extra padding around the border.
+ preview: If True, will display the Gallery in preview mode, which shows all of the images as thumbnails and allows the user to click on them to view them in full size.
+ """
+ if grid is not None:
+ self._style["grid"] = grid
+ if height is not None:
+ self._style["height"] = height
+ if preview is not None:
+ self._style["preview"] = preview
+
+ Component.style(self, container=container, **kwargs)
+ return self
+
+ def deserialize(
+ self,
+ x: Any,
+ save_dir: str = "",
+ root_url: str | None = None,
+ ) -> None | str:
+ if x is None:
+ return None
+ gallery_path = Path(save_dir) / str(uuid.uuid4())
+ gallery_path.mkdir(exist_ok=True, parents=True)
+ captions = {}
+ for img_data in x:
+ if isinstance(img_data, list) or isinstance(img_data, tuple):
+ img_data, caption = img_data
+ else:
+ caption = None
+ name = FileSerializable.deserialize(
+ self, img_data, gallery_path, root_url=root_url
+ )
+ captions[name] = caption
+ captions_file = gallery_path / "captions.json"
+ with captions_file.open("w") as captions_json:
+ json.dump(captions, captions_json)
+ return str(utils.abspath(gallery_path))
+
+ def serialize(self, x: Any, load_dir: str = "", called_directly: bool = False):
+ files = []
+ captions_file = Path(x) / "captions.json"
+ with captions_file.open("r") as captions_json:
+ captions = json.load(captions_json)
+ for file_name, caption in captions.items():
+ img = FileSerializable.serialize(self, file_name)
+ files.append([img, caption])
+ return files
+
+
+class Carousel(IOComponent, Changeable, SimpleSerializable):
+ """
+ Deprecated Component
+ """
+
+ def __init__(
+ self,
+ *args,
+ **kwargs,
+ ):
+ raise DeprecationWarning(
+ "The Carousel component is deprecated. Please consider using the Gallery "
+ "component, which can be used to display images (and optional captions).",
+ )
+
+
+@document("style")
+class Chatbot(Changeable, Selectable, IOComponent, JSONSerializable):
+ """
+ Displays a chatbot output showing both user submitted messages and responses. Supports a subset of Markdown including bold, italics, code, and images.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects function to return a {List[Tuple[str | None | Tuple, str | None | Tuple]]}, a list of tuples with user message and response messages. Messages should be strings, tuples, or Nones. If the message is a string, it can include Markdown. If it is a tuple, it should consist of (string filepath to image/video/audio, [optional string alt text]). Messages that are `None` are not displayed.
+
+ Demos: chatbot_simple, chatbot_multimodal
+ """
+
+ def __init__(
+ self,
+ value: List[Tuple[str | None, str | None]] | Callable | None = None,
+ color_map: Dict[str, str] | None = None, # Parameter moved to Chatbot.style()
+ *,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Default value to show in chatbot. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ if color_map is not None:
+ warnings.warn(
+ "The 'color_map' parameter has been deprecated.",
+ )
+ self.md = utils.get_markdown_parser()
+ self.select: EventListenerMethod
+ """
+ Event listener for when the user selects message from Chatbot.
+ Uses event data gradio.SelectData to carry `value` referring to text of selected message, and `index` tuple to refer to [message, participant] index.
+ See EventData documentation on how to use this event data.
+ """
+
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "value": self.value,
+ "selectable": self.selectable,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ ):
+ updated_config = {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "__type__": "update",
+ }
+ return updated_config
+
+ def _process_chat_messages(
+ self, chat_message: str | Tuple | List | Dict | None
+ ) -> str | Dict | None:
+ if chat_message is None:
+ return None
+ elif isinstance(chat_message, (tuple, list)):
+ mime_type = processing_utils.get_mimetype(chat_message[0])
+ return {
+ "name": chat_message[0],
+ "mime_type": mime_type,
+ "alt_text": chat_message[1] if len(chat_message) > 1 else None,
+ "data": None, # These last two fields are filled in by the frontend
+ "is_file": True,
+ }
+ elif isinstance(
+ chat_message, dict
+ ): # This happens for previously processed messages
+ return chat_message
+ elif isinstance(chat_message, str):
+ return self.md.renderInline(chat_message)
+ else:
+ raise ValueError(f"Invalid message for Chatbot component: {chat_message}")
+
+ def postprocess(
+ self,
+ y: List[
+ Tuple[str | Tuple | List | Dict | None, str | Tuple | List | Dict | None]
+ ],
+ ) -> List[Tuple[str | Dict | None, str | Dict | None]]:
+ """
+ Parameters:
+ y: List of tuples representing the message and response pairs. Each message and response should be a string, which may be in Markdown format. It can also be a tuple whose first element is a string filepath or URL to an image/video/audio, and second (optional) element is the alt text, in which case the media file is displayed. It can also be None, in which case that message is not displayed.
+ Returns:
+ List of tuples representing the message and response. Each message and response will be a string of HTML, or a dictionary with media information.
+ """
+ if y is None:
+ return []
+ processed_messages = []
+ for message_pair in y:
+ assert isinstance(
+ message_pair, (tuple, list)
+ ), f"Expected a list of lists or list of tuples. Received: {message_pair}"
+ assert (
+ len(message_pair) == 2
+ ), f"Expected a list of lists of length 2 or list of tuples of length 2. Received: {message_pair}"
+ processed_messages.append(
+ (
+ self._process_chat_messages(message_pair[0]),
+ self._process_chat_messages(message_pair[1]),
+ )
+ )
+ return processed_messages
+
+ def style(self, height: int | None = None, **kwargs):
+ """
+ This method can be used to change the appearance of the Chatbot component.
+ """
+ if height is not None:
+ self._style["height"] = height
+ if kwargs.get("color_map") is not None:
+ warnings.warn("The 'color_map' parameter has been deprecated.")
+
+ Component.style(
+ self,
+ **kwargs,
+ )
+ return self
+
+
+@document("style")
+class Model3D(
+ Changeable, Editable, Clearable, IOComponent, FileSerializable, TempFileManager
+):
+ """
+ Component allows users to upload or view 3D Model files (.obj, .glb, or .gltf).
+ Preprocessing: This component passes the uploaded file as a {str} filepath.
+ Postprocessing: expects function to return a {str} path to a file of type (.obj, glb, or .gltf)
+
+ Demos: model3D
+ Guides: how_to_use_3D_model_component
+ """
+
+ def __init__(
+ self,
+ value: str | Callable | None = None,
+ *,
+ clear_color: List[float] | None = None,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: path to (.obj, glb, or .gltf) file to show in model3D viewer. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ clear_color: background color of scene
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.clear_color = clear_color or [0, 0, 0, 0]
+ TempFileManager.__init__(self)
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "clearColor": self.clear_color,
+ "value": self.value,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ ):
+ updated_config = {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "__type__": "update",
+ }
+ return updated_config
+
+ def preprocess(self, x: Dict[str, str] | None) -> str | None:
+ """
+ Parameters:
+ x: JSON object with filename as 'name' property and base64 data as 'data' property
+ Returns:
+ string file path to temporary file with the 3D image model
+ """
+ if x is None:
+ return x
+ file_name, file_data, is_file = (
+ x["name"],
+ x["data"],
+ x.get("is_file", False),
+ )
+ if is_file:
+ temp_file_path = self.make_temp_copy_if_needed(file_name)
+ else:
+ temp_file_path = self.base64_to_temp_file_if_needed(file_data, file_name)
+
+ return temp_file_path
+
+ def postprocess(self, y: str | None) -> Dict[str, str] | None:
+ """
+ Parameters:
+ y: path to the model
+ Returns:
+ file name mapped to base64 url data
+ """
+ if y is None:
+ return y
+ data = {
+ "name": self.make_temp_copy_if_needed(y),
+ "data": None,
+ "is_file": True,
+ }
+ return data
+
+ def style(self, **kwargs):
+ """
+ This method can be used to change the appearance of the Model3D component.
+ """
+ Component.style(
+ self,
+ **kwargs,
+ )
+ return self
+
+ def as_example(self, input_data: str | None) -> str:
+ return Path(input_data).name if input_data else ""
+
+
+@document()
+class Plot(Changeable, Clearable, IOComponent, JSONSerializable):
+ """
+ Used to display various kinds of plots (matplotlib, plotly, or bokeh are supported)
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects either a {matplotlib.figure.Figure}, a {plotly.graph_objects._figure.Figure}, or a {dict} corresponding to a bokeh plot (json_item format)
+
+ Demos: altair_plot, outbreak_forecast, blocks_kinematics, stock_forecast, map_airbnb
+ Guides: plot_component_for_maps
+ """
+
+ def __init__(
+ self,
+ value: Callable | None | pd.DataFrame = None,
+ *,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Optionally, supply a default plot object to display, must be a matplotlib, plotly, altair, or bokeh figure, or a callable. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ label: component name in interface.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: if True, will display label.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ IOComponent.__init__(
+ self,
+ label=label,
+ every=every,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ try:
+ import bokeh # type: ignore
+
+ bokeh_version = bokeh.__version__
+ except ImportError:
+ bokeh_version = None
+ return {
+ "value": self.value,
+ "bokeh_version": bokeh_version,
+ **IOComponent.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ ):
+ updated_config = {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "__type__": "update",
+ }
+ return updated_config
+
+ def postprocess(self, y) -> Dict[str, str] | None:
+ """
+ Parameters:
+ y: plot data
+ Returns:
+ plot type mapped to plot base64 data
+ """
+ if y is None:
+ return None
+ if isinstance(y, (ModuleType, matplotlib.figure.Figure)):
+ dtype = "matplotlib"
+ out_y = processing_utils.encode_plot_to_base64(y)
+ elif "bokeh" in y.__module__:
+ dtype = "bokeh"
+ from bokeh.embed import json_item # type: ignore
+
+ out_y = json.dumps(json_item(y))
+ else:
+ is_altair = "altair" in y.__module__
+ if is_altair:
+ dtype = "altair"
+ else:
+ dtype = "plotly"
+ out_y = y.to_json()
+ return {"type": dtype, "plot": out_y}
+
+ def style(self, container: bool | None = None):
+ Component.style(
+ self,
+ container=container,
+ )
+ return self
+
+
+class AltairPlot:
+ @staticmethod
+ def create_legend(position, title):
+ if position == "none":
+ legend = None
+ else:
+ position = {"orient": position} if position else {}
+ legend = {"title": title, **position}
+
+ return legend
+
+ @staticmethod
+ def create_scale(limit):
+ return alt.Scale(domain=limit) if limit else alt.Undefined
+
+
+@document()
+class ScatterPlot(Plot):
+ """
+ Create a scatter plot.
+
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a pandas dataframe with the data to plot.
+
+ Demos: native_plots
+ Guides: creating_a_dashboard_from_bigquery_data
+ """
+
+ def __init__(
+ self,
+ value: pd.DataFrame | Callable | None = None,
+ x: str | None = None,
+ y: str | None = None,
+ *,
+ color: str | None = None,
+ size: str | None = None,
+ shape: str | None = None,
+ title: str | None = None,
+ tooltip: List[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ color_legend_title: str | None = None,
+ size_legend_title: str | None = None,
+ shape_legend_title: str | None = None,
+ color_legend_position: str | None = None,
+ size_legend_position: str | None = None,
+ shape_legend_position: str | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ x_lim: List[int | float] | None = None,
+ y_lim: List[int | float] | None = None,
+ caption: str | None = None,
+ interactive: bool | None = True,
+ label: str | None = None,
+ every: float | None = None,
+ show_label: bool = True,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ ):
+ """
+ Parameters:
+ value: The pandas dataframe containing the data to display in a scatter plot, or a callable. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ x: Column corresponding to the x axis.
+ y: Column corresponding to the y axis.
+ color: The column to determine the point color. If the column contains numeric data, gradio will interpolate the column data so that small values correspond to light colors and large values correspond to dark values.
+ size: The column used to determine the point size. Should contain numeric data so that gradio can map the data to the point size.
+ shape: The column used to determine the point shape. Should contain categorical data. Gradio will map each unique value to a different shape.
+ title: The title to display on top of the chart.
+ tooltip: The column (or list of columns) to display on the tooltip when a user hovers a point on the plot.
+ x_title: The title given to the x axis. By default, uses the value of the x parameter.
+ y_title: The title given to the y axis. By default, uses the value of the y parameter.
+ color_legend_title: The title given to the color legend. By default, uses the value of color parameter.
+ size_legend_title: The title given to the size legend. By default, uses the value of the size parameter.
+ shape_legend_title: The title given to the shape legend. By default, uses the value of the shape parameter.
+ color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ size_legend_position: The position of the size legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ shape_legend_position: The position of the shape legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ height: The height of the plot in pixels.
+ width: The width of the plot in pixels.
+ x_lim: A tuple or list containing the limits for the x-axis, specified as [x_min, x_max].
+ y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max].
+ caption: The (optional) caption to display below the plot.
+ interactive: Whether users should be able to interact with the plot by panning or zooming with their mouse or trackpad.
+ label: The (optional) label to display on the top left corner of the plot.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ show_label: Whether the label should be displayed.
+ visible: Whether the plot should be visible.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.x = x
+ self.y = y
+ self.color = color
+ self.size = size
+ self.shape = shape
+ self.tooltip = tooltip
+ self.title = title
+ self.x_title = x_title
+ self.y_title = y_title
+ self.color_legend_title = color_legend_title
+ self.color_legend_position = color_legend_position
+ self.size_legend_title = size_legend_title
+ self.size_legend_position = size_legend_position
+ self.shape_legend_title = shape_legend_title
+ self.shape_legend_position = shape_legend_position
+ self.caption = caption
+ self.interactive_chart = interactive
+ self.width = width
+ self.height = height
+ self.x_lim = x_lim
+ self.y_lim = y_lim
+ super().__init__(
+ value=value,
+ label=label,
+ every=every,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ )
+
+ def get_config(self):
+ config = super().get_config()
+ config["caption"] = self.caption
+ return config
+
+ def get_block_name(self) -> str:
+ return "plot"
+
+ @staticmethod
+ def update(
+ value: DataFrame | Dict | Literal[_Keywords.NO_VALUE] = _Keywords.NO_VALUE,
+ x: str | None = None,
+ y: str | None = None,
+ color: str | None = None,
+ size: str | None = None,
+ shape: str | None = None,
+ title: str | None = None,
+ tooltip: List[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ color_legend_title: str | None = None,
+ size_legend_title: str | None = None,
+ shape_legend_title: str | None = None,
+ color_legend_position: str | None = None,
+ size_legend_position: str | None = None,
+ shape_legend_position: str | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ x_lim: List[int | float] | None = None,
+ y_lim: List[int | float] | None = None,
+ interactive: bool | None = None,
+ caption: str | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ ):
+ """Update an existing plot component.
+
+ If updating any of the plot properties (color, size, etc) the value, x, and y parameters must be specified.
+
+ Parameters:
+ value: The pandas dataframe containing the data to display in a scatter plot.
+ x: Column corresponding to the x axis.
+ y: Column corresponding to the y axis.
+ color: The column to determine the point color. If the column contains numeric data, gradio will interpolate the column data so that small values correspond to light colors and large values correspond to dark values.
+ size: The column used to determine the point size. Should contain numeric data so that gradio can map the data to the point size.
+ shape: The column used to determine the point shape. Should contain categorical data. Gradio will map each unique value to a different shape.
+ title: The title to display on top of the chart.
+ tooltip: The column (or list of columns) to display on the tooltip when a user hovers a point on the plot.
+ x_title: The title given to the x axis. By default, uses the value of the x parameter.
+ y_title: The title given to the y axis. By default, uses the value of the y parameter.
+ color_legend_title: The title given to the color legend. By default, uses the value of color parameter.
+ size_legend_title: The title given to the size legend. By default, uses the value of the size parameter.
+ shape_legend_title: The title given to the shape legend. By default, uses the value of the shape parameter.
+ color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ size_legend_position: The position of the size legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ shape_legend_position: The position of the shape legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ height: The height of the plot in pixels.
+ width: The width of the plot in pixels.
+ x_lim: A tuple or list containing the limits for the x-axis, specified as [x_min, x_max].
+ y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max].
+ interactive: Whether users should be able to interact with the plot by panning or zooming with their mouse or trackpad.
+ caption: The (optional) caption to display below the plot.
+ label: The (optional) label to display in the top left corner of the plot.
+ show_label: Whether the label should be displayed.
+ visible: Whether the plot should be visible.
+ """
+ properties = [
+ x,
+ y,
+ color,
+ size,
+ shape,
+ title,
+ tooltip,
+ x_title,
+ y_title,
+ color_legend_title,
+ size_legend_title,
+ shape_legend_title,
+ color_legend_position,
+ size_legend_position,
+ shape_legend_position,
+ height,
+ width,
+ x_lim,
+ y_lim,
+ interactive,
+ ]
+ if any(properties):
+ if not isinstance(value, pd.DataFrame):
+ raise ValueError(
+ "In order to update plot properties the value parameter "
+ "must be provided, and it must be a Dataframe. Please pass a value "
+ "parameter to gr.ScatterPlot.update."
+ )
+ if x is None or y is None:
+ raise ValueError(
+ "In order to update plot properties, the x and y axis data "
+ "must be specified. Please pass valid values for x an y to "
+ "gr.ScatterPlot.update."
+ )
+ chart = ScatterPlot.create_plot(value, *properties)
+ value = {"type": "altair", "plot": chart.to_json(), "chart": "scatter"}
+
+ updated_config = {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "caption": caption,
+ "__type__": "update",
+ }
+ return updated_config
+
+ @staticmethod
+ def create_plot(
+ value: pd.DataFrame,
+ x: str,
+ y: str,
+ color: str | None = None,
+ size: str | None = None,
+ shape: str | None = None,
+ title: str | None = None,
+ tooltip: List[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ color_legend_title: str | None = None,
+ size_legend_title: str | None = None,
+ shape_legend_title: str | None = None,
+ color_legend_position: str | None = None,
+ size_legend_position: str | None = None,
+ shape_legend_position: str | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ x_lim: List[int | float] | None = None,
+ y_lim: List[int | float] | None = None,
+ interactive: bool | None = True,
+ ):
+ """Helper for creating the scatter plot."""
+ interactive = True if interactive is None else interactive
+ encodings = dict(
+ x=alt.X(
+ x, # type: ignore
+ title=x_title or x, # type: ignore
+ scale=AltairPlot.create_scale(x_lim), # type: ignore
+ ), # ignore: type
+ y=alt.Y(
+ y, # type: ignore
+ title=y_title or y, # type: ignore
+ scale=AltairPlot.create_scale(y_lim), # type: ignore
+ ),
+ )
+ properties = {}
+ if title:
+ properties["title"] = title
+ if height:
+ properties["height"] = height
+ if width:
+ properties["width"] = width
+ if color:
+ if is_numeric_dtype(value[color]):
+ domain = [value[color].min(), value[color].max()]
+ range_ = [0, 1]
+ type_ = "quantitative"
+ else:
+ domain = value[color].unique().tolist()
+ range_ = list(range(len(domain)))
+ type_ = "nominal"
+
+ encodings["color"] = {
+ "field": color,
+ "type": type_,
+ "legend": AltairPlot.create_legend(
+ position=color_legend_position, title=color_legend_title or color
+ ),
+ "scale": {"domain": domain, "range": range_},
+ }
+ if tooltip:
+ encodings["tooltip"] = tooltip
+ if size:
+ encodings["size"] = {
+ "field": size,
+ "type": "quantitative" if is_numeric_dtype(value[size]) else "nominal",
+ "legend": AltairPlot.create_legend(
+ position=size_legend_position, title=size_legend_title or size
+ ),
+ }
+ if shape:
+ encodings["shape"] = {
+ "field": shape,
+ "type": "quantitative" if is_numeric_dtype(value[shape]) else "nominal",
+ "legend": AltairPlot.create_legend(
+ position=shape_legend_position, title=shape_legend_title or shape
+ ),
+ }
+ chart = (
+ alt.Chart(value) # type: ignore
+ .mark_point(clip=True) # type: ignore
+ .encode(**encodings)
+ .properties(background="transparent", **properties)
+ )
+ if interactive:
+ chart = chart.interactive()
+
+ return chart
+
+ def postprocess(self, y: pd.DataFrame | Dict | None) -> Dict[str, str] | None:
+ # if None or update
+ if y is None or isinstance(y, Dict):
+ return y
+ if self.x is None or self.y is None:
+ raise ValueError("No value provided for required parameters `x` and `y`.")
+ chart = self.create_plot(
+ value=y,
+ x=self.x,
+ y=self.y,
+ color=self.color,
+ size=self.size,
+ shape=self.shape,
+ title=self.title,
+ tooltip=self.tooltip,
+ x_title=self.x_title,
+ y_title=self.y_title,
+ color_legend_title=self.color_legend_title,
+ size_legend_title=self.size_legend_title,
+ shape_legend_title=self.size_legend_title,
+ color_legend_position=self.color_legend_position,
+ size_legend_position=self.size_legend_position,
+ shape_legend_position=self.shape_legend_position,
+ interactive=self.interactive_chart,
+ height=self.height,
+ width=self.width,
+ x_lim=self.x_lim,
+ y_lim=self.y_lim,
+ )
+
+ return {"type": "altair", "plot": chart.to_json(), "chart": "scatter"}
+
+
+@document()
+class LinePlot(Plot):
+ """
+ Create a line plot.
+
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a pandas dataframe with the data to plot.
+
+ Demos: native_plots, live_dashboard
+ """
+
+ def __init__(
+ self,
+ value: pd.DataFrame | Callable | None = None,
+ x: str | None = None,
+ y: str | None = None,
+ *,
+ color: str | None = None,
+ stroke_dash: str | None = None,
+ overlay_point: bool | None = None,
+ title: str | None = None,
+ tooltip: List[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ color_legend_title: str | None = None,
+ stroke_dash_legend_title: str | None = None,
+ color_legend_position: str | None = None,
+ stroke_dash_legend_position: str | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ x_lim: List[int] | None = None,
+ y_lim: List[int] | None = None,
+ caption: str | None = None,
+ interactive: bool | None = True,
+ label: str | None = None,
+ show_label: bool = True,
+ every: float | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ ):
+ """
+ Parameters:
+ value: The pandas dataframe containing the data to display in a scatter plot.
+ x: Column corresponding to the x axis.
+ y: Column corresponding to the y axis.
+ color: The column to determine the point color. If the column contains numeric data, gradio will interpolate the column data so that small values correspond to light colors and large values correspond to dark values.
+ stroke_dash: The column to determine the symbol used to draw the line, e.g. dashed lines, dashed lines with points.
+ overlay_point: Whether to draw a point on the line for each (x, y) coordinate pair.
+ title: The title to display on top of the chart.
+ tooltip: The column (or list of columns) to display on the tooltip when a user hovers a point on the plot.
+ x_title: The title given to the x axis. By default, uses the value of the x parameter.
+ y_title: The title given to the y axis. By default, uses the value of the y parameter.
+ color_legend_title: The title given to the color legend. By default, uses the value of color parameter.
+ stroke_dash_legend_title: The title given to the stroke_dash legend. By default, uses the value of the stroke_dash parameter.
+ color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ stroke_dash_legend_position: The position of the stoke_dash legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ height: The height of the plot in pixels.
+ width: The width of the plot in pixels.
+ x_lim: A tuple or list containing the limits for the x-axis, specified as [x_min, x_max].
+ y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max].
+ caption: The (optional) caption to display below the plot.
+ interactive: Whether users should be able to interact with the plot by panning or zooming with their mouse or trackpad.
+ label: The (optional) label to display on the top left corner of the plot.
+ show_label: Whether the label should be displayed.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ visible: Whether the plot should be visible.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.x = x
+ self.y = y
+ self.color = color
+ self.stroke_dash = stroke_dash
+ self.tooltip = tooltip
+ self.title = title
+ self.x_title = x_title
+ self.y_title = y_title
+ self.color_legend_title = color_legend_title
+ self.stroke_dash_legend_title = stroke_dash_legend_title
+ self.color_legend_position = color_legend_position
+ self.stroke_dash_legend_position = stroke_dash_legend_position
+ self.overlay_point = overlay_point
+ self.x_lim = x_lim
+ self.y_lim = y_lim
+ self.caption = caption
+ self.interactive_chart = interactive
+ self.width = width
+ self.height = height
+ super().__init__(
+ value=value,
+ label=label,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ every=every,
+ )
+
+ def get_config(self):
+ config = super().get_config()
+ config["caption"] = self.caption
+ return config
+
+ def get_block_name(self) -> str:
+ return "plot"
+
+ @staticmethod
+ def update(
+ value: pd.DataFrame | Dict | Literal[_Keywords.NO_VALUE] = _Keywords.NO_VALUE,
+ x: str | None = None,
+ y: str | None = None,
+ color: str | None = None,
+ stroke_dash: str | None = None,
+ overlay_point: bool | None = None,
+ title: str | None = None,
+ tooltip: List[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ color_legend_title: str | None = None,
+ stroke_dash_legend_title: str | None = None,
+ color_legend_position: str | None = None,
+ stroke_dash_legend_position: str | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ x_lim: List[int] | None = None,
+ y_lim: List[int] | None = None,
+ interactive: bool | None = None,
+ caption: str | None = None,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ ):
+ """Update an existing plot component.
+
+ If updating any of the plot properties (color, size, etc) the value, x, and y parameters must be specified.
+
+ Parameters:
+ value: The pandas dataframe containing the data to display in a scatter plot.
+ x: Column corresponding to the x axis.
+ y: Column corresponding to the y axis.
+ color: The column to determine the point color. If the column contains numeric data, gradio will interpolate the column data so that small values correspond to light colors and large values correspond to dark values.
+ stroke_dash: The column to determine the symbol used to draw the line, e.g. dashed lines, dashed lines with points.
+ overlay_point: Whether to draw a point on the line for each (x, y) coordinate pair.
+ title: The title to display on top of the chart.
+ tooltip: The column (or list of columns) to display on the tooltip when a user hovers a point on the plot.
+ x_title: The title given to the x axis. By default, uses the value of the x parameter.
+ y_title: The title given to the y axis. By default, uses the value of the y parameter.
+ color_legend_title: The title given to the color legend. By default, uses the value of color parameter.
+ stroke_dash_legend_title: The title given to the stroke legend. By default, uses the value of stroke parameter.
+ color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation
+ stroke_dash_legend_position: The position of the stoke_dash legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation
+ height: The height of the plot in pixels.
+ width: The width of the plot in pixels.
+ x_lim: A tuple or list containing the limits for the x-axis, specified as [x_min, x_max].
+ y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max].
+ caption: The (optional) caption to display below the plot.
+ interactive: Whether users should be able to interact with the plot by panning or zooming with their mouse or trackpad.
+ label: The (optional) label to display in the top left corner of the plot.
+ show_label: Whether the label should be displayed.
+ visible: Whether the plot should be visible.
+ """
+ properties = [
+ x,
+ y,
+ color,
+ stroke_dash,
+ overlay_point,
+ title,
+ tooltip,
+ x_title,
+ y_title,
+ color_legend_title,
+ stroke_dash_legend_title,
+ color_legend_position,
+ stroke_dash_legend_position,
+ height,
+ width,
+ x_lim,
+ y_lim,
+ interactive,
+ ]
+ if any(properties):
+ if not isinstance(value, pd.DataFrame):
+ raise ValueError(
+ "In order to update plot properties the value parameter "
+ "must be provided, and it must be a Dataframe. Please pass a value "
+ "parameter to gr.LinePlot.update."
+ )
+ if x is None or y is None:
+ raise ValueError(
+ "In order to update plot properties, the x and y axis data "
+ "must be specified. Please pass valid values for x an y to "
+ "gr.LinePlot.update."
+ )
+ chart = LinePlot.create_plot(value, *properties)
+ value = {"type": "altair", "plot": chart.to_json(), "chart": "line"}
+
+ updated_config = {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "caption": caption,
+ "__type__": "update",
+ }
+ return updated_config
+
+ @staticmethod
+ def create_plot(
+ value: pd.DataFrame,
+ x: str,
+ y: str,
+ color: str | None = None,
+ stroke_dash: str | None = None,
+ overlay_point: bool | None = None,
+ title: str | None = None,
+ tooltip: List[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ color_legend_title: str | None = None,
+ stroke_dash_legend_title: str | None = None,
+ color_legend_position: str | None = None,
+ stroke_dash_legend_position: str | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ x_lim: List[int] | None = None,
+ y_lim: List[int] | None = None,
+ interactive: bool | None = None,
+ ):
+ """Helper for creating the scatter plot."""
+ interactive = True if interactive is None else interactive
+ encodings = dict(
+ x=alt.X(
+ x, # type: ignore
+ title=x_title or x, # type: ignore
+ scale=AltairPlot.create_scale(x_lim), # type: ignore
+ ),
+ y=alt.Y(
+ y, # type: ignore
+ title=y_title or y, # type: ignore
+ scale=AltairPlot.create_scale(y_lim), # type: ignore
+ ),
+ )
+ properties = {}
+ if title:
+ properties["title"] = title
+ if height:
+ properties["height"] = height
+ if width:
+ properties["width"] = width
+
+ if color:
+ domain = value[color].unique().tolist()
+ range_ = list(range(len(domain)))
+ encodings["color"] = {
+ "field": color,
+ "type": "nominal",
+ "scale": {"domain": domain, "range": range_},
+ "legend": AltairPlot.create_legend(
+ position=color_legend_position, title=color_legend_title or color
+ ),
+ }
+
+ highlight = None
+ if interactive and any([color, stroke_dash]):
+ highlight = alt.selection(
+ type="single", # type: ignore
+ on="mouseover",
+ fields=[c for c in [color, stroke_dash] if c],
+ nearest=True,
+ )
+
+ if stroke_dash:
+ stroke_dash = {
+ "field": stroke_dash, # type: ignore
+ "legend": AltairPlot.create_legend( # type: ignore
+ position=stroke_dash_legend_position, # type: ignore
+ title=stroke_dash_legend_title or stroke_dash, # type: ignore
+ ), # type: ignore
+ } # type: ignore
+ else:
+ stroke_dash = alt.value(alt.Undefined) # type: ignore
+
+ if tooltip:
+ encodings["tooltip"] = tooltip
+
+ chart = alt.Chart(value).encode(**encodings) # type: ignore
+
+ points = chart.mark_point(clip=True).encode(
+ opacity=alt.value(alt.Undefined) if overlay_point else alt.value(0),
+ )
+ lines = chart.mark_line(clip=True).encode(strokeDash=stroke_dash)
+
+ if highlight:
+ points = points.add_selection(highlight)
+
+ lines = lines.encode(
+ size=alt.condition(highlight, alt.value(4), alt.value(1)),
+ )
+
+ chart = (lines + points).properties(background="transparent", **properties)
+ if interactive:
+ chart = chart.interactive()
+
+ return chart
+
+ def postprocess(self, y: pd.DataFrame | Dict | None) -> Dict[str, str] | None:
+ # if None or update
+ if y is None or isinstance(y, Dict):
+ return y
+ if self.x is None or self.y is None:
+ raise ValueError("No value provided for required parameters `x` and `y`.")
+ chart = self.create_plot(
+ value=y,
+ x=self.x,
+ y=self.y,
+ color=self.color,
+ overlay_point=self.overlay_point,
+ title=self.title,
+ tooltip=self.tooltip,
+ x_title=self.x_title,
+ y_title=self.y_title,
+ color_legend_title=self.color_legend_title,
+ color_legend_position=self.color_legend_position,
+ stroke_dash_legend_title=self.stroke_dash_legend_title,
+ stroke_dash_legend_position=self.stroke_dash_legend_position,
+ x_lim=self.x_lim,
+ y_lim=self.y_lim,
+ stroke_dash=self.stroke_dash,
+ interactive=self.interactive_chart,
+ height=self.height,
+ width=self.width,
+ )
+
+ return {"type": "altair", "plot": chart.to_json(), "chart": "line"}
+
+
+@document()
+class BarPlot(Plot):
+ """
+ Create a bar plot.
+
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a pandas dataframe with the data to plot.
+
+ Demos: native_plots, chicago-bikeshare-dashboard
+ """
+
+ def __init__(
+ self,
+ value: pd.DataFrame | Callable | None = None,
+ x: str | None = None,
+ y: str | None = None,
+ *,
+ color: str | None = None,
+ vertical: bool = True,
+ group: str | None = None,
+ title: str | None = None,
+ tooltip: List[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ color_legend_title: str | None = None,
+ group_title: str | None = None,
+ color_legend_position: str | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ y_lim: List[int] | None = None,
+ caption: str | None = None,
+ interactive: bool | None = True,
+ label: str | None = None,
+ show_label: bool = True,
+ every: float | None = None,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ ):
+ """
+ Parameters:
+ value: The pandas dataframe containing the data to display in a scatter plot.
+ x: Column corresponding to the x axis.
+ y: Column corresponding to the y axis.
+ color: The column to determine the bar color. Must be categorical (discrete values).
+ vertical: If True, the bars will be displayed vertically. If False, the x and y axis will be switched, displaying the bars horizontally. Default is True.
+ group: The column with which to split the overall plot into smaller subplots.
+ title: The title to display on top of the chart.
+ tooltip: The column (or list of columns) to display on the tooltip when a user hovers over a bar.
+ x_title: The title given to the x axis. By default, uses the value of the x parameter.
+ y_title: The title given to the y axis. By default, uses the value of the y parameter.
+ color_legend_title: The title given to the color legend. By default, uses the value of color parameter.
+ group_title: The label displayed on top of the subplot columns (or rows if vertical=True). Use an empty string to omit.
+ color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ height: The height of the plot in pixels.
+ width: The width of the plot in pixels.
+ y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max].
+ caption: The (optional) caption to display below the plot.
+ interactive: Whether users should be able to interact with the plot by panning or zooming with their mouse or trackpad.
+ label: The (optional) label to display on the top left corner of the plot.
+ show_label: Whether the label should be displayed.
+ every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
+ visible: Whether the plot should be visible.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.x = x
+ self.y = y
+ self.color = color
+ self.vertical = vertical
+ self.group = group
+ self.group_title = group_title
+ self.tooltip = tooltip
+ self.title = title
+ self.x_title = x_title
+ self.y_title = y_title
+ self.color_legend_title = color_legend_title
+ self.group_title = group_title
+ self.color_legend_position = color_legend_position
+ self.y_lim = y_lim
+ self.caption = caption
+ self.interactive_chart = interactive
+ self.width = width
+ self.height = height
+ super().__init__(
+ value=value,
+ label=label,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ every=every,
+ )
+
+ def get_config(self):
+ config = super().get_config()
+ config["caption"] = self.caption
+ return config
+
+ def get_block_name(self) -> str:
+ return "plot"
+
+ @staticmethod
+ def update(
+ value: pd.DataFrame | Dict | Literal[_Keywords.NO_VALUE] = _Keywords.NO_VALUE,
+ x: str | None = None,
+ y: str | None = None,
+ color: str | None = None,
+ vertical: bool = True,
+ group: str | None = None,
+ title: str | None = None,
+ tooltip: List[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ color_legend_title: str | None = None,
+ group_title: str | None = None,
+ color_legend_position: str | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ y_lim: List[int] | None = None,
+ caption: str | None = None,
+ interactive: bool | None = True,
+ label: str | None = None,
+ show_label: bool = True,
+ visible: bool = True,
+ ):
+ """Update an existing BarPlot component.
+
+ If updating any of the plot properties (color, size, etc) the value, x, and y parameters must be specified.
+
+ Parameters:
+ value: The pandas dataframe containing the data to display in a scatter plot.
+ x: Column corresponding to the x axis.
+ y: Column corresponding to the y axis.
+ color: The column to determine the bar color. Must be categorical (discrete values).
+ vertical: If True, the bars will be displayed vertically. If False, the x and y axis will be switched, displaying the bars horizontally. Default is True.
+ group: The column with which to split the overall plot into smaller subplots.
+ title: The title to display on top of the chart.
+ tooltip: The column (or list of columns) to display on the tooltip when a user hovers over a bar.
+ x_title: The title given to the x axis. By default, uses the value of the x parameter.
+ y_title: The title given to the y axis. By default, uses the value of the y parameter.
+ color_legend_title: The title given to the color legend. By default, uses the value of color parameter.
+ group_title: The label displayed on top of the subplot columns (or rows if vertical=True). Use an empty string to omit.
+ color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation.
+ height: The height of the plot in pixels.
+ width: The width of the plot in pixels.
+ y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max].
+ caption: The (optional) caption to display below the plot.
+ interactive: Whether users should be able to interact with the plot by panning or zooming with their mouse or trackpad.
+ label: The (optional) label to display on the top left corner of the plot.
+ show_label: Whether the label should be displayed.
+ visible: Whether the plot should be visible.
+ """
+ properties = [
+ x,
+ y,
+ color,
+ vertical,
+ group,
+ title,
+ tooltip,
+ x_title,
+ y_title,
+ color_legend_title,
+ group_title,
+ color_legend_position,
+ height,
+ width,
+ y_lim,
+ interactive,
+ ]
+ if any(properties):
+ if not isinstance(value, pd.DataFrame):
+ raise ValueError(
+ "In order to update plot properties the value parameter "
+ "must be provided, and it must be a Dataframe. Please pass a value "
+ "parameter to gr.BarPlot.update."
+ )
+ if x is None or y is None:
+ raise ValueError(
+ "In order to update plot properties, the x and y axis data "
+ "must be specified. Please pass valid values for x an y to "
+ "gr.BarPlot.update."
+ )
+ chart = BarPlot.create_plot(value, *properties)
+ value = {"type": "altair", "plot": chart.to_json(), "chart": "bar"}
+
+ updated_config = {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "caption": caption,
+ "__type__": "update",
+ }
+ return updated_config
+
+ @staticmethod
+ def create_plot(
+ value: pd.DataFrame,
+ x: str,
+ y: str,
+ color: str | None = None,
+ vertical: bool = True,
+ group: str | None = None,
+ title: str | None = None,
+ tooltip: List[str] | str | None = None,
+ x_title: str | None = None,
+ y_title: str | None = None,
+ color_legend_title: str | None = None,
+ group_title: str | None = None,
+ color_legend_position: str | None = None,
+ height: int | None = None,
+ width: int | None = None,
+ y_lim: List[int] | None = None,
+ interactive: bool | None = True,
+ ):
+ """Helper for creating the scatter plot."""
+ interactive = True if interactive is None else interactive
+ orientation = (
+ dict(field=group, title=group_title if group_title is not None else group)
+ if group
+ else {}
+ )
+
+ x_title = x_title or x
+ y_title = y_title or y
+
+ # If horizontal, switch x and y
+ if not vertical:
+ y, x = x, y
+ x = f"sum({x}):Q"
+ y_title, x_title = x_title, y_title
+ orientation = {"row": alt.Row(**orientation)} if orientation else {} # type: ignore
+ x_lim = y_lim
+ y_lim = None
+ else:
+ y = f"sum({y}):Q"
+ x_lim = None
+ orientation = {"column": alt.Column(**orientation)} if orientation else {} # type: ignore
+
+ encodings = dict(
+ x=alt.X(
+ x, # type: ignore
+ title=x_title, # type: ignore
+ scale=AltairPlot.create_scale(x_lim), # type: ignore
+ ),
+ y=alt.Y(
+ y, # type: ignore
+ title=y_title, # type: ignore
+ scale=AltairPlot.create_scale(y_lim), # type: ignore
+ ),
+ **orientation,
+ )
+ properties = {}
+ if title:
+ properties["title"] = title
+ if height:
+ properties["height"] = height
+ if width:
+ properties["width"] = width
+
+ if color:
+ domain = value[color].unique().tolist()
+ range_ = list(range(len(domain)))
+ encodings["color"] = {
+ "field": color,
+ "type": "nominal",
+ "scale": {"domain": domain, "range": range_},
+ "legend": AltairPlot.create_legend(
+ position=color_legend_position, title=color_legend_title or color
+ ),
+ }
+
+ if tooltip:
+ encodings["tooltip"] = tooltip
+
+ chart = (
+ alt.Chart(value) # type: ignore
+ .mark_bar() # type: ignore
+ .encode(**encodings)
+ .properties(background="transparent", **properties)
+ )
+ if interactive:
+ chart = chart.interactive()
+
+ return chart
+
+ def postprocess(self, y: pd.DataFrame | Dict | None) -> Dict[str, str] | None:
+ # if None or update
+ if y is None or isinstance(y, Dict):
+ return y
+ if self.x is None or self.y is None:
+ raise ValueError("No value provided for required parameters `x` and `y`.")
+ chart = self.create_plot(
+ value=y,
+ x=self.x,
+ y=self.y,
+ color=self.color,
+ vertical=self.vertical,
+ group=self.group,
+ title=self.title,
+ tooltip=self.tooltip,
+ x_title=self.x_title,
+ y_title=self.y_title,
+ color_legend_title=self.color_legend_title,
+ color_legend_position=self.color_legend_position,
+ group_title=self.group_title,
+ y_lim=self.y_lim,
+ interactive=self.interactive_chart,
+ height=self.height,
+ width=self.width,
+ )
+
+ return {"type": "altair", "plot": chart.to_json(), "chart": "bar"}
+
+
+@document()
+class Markdown(IOComponent, Changeable, SimpleSerializable):
+ """
+ Used to render arbitrary Markdown output. Can also render latex enclosed by dollar signs.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a valid {str} that can be rendered as Markdown.
+
+ Demos: blocks_hello, blocks_kinematics
+ Guides: key_features
+ """
+
+ def __init__(
+ self,
+ value: str | Callable = "",
+ *,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Value to show in Markdown component. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ self.md = utils.get_markdown_parser()
+ IOComponent.__init__(
+ self,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def postprocess(self, y: str | None) -> str | None:
+ """
+ Parameters:
+ y: markdown representation
+ Returns:
+ HTML rendering of markdown
+ """
+ if y is None:
+ return None
+ unindented_y = inspect.cleandoc(y)
+ return self.md.render(unindented_y)
+
+ def get_config(self):
+ return {
+ "value": self.value,
+ **Component.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ visible: bool | None = None,
+ ):
+ updated_config = {
+ "visible": visible,
+ "value": value,
+ "__type__": "update",
+ }
+ return updated_config
+
+ def style(self):
+ return self
+
+ def as_example(self, input_data: str | None) -> str:
+ postprocessed = self.postprocess(input_data)
+ return postprocessed if postprocessed else ""
+
+
+@document("languages")
+class Code(Changeable, IOComponent, SimpleSerializable):
+ """
+ Creates a Code editor for entering, editing or viewing code.
+ Preprocessing: passes a {str} of code into the function.
+ Postprocessing: expects the function to return a {str} of code or a single-elment {tuple}: (string filepath,)
+ """
+
+ languages = [
+ "python",
+ "markdown",
+ "json",
+ "html",
+ "css",
+ "javascript",
+ "typescript",
+ "yaml",
+ "dockerfile",
+ "shell",
+ "r",
+ None,
+ ]
+
+ def __init__(
+ self,
+ value: str | None = None,
+ language: str | None = None,
+ *,
+ label: str | None = None,
+ interactive: bool | None = None,
+ show_label: bool = True,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ value: Default value to show in the code editor. If callable, the function will be called whenever the app loads to set the initial value of the component.
+ language: The language to display the code as. Supported languages listed in `gr.Code.languages`.
+ label: component name in interface.
+ interactive: Whether user should be able to enter code or only view it.
+ show_label: if True, will display label.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ assert language in Code.languages, f"Language {language} not supported."
+ self.language = language
+ IOComponent.__init__(
+ self,
+ label=label,
+ interactive=interactive,
+ show_label=show_label,
+ visible=visible,
+ elem_id=elem_id,
+ elem_classes=elem_classes,
+ value=value,
+ **kwargs,
+ )
+
+ def get_config(self):
+ return {
+ "value": self.value,
+ "language": self.language,
+ **IOComponent.get_config(self),
+ }
+
+ def postprocess(self, y):
+ if y is None:
+ return None
+ elif isinstance(y, tuple):
+ with open(y[0]) as file_data:
+ return file_data.read()
+ else:
+ unindented_y = inspect.cleandoc(y)
+ return unindented_y
+
+ @staticmethod
+ def update(
+ value: str | None | Literal[_Keywords.NO_VALUE] = _Keywords.NO_VALUE,
+ label: str | None = None,
+ show_label: bool | None = None,
+ visible: bool | None = None,
+ language: str | None = None,
+ interactive: bool | None = True,
+ ):
+ return {
+ "label": label,
+ "show_label": show_label,
+ "visible": visible,
+ "value": value,
+ "language": language,
+ "interactive": interactive,
+ "__type__": "update",
+ }
+
+ def style(self):
+ return self
+
+
+############################
+# Special Components
+############################
+
+
+@document("style")
+class Dataset(Clickable, Selectable, Component):
+ """
+ Used to create an output widget for showing datasets. Used to render the examples
+ box.
+ Preprocessing: passes the selected sample either as a {list} of data (if type="value") or as an {int} index (if type="index")
+ Postprocessing: expects a {list} of {lists} corresponding to the dataset data.
+ """
+
+ def __init__(
+ self,
+ *,
+ label: str | None = None,
+ components: List[IOComponent] | List[str],
+ samples: List[List[Any]] | None = None,
+ headers: List[str] | None = None,
+ type: str = "values",
+ samples_per_page: int = 10,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ components: Which component types to show in this dataset widget, can be passed in as a list of string names or Components instances. The following components are supported in a Dataset: Audio, Checkbox, CheckboxGroup, ColorPicker, Dataframe, Dropdown, File, HTML, Image, Markdown, Model3D, Number, Radio, Slider, Textbox, TimeSeries, Video
+ samples: a nested list of samples. Each sublist within the outer list represents a data sample, and each element within the sublist represents an value for each component
+ headers: Column headers in the Dataset widget, should be the same len as components. If not provided, inferred from component labels
+ type: 'values' if clicking on a sample should pass the value of the sample, or "index" if it should pass the index of the sample
+ samples_per_page: how many examples to show per page.
+ visible: If False, component will be hidden.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ Component.__init__(
+ self, visible=visible, elem_id=elem_id, elem_classes=elem_classes, **kwargs
+ )
+ self.components = [get_component_instance(c, render=False) for c in components]
+
+ # Narrow type to IOComponent
+ assert all(
+ [isinstance(c, IOComponent) for c in self.components]
+ ), "All components in a `Dataset` must be subclasses of `IOComponent`"
+ self.components = [c for c in self.components if isinstance(c, IOComponent)]
+ for component in self.components:
+ component.root_url = self.root_url
+
+ self.samples = [[]] if samples is None else samples
+ for example in self.samples:
+ for i, (component, ex) in enumerate(zip(self.components, example)):
+ example[i] = component.as_example(ex)
+ self.type = type
+ self.label = label
+ if headers is not None:
+ self.headers = headers
+ elif all([c.label is None for c in self.components]):
+ self.headers = []
+ else:
+ self.headers = [c.label or "" for c in self.components]
+ self.samples_per_page = samples_per_page
+
+ def get_config(self):
+ return {
+ "components": [component.get_block_name() for component in self.components],
+ "headers": self.headers,
+ "samples": self.samples,
+ "type": self.type,
+ "label": self.label,
+ "samples_per_page": self.samples_per_page,
+ **Component.get_config(self),
+ }
+
+ @staticmethod
+ def update(
+ samples: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ visible: bool | None = None,
+ label: str | None = None,
+ ):
+ return {
+ "samples": samples,
+ "visible": visible,
+ "label": label,
+ "__type__": "update",
+ }
+
+ def preprocess(self, x: Any) -> Any:
+ """
+ Any preprocessing needed to be performed on function input.
+ """
+ if self.type == "index":
+ return x
+ elif self.type == "values":
+ return self.samples[x]
+
+ def postprocess(self, samples: List[List[Any]]) -> Dict:
+ return {
+ "samples": samples,
+ "__type__": "update",
+ }
+
+ def style(self, **kwargs):
+ """
+ This method can be used to change the appearance of the Dataset component.
+ """
+ Component.style(self, **kwargs)
+ return self
+
+
+@document()
+class Interpretation(Component):
+ """
+ Used to create an interpretation widget for a component.
+ Preprocessing: this component does *not* accept input.
+ Postprocessing: expects a {dict} with keys "original" and "interpretation".
+
+ Guides: custom_interpretations_with_blocks
+ """
+
+ def __init__(
+ self,
+ component: Component,
+ *,
+ visible: bool = True,
+ elem_id: str | None = None,
+ elem_classes: List[str] | str | None = None,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ component: Which component to show in the interpretation widget.
+ visible: Whether or not the interpretation is visible.
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
+ elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
+ """
+ Component.__init__(
+ self, visible=visible, elem_id=elem_id, elem_classes=elem_classes, **kwargs
+ )
+ self.component = component
+
+ def get_config(self):
+ return {
+ "component": self.component.get_block_name(),
+ "component_props": self.component.get_config(),
+ }
+
+ @staticmethod
+ def update(
+ value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
+ visible: bool | None = None,
+ ):
+ return {
+ "visible": visible,
+ "value": value,
+ "__type__": "update",
+ }
+
+ def style(self):
+ return self
+
+
+class StatusTracker(Component):
+ def __init__(
+ self,
+ **kwargs,
+ ):
+ warnings.warn("The StatusTracker component is deprecated.")
+
+
+def component(cls_name: str) -> Component:
+ obj = utils.component_or_layout_class(cls_name)()
+ if isinstance(obj, BlockContext):
+ raise ValueError(f"Invalid component: {obj.__class__}")
+ return obj
+
+
+def get_component_instance(comp: str | dict | Component, render=True) -> Component:
+ if isinstance(comp, str):
+ component_obj = component(comp)
+ if not (render):
+ component_obj.unrender()
+ return component_obj
+ elif isinstance(comp, dict):
+ name = comp.pop("name")
+ component_cls = utils.component_or_layout_class(name)
+ component_obj = component_cls(**comp)
+ if isinstance(component_obj, BlockContext):
+ raise ValueError(f"Invalid component: {name}")
+ if not (render):
+ component_obj.unrender()
+ return component_obj
+ elif isinstance(comp, Component):
+ return comp
+ else:
+ raise ValueError(
+ f"Component must provided as a `str` or `dict` or `Component` but is {comp}"
+ )
+
+
+Text = Textbox
+DataFrame = Dataframe
+Highlightedtext = HighlightedText
+Highlight = HighlightedText
+Checkboxgroup = CheckboxGroup
+TimeSeries = Timeseries
+Json = JSON
diff --git a/gradio/context.py b/gradio/context.py
new file mode 100644
index 0000000000000000000000000000000000000000..6048312eb01799d0dd042f8b25294f3dc6f11c8e
--- /dev/null
+++ b/gradio/context.py
@@ -0,0 +1,18 @@
+# Defines the Context class, which is used to store the state of all Blocks that are being rendered.
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING: # Only import for type checking (is False at runtime).
+ from gradio.blocks import BlockContext, Blocks
+
+
+class Context:
+ root_block: Blocks | None = None # The current root block that holds all blocks.
+ block: BlockContext | None = None # The current block that children are added to.
+ id: int = 0 # Running id to uniquely refer to any block that gets defined
+ ip_address: str | None = None # The IP address of the user.
+ access_token: str | None = (
+ None # The HF token that is provided when loading private models or Spaces
+ )
diff --git a/gradio/data_classes.py b/gradio/data_classes.py
new file mode 100644
index 0000000000000000000000000000000000000000..9b0ae76c489245c10c0adc6cd843e5c1161f81a5
--- /dev/null
+++ b/gradio/data_classes.py
@@ -0,0 +1,55 @@
+"""Pydantic data models and other dataclasses. This is the only file that uses Optional[]
+typing syntax instead of | None syntax to work with pydantic"""
+from enum import Enum, auto
+from typing import Any, Dict, List, Optional, Union
+
+from pydantic import BaseModel
+
+
+class PredictBody(BaseModel):
+ session_hash: Optional[str]
+ event_id: Optional[str]
+ data: List[Any]
+ event_data: Optional[Any]
+ fn_index: Optional[int]
+ batched: Optional[
+ bool
+ ] = False # Whether the data is a batch of samples (i.e. called from the queue if batch=True) or a single sample (i.e. called from the UI)
+ request: Optional[
+ Union[Dict, List[Dict]]
+ ] = None # dictionary of request headers, query parameters, url, etc. (used to to pass in request for queuing)
+
+
+class ResetBody(BaseModel):
+ session_hash: str
+ fn_index: int
+
+
+class InterfaceTypes(Enum):
+ STANDARD = auto()
+ INPUT_ONLY = auto()
+ OUTPUT_ONLY = auto()
+ UNIFIED = auto()
+
+
+class Estimation(BaseModel):
+ msg: Optional[str] = "estimation"
+ rank: Optional[int] = None
+ queue_size: int
+ avg_event_process_time: Optional[float]
+ avg_event_concurrent_process_time: Optional[float]
+ rank_eta: Optional[float] = None
+ queue_eta: float
+
+
+class ProgressUnit(BaseModel):
+ index: Optional[int]
+ length: Optional[int]
+ unit: Optional[str]
+ progress: Optional[float]
+ desc: Optional[str]
+
+
+class Progress(BaseModel):
+ msg: str = "progress"
+ progress_data: List[ProgressUnit] = []
diff --git a/gradio/deprecation.py b/gradio/deprecation.py
new file mode 100644
index 0000000000000000000000000000000000000000..555a4fed4474ec18c72bd36484ddf3a5ec466c0b
--- /dev/null
+++ b/gradio/deprecation.py
@@ -0,0 +1,45 @@
+import warnings
+
+
+def simple_deprecated_notice(term: str) -> str:
+ return f"`{term}` parameter is deprecated, and it has no effect"
+
+
+def use_in_launch(term: str) -> str:
+ return f"`{term}` is deprecated in `Interface()`, please use it within `launch()` instead."
+
+
+DEPRECATION_MESSAGE = {
+ "optional": simple_deprecated_notice("optional"),
+ "keep_filename": simple_deprecated_notice("keep_filename"),
+ "numeric": simple_deprecated_notice("numeric"),
+ "verbose": simple_deprecated_notice("verbose"),
+ "allow_screenshot": simple_deprecated_notice("allow_screenshot"),
+ "layout": simple_deprecated_notice("layout"),
+ "show_input": simple_deprecated_notice("show_input"),
+ "show_output": simple_deprecated_notice("show_output"),
+ "capture_session": simple_deprecated_notice("capture_session"),
+ "api_mode": simple_deprecated_notice("api_mode"),
+ "show_tips": use_in_launch("show_tips"),
+ "encrypt": simple_deprecated_notice("encrypt"),
+ "enable_queue": use_in_launch("enable_queue"),
+ "server_name": use_in_launch("server_name"),
+ "server_port": use_in_launch("server_port"),
+ "width": use_in_launch("width"),
+ "height": use_in_launch("height"),
+ "plot": "The 'plot' parameter has been deprecated. Use the new Plot component instead",
+ "type": "The 'type' parameter has been deprecated. Use the Number component instead.",
+}
+
+
+def check_deprecated_parameters(cls: str, **kwargs) -> None:
+ for key, value in DEPRECATION_MESSAGE.items():
+ if key in kwargs:
+ kwargs.pop(key)
+ # Interestingly, using DeprecationWarning causes warning to not appear.
+ warnings.warn(value)
+
+ if len(kwargs) != 0:
+ warnings.warn(
+ f"You have unused kwarg parameters in {cls}, please remove them: {kwargs}"
+ )
diff --git a/gradio/documentation.py b/gradio/documentation.py
new file mode 100644
index 0000000000000000000000000000000000000000..a3c8792d59217c2c798d5eead77d9a95aa91fdd9
--- /dev/null
+++ b/gradio/documentation.py
@@ -0,0 +1,261 @@
+"""Contains methods that generate documentation for Gradio functions and classes."""
+
+from __future__ import annotations
+
+import inspect
+from typing import Callable, Dict, List, Tuple
+
+classes_to_document = {}
+classes_inherit_documentation = {}
+documentation_group = None
+
+
+def set_documentation_group(m):
+ global documentation_group
+ documentation_group = m
+ if m not in classes_to_document:
+ classes_to_document[m] = []
+
+
+def extract_instance_attr_doc(cls, attr):
+ code = inspect.getsource(cls.__init__)
+ lines = [line.strip() for line in code.split("\n")]
+ i = None
+ for i, line in enumerate(lines):
+ if line.startswith("self." + attr + ":") or line.startswith(
+ "self." + attr + " ="
+ ):
+ break
+ assert i is not None, f"Could not find {attr} in {cls.__name__}"
+ start_line = lines.index('"""', i)
+ end_line = lines.index('"""', start_line + 1)
+ for j in range(i + 1, start_line):
+ assert not lines[j].startswith("self."), (
+ f"Found another attribute before docstring for {attr} in {cls.__name__}: "
+ + lines[j]
+ + "\n start:"
+ + lines[i]
+ )
+ doc_string = " ".join(lines[start_line + 1 : end_line])
+ return doc_string
+
+
+def document(*fns, inherit=False):
+ """
+ Defines the @document decorator which adds classes or functions to the Gradio
+ documentation at www.gradio.app/docs.
+
+ Usage examples:
+ - Put @document() above a class to document the class and its constructor.
+ - Put @document("fn1", "fn2") above a class to also document methods fn1 and fn2.
+ - Put @document("*fn3") with an asterisk above a class to document the instance attribute methods f3.
+ """
+
+ def inner_doc(cls):
+ global documentation_group
+ if inherit:
+ classes_inherit_documentation[cls] = None
+ classes_to_document[documentation_group].append((cls, fns))
+ return cls
+
+ return inner_doc
+
+
+def document_fn(fn: Callable, cls) -> Tuple[str, List[Dict], Dict, str | None]:
+ """
+ Generates documentation for any function.
+ Parameters:
+ fn: Function to document
+ Returns:
+ description: General description of fn
+ parameters: A list of dicts for each parameter, storing data for the parameter name, annotation and doc
+ return: A dict storing data for the returned annotation and doc
+ example: Code for an example use of the fn
+ """
+ doc_str = inspect.getdoc(fn) or ""
+ doc_lines = doc_str.split("\n")
+ signature = inspect.signature(fn)
+ description, parameters, returns, examples = [], {}, [], []
+ mode = "description"
+ for line in doc_lines:
+ line = line.rstrip()
+ if line == "Parameters:":
+ mode = "parameter"
+ elif line.startswith("Example:"):
+ mode = "example"
+ if "(" in line and ")" in line:
+ c = line.split("(")[1].split(")")[0]
+ if c != cls.__name__:
+ mode = "ignore"
+ elif line == "Returns:":
+ mode = "return"
+ else:
+ if mode == "description":
+ description.append(line if line.strip() else " ")
+ continue
+ assert (
+ line.startswith(" ") or line.strip() == ""
+ ), f"Documentation format for {fn.__name__} has format error in line: {line}"
+ line = line[4:]
+ if mode == "parameter":
+ colon_index = line.index(": ")
+ assert (
+ colon_index > -1
+ ), f"Documentation format for {fn.__name__} has format error in line: {line}"
+ parameter = line[:colon_index]
+ parameter_doc = line[colon_index + 2 :]
+ parameters[parameter] = parameter_doc
+ elif mode == "return":
+ returns.append(line)
+ elif mode == "example":
+ examples.append(line)
+ description_doc = " ".join(description)
+ parameter_docs = []
+ for param_name, param in signature.parameters.items():
+ if param_name.startswith("_"):
+ continue
+ if param_name == "kwargs" and param_name not in parameters:
+ continue
+ parameter_doc = {
+ "name": param_name,
+ "annotation": param.annotation,
+ "doc": parameters.get(param_name),
+ }
+ if param_name in parameters:
+ del parameters[param_name]
+ if param.default != inspect.Parameter.empty:
+ default = param.default
+ if type(default) == str:
+ default = '"' + default + '"'
+ if default.__class__.__module__ != "builtins":
+ default = f"{default.__class__.__name__}()"
+ parameter_doc["default"] = default
+ elif parameter_doc["doc"] is not None and "kwargs" in parameter_doc["doc"]:
+ parameter_doc["kwargs"] = True
+ parameter_docs.append(parameter_doc)
+ assert (
+ len(parameters) == 0
+ ), f"Documentation format for {fn.__name__} documents nonexistent parameters: {''.join(parameters.keys())}"
+ if len(returns) == 0:
+ return_docs = {}
+ elif len(returns) == 1:
+ return_docs = {"annotation": signature.return_annotation, "doc": returns[0]}
+ else:
+ return_docs = {}
+ # raise ValueError("Does not support multiple returns yet.")
+ examples_doc = "\n".join(examples) if len(examples) > 0 else None
+ return description_doc, parameter_docs, return_docs, examples_doc
+
+
+def document_cls(cls):
+ doc_str = inspect.getdoc(cls)
+ if doc_str is None:
+ return "", {}, ""
+ tags = {}
+ description_lines = []
+ mode = "description"
+ for line in doc_str.split("\n"):
+ line = line.rstrip()
+ if line.endswith(":") and " " not in line:
+ mode = line[:-1].lower()
+ tags[mode] = []
+ elif line.split(" ")[0].endswith(":") and not line.startswith(" "):
+ tag = line[: line.index(":")].lower()
+ value = line[line.index(":") + 2 :]
+ tags[tag] = value
+ else:
+ if mode == "description":
+ description_lines.append(line if line.strip() else " ")
+ else:
+ assert (
+ line.startswith(" ") or not line.strip()
+ ), f"Documentation format for {cls.__name__} has format error in line: {line}"
+ tags[mode].append(line[4:])
+ if "example" in tags:
+ example = "\n".join(tags["example"])
+ del tags["example"]
+ else:
+ example = None
+ for key, val in tags.items():
+ if isinstance(val, list):
+ tags[key] = " ".join(val)
+ description = " ".join(description_lines).replace("\n", " ")
+ return description, tags, example
+
+
+def generate_documentation():
+ documentation = {}
+ for mode, class_list in classes_to_document.items():
+ documentation[mode] = []
+ for cls, fns in class_list:
+ fn_to_document = cls if inspect.isfunction(cls) else cls.__init__
+ _, parameter_doc, return_doc, _ = document_fn(fn_to_document, cls)
+ cls_description, cls_tags, cls_example = document_cls(cls)
+ cls_documentation = {
+ "class": cls,
+ "name": cls.__name__,
+ "description": cls_description,
+ "tags": cls_tags,
+ "parameters": parameter_doc,
+ "returns": return_doc,
+ "example": cls_example,
+ "fns": [],
+ }
+ for fn_name in fns:
+ instance_attribute_fn = fn_name.startswith("*")
+ if instance_attribute_fn:
+ fn_name = fn_name[1:]
+ # Instance attribute fns are classes
+ # whose __call__ method determines their behavior
+ fn = getattr(cls(), fn_name).__call__
+ else:
+ fn = getattr(cls, fn_name)
+ if not callable(fn):
+ description_doc = str(fn)
+ parameter_docs = {}
+ return_docs = {}
+ examples_doc = ""
+ override_signature = f"gr.{cls.__name__}.{fn_name}"
+ else:
+ (
+ description_doc,
+ parameter_docs,
+ return_docs,
+ examples_doc,
+ ) = document_fn(fn, cls)
+ override_signature = None
+ if instance_attribute_fn:
+ description_doc = extract_instance_attr_doc(cls, fn_name)
+ cls_documentation["fns"].append(
+ {
+ "fn": fn,
+ "name": fn_name,
+ "description": description_doc,
+ "tags": {},
+ "parameters": parameter_docs,
+ "returns": return_docs,
+ "example": examples_doc,
+ "override_signature": override_signature,
+ }
+ )
+ documentation[mode].append(cls_documentation)
+ if cls in classes_inherit_documentation:
+ classes_inherit_documentation[cls] = cls_documentation["fns"]
+ for mode, class_list in classes_to_document.items():
+ for i, (cls, _) in enumerate(class_list):
+ for super_class in classes_inherit_documentation:
+ if (
+ inspect.isclass(cls)
+ and issubclass(cls, super_class)
+ and cls != super_class
+ ):
+ for inherited_fn in classes_inherit_documentation[super_class]:
+ inherited_fn = dict(inherited_fn)
+ try:
+ inherited_fn["description"] = extract_instance_attr_doc(
+ cls, inherited_fn["name"]
+ )
+ except (ValueError, AssertionError):
+ pass
+ documentation[mode][i]["fns"].append(inherited_fn)
+ return documentation
diff --git a/gradio/events.py b/gradio/events.py
new file mode 100644
index 0000000000000000000000000000000000000000..c19539e45c9332cf30db0d381e507c43e261aa5b
--- /dev/null
+++ b/gradio/events.py
@@ -0,0 +1,298 @@
+"""Contains all of the events that can be triggered in a gr.Blocks() app, with the exception
+of the on-page-load event, which is defined in gr.Blocks().load()."""
+
+from __future__ import annotations
+
+import warnings
+from typing import TYPE_CHECKING, Any, Callable, Dict, List, Set, Tuple
+
+from gradio.blocks import Block
+from gradio.documentation import document, set_documentation_group
+from gradio.helpers import EventData
+from gradio.utils import get_cancel_function
+
+if TYPE_CHECKING: # Only import for type checking (is False at runtime).
+ from gradio.components import Component, StatusTracker
+
+set_documentation_group("events")
+
+
+def set_cancel_events(
+ block: Block, event_name: str, cancels: None | Dict[str, Any] | List[Dict[str, Any]]
+):
+ if cancels:
+ if not isinstance(cancels, list):
+ cancels = [cancels]
+ cancel_fn, fn_indices_to_cancel = get_cancel_function(cancels)
+ block.set_event_trigger(
+ event_name,
+ cancel_fn,
+ inputs=None,
+ outputs=None,
+ queue=False,
+ preprocess=False,
+ cancels=fn_indices_to_cancel,
+ )
+
+
+class EventListener(Block):
+ def __init__(self: Any):
+ for event_listener_class in EventListener.__subclasses__():
+ if isinstance(self, event_listener_class):
+ event_listener_class.__init__(self)
+
+
+class Dependency(dict):
+ def __init__(self, trigger, key_vals, dep_index):
+ super().__init__(key_vals)
+ self.trigger = trigger
+ self.then = EventListenerMethod(
+ self.trigger,
+ "then",
+ trigger_after=dep_index,
+ trigger_only_on_success=False,
+ )
+ """
+ Triggered after directly preceding event is completed, regardless of success or failure.
+ """
+ self.success = EventListenerMethod(
+ self.trigger,
+ "success",
+ trigger_after=dep_index,
+ trigger_only_on_success=True,
+ )
+ """
+ Triggered after directly preceding event is completed, if it was successful.
+ """
+
+
+class EventListenerMethod:
+ """
+ Triggered on an event deployment.
+ """
+
+ def __init__(
+ self,
+ trigger: Block,
+ event_name: str,
+ show_progress: bool = True,
+ callback: Callable | None = None,
+ trigger_after: int | None = None,
+ trigger_only_on_success: bool = False,
+ ):
+ self.trigger = trigger
+ self.event_name = event_name
+ self.show_progress = show_progress
+ self.callback = callback
+ self.trigger_after = trigger_after
+ self.trigger_only_on_success = trigger_only_on_success
+
+ def __call__(
+ self,
+ fn: Callable | None,
+ inputs: Component | List[Component] | Set[Component] | None = None,
+ outputs: Component | List[Component] | None = None,
+ api_name: str | None = None,
+ status_tracker: StatusTracker | None = None,
+ scroll_to_output: bool = False,
+ show_progress: bool | None = None,
+ queue: bool | None = None,
+ batch: bool = False,
+ max_batch_size: int = 4,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ cancels: Dict[str, Any] | List[Dict[str, Any]] | None = None,
+ every: float | None = None,
+ _js: str | None = None,
+ ) -> Dependency:
+ """
+ Parameters:
+ fn: the function to wrap an interface around. Often a machine learning model's prediction function. Each parameter of the function corresponds to one input component, and the function should return a single value or a tuple of values, with each element in the tuple corresponding to one output component.
+ inputs: List of gradio.components to use as inputs. If the function takes no inputs, this should be an empty list.
+ outputs: List of gradio.components to use as outputs. If the function returns no outputs, this should be an empty list.
+ api_name: Defining this parameter exposes the endpoint in the api docs
+ scroll_to_output: If True, will scroll to output component on completion
+ show_progress: If True, will show progress animation while pending
+ queue: If True, will place the request on the queue, if the queue exists
+ batch: If True, then the function should process a batch of inputs, meaning that it should accept a list of input values for each parameter. The lists should be of equal length (and be up to length `max_batch_size`). The function is then *required* to return a tuple of lists (even if there is only 1 output component), with each list in the tuple corresponding to one output component.
+ max_batch_size: Maximum number of inputs to batch together if this is called from the queue (only relevant if batch=True)
+ preprocess: If False, will not run preprocessing of component data before running 'fn' (e.g. leaving it as a base64 string if this method is called with the `Image` component).
+ postprocess: If False, will not run postprocessing of component data before returning 'fn' output to the browser.
+ cancels: A list of other events to cancel when this event is triggered. For example, setting cancels=[click_event] will cancel the click_event, where click_event is the return value of another components .click method.
+ every: Run this event 'every' number of seconds while the client connection is open. Interpreted in seconds. Queue must be enabled.
+ """
+ # _js: Optional frontend js method to run before running 'fn'. Input arguments for js method are values of 'inputs' and 'outputs', return should be a list of values for output components.
+ if status_tracker:
+ warnings.warn(
+ "The 'status_tracker' parameter has been deprecated and has no effect."
+ )
+ dep, dep_index = self.trigger.set_event_trigger(
+ self.event_name,
+ fn,
+ inputs,
+ outputs,
+ preprocess=preprocess,
+ postprocess=postprocess,
+ scroll_to_output=scroll_to_output,
+ show_progress=show_progress
+ if show_progress is not None
+ else self.show_progress,
+ api_name=api_name,
+ js=_js,
+ queue=queue,
+ batch=batch,
+ max_batch_size=max_batch_size,
+ every=every,
+ trigger_after=self.trigger_after,
+ trigger_only_on_success=self.trigger_only_on_success,
+ )
+ set_cancel_events(self.trigger, self.event_name, cancels)
+ if self.callback:
+ self.callback()
+ return Dependency(self.trigger, dep, dep_index)
+
+
+@document("*change", inherit=True)
+class Changeable(EventListener):
+ def __init__(self):
+ self.change = EventListenerMethod(self, "change")
+ """
+ This event is triggered when the component's input value changes (e.g. when the user types in a textbox
+ or uploads an image). This method can be used when this component is in a Gradio Blocks.
+ """
+
+
+@document("*click", inherit=True)
+class Clickable(EventListener):
+ def __init__(self):
+ self.click = EventListenerMethod(self, "click")
+ """
+ This event is triggered when the component (e.g. a button) is clicked.
+ This method can be used when this component is in a Gradio Blocks.
+ """
+
+
+@document("*submit", inherit=True)
+class Submittable(EventListener):
+ def __init__(self):
+ self.submit = EventListenerMethod(self, "submit")
+ """
+ This event is triggered when the user presses the Enter key while the component (e.g. a textbox) is focused.
+ This method can be used when this component is in a Gradio Blocks.
+ """
+
+
+@document("*edit", inherit=True)
+class Editable(EventListener):
+ def __init__(self):
+ self.edit = EventListenerMethod(self, "edit")
+ """
+ This event is triggered when the user edits the component (e.g. image) using the
+ built-in editor. This method can be used when this component is in a Gradio Blocks.
+ """
+
+
+@document("*clear", inherit=True)
+class Clearable(EventListener):
+ def __init__(self):
+ self.clear = EventListenerMethod(self, "clear")
+ """
+ This event is triggered when the user clears the component (e.g. image or audio)
+ using the X button for the component. This method can be used when this component is in a Gradio Blocks.
+ """
+
+
+@document("*play", "*pause", "*stop", inherit=True)
+class Playable(EventListener):
+ def __init__(self):
+ self.play = EventListenerMethod(self, "play")
+ """
+ This event is triggered when the user plays the component (e.g. audio or video).
+ This method can be used when this component is in a Gradio Blocks.
+ """
+
+ self.pause = EventListenerMethod(self, "pause")
+ """
+ This event is triggered when the user pauses the component (e.g. audio or video).
+ This method can be used when this component is in a Gradio Blocks.
+ """
+
+ self.stop = EventListenerMethod(self, "stop")
+ """
+ This event is triggered when the user stops the component (e.g. audio or video).
+ This method can be used when this component is in a Gradio Blocks.
+ """
+
+
+@document("*stream", inherit=True)
+class Streamable(EventListener):
+ def __init__(self):
+ self.streaming: bool
+ self.stream = EventListenerMethod(
+ self,
+ "stream",
+ show_progress=False,
+ callback=lambda: setattr(self, "streaming", True),
+ )
+ """
+ This event is triggered when the user streams the component (e.g. a live webcam
+ component). This method can be used when this component is in a Gradio Blocks.
+ """
+
+
+@document("*blur", inherit=True)
+class Blurrable(EventListener):
+ def __init__(self):
+ self.blur = EventListenerMethod(self, "blur")
+ """
+ This event is triggered when the component's is unfocused/blurred (e.g. when the user clicks outside of a textbox). This method can be used when this component is in a Gradio Blocks.
+ """
+
+
+@document("*upload", inherit=True)
+class Uploadable(EventListener):
+ def __init__(self):
+ self.upload = EventListenerMethod(self, "upload")
+ """
+ This event is triggered when the user uploads a file into the component (e.g. when the user uploads a video into a video component). This method can be used when this component is in a Gradio Blocks.
+ """
+
+
+@document("*release", inherit=True)
+class Releaseable(EventListener):
+ def __init__(self):
+ self.release = EventListenerMethod(self, "release")
+ """
+ This event is triggered when the user releases the mouse on this component (e.g. when the user releases the slider). This method can be used when this component is in a Gradio Blocks.
+ """
+
+
+@document("*select", inherit=True)
+class Selectable(EventListener):
+ def __init__(self):
+ self.selectable: bool = False
+ self.select = EventListenerMethod(
+ self, "select", callback=lambda: setattr(self, "selectable", True)
+ )
+ """
+ This event is triggered when the user selects from within the Component.
+ This event has EventData of type gradio.SelectData that carries information, accessible through SelectData.index and SelectData.value.
+ See EventData documentation on how to use this event data.
+ """
+
+
+class SelectData(EventData):
+ def __init__(self, target: Block | None, data: Any):
+ super().__init__(target, data)
+ self.index: int | Tuple[int, int] = data["index"]
+ """
+ The index of the selected item. Is a tuple if the component is two dimensional or selection is a range.
+ """
+ self.value: Any = data["value"]
+ """
+ The value of the selected item.
+ """
+ self.selected: bool = data.get("selected", True)
+ """
+ True if the item was selected, False if deselected.
+ """
diff --git a/gradio/exceptions.py b/gradio/exceptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..54e582f58f964f34a5e1d87bf86ab2321af8538f
--- /dev/null
+++ b/gradio/exceptions.py
@@ -0,0 +1,39 @@
+from gradio.documentation import document, set_documentation_group
+
+set_documentation_group("helpers")
+
+
+class DuplicateBlockError(ValueError):
+ """Raised when a Blocks contains more than one Block with the same id"""
+
+ pass
+
+
+class TooManyRequestsError(Exception):
+ """Raised when the Hugging Face API returns a 429 status code."""
+
+ pass
+
+
+class InvalidApiName(ValueError):
+ pass
+
+
+@document()
+class Error(Exception):
+ """
+ This class allows you to pass custom error messages to the user. You can do so by raising a gr.Error("custom message") anywhere in the code, and when that line is executed the custom message will appear in a modal on the demo.
+
+ Demos: calculator
+ """
+
+ def __init__(self, message: str):
+ """
+ Parameters:
+ message: The error message to be displayed to the user.
+ """
+ self.message = message
+ super().__init__(self.message)
+
+ def __str__(self):
+ return repr(self.message)
diff --git a/gradio/external.py b/gradio/external.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e6686470910b232909a6fd2af1ef41e8c729b3d
--- /dev/null
+++ b/gradio/external.py
@@ -0,0 +1,512 @@
+"""This module should not be used directly as its API is subject to change. Instead,
+use the `gr.Blocks.load()` or `gr.Interface.load()` functions."""
+
+from __future__ import annotations
+
+import json
+import re
+import uuid
+import warnings
+from copy import deepcopy
+from typing import TYPE_CHECKING, Callable, Dict
+
+import requests
+
+import gradio
+from gradio import components, utils
+from gradio.context import Context
+from gradio.exceptions import Error, TooManyRequestsError
+from gradio.external_utils import (
+ cols_to_rows,
+ encode_to_base64,
+ get_tabular_examples,
+ get_ws_fn,
+ postprocess_label,
+ rows_to_cols,
+ streamline_spaces_interface,
+ use_websocket,
+)
+from gradio.processing_utils import to_binary
+
+if TYPE_CHECKING:
+ from gradio.blocks import Blocks
+ from gradio.interface import Interface
+
+
+def load_blocks_from_repo(
+ name: str,
+ src: str | None = None,
+ api_key: str | None = None,
+ alias: str | None = None,
+ **kwargs,
+) -> Blocks:
+ """Creates and returns a Blocks instance from a Hugging Face model or Space repo."""
+ if src is None:
+ # Separate the repo type (e.g. "model") from repo name (e.g. "google/vit-base-patch16-224")
+ tokens = name.split("/")
+ assert (
+ len(tokens) > 1
+ ), "Either `src` parameter must be provided, or `name` must be formatted as {src}/{repo name}"
+ src = tokens[0]
+ name = "/".join(tokens[1:])
+
+ factory_methods: Dict[str, Callable] = {
+ # for each repo type, we have a method that returns the Interface given the model name & optionally an api_key
+ "huggingface": from_model,
+ "models": from_model,
+ "spaces": from_spaces,
+ }
+ assert src.lower() in factory_methods, "parameter: src must be one of {}".format(
+ factory_methods.keys()
+ )
+
+ if api_key is not None:
+ if Context.access_token is not None and Context.access_token != api_key:
+ warnings.warn(
+ """You are loading a model/Space with a different access token than the one you used to load a previous model/Space. This is not recommended, as it may cause unexpected behavior."""
+ )
+ Context.access_token = api_key
+
+ blocks: gradio.Blocks = factory_methods[src](name, api_key, alias, **kwargs)
+ return blocks
+
+
+def chatbot_preprocess(text, state):
+ payload = {
+ "inputs": {"generated_responses": None, "past_user_inputs": None, "text": text}
+ }
+ if state is not None:
+ payload["inputs"]["generated_responses"] = state["conversation"][
+ "generated_responses"
+ ]
+ payload["inputs"]["past_user_inputs"] = state["conversation"][
+ "past_user_inputs"
+ ]
+
+ return payload
+
+
+def chatbot_postprocess(response):
+ response_json = response.json()
+ chatbot_value = list(
+ zip(
+ response_json["conversation"]["past_user_inputs"],
+ response_json["conversation"]["generated_responses"],
+ )
+ )
+ return chatbot_value, response_json
+
+
+def from_model(model_name: str, api_key: str | None, alias: str | None, **kwargs):
+ model_url = "https://huggingface.co/{}".format(model_name)
+ api_url = "https://api-inference.huggingface.co/models/{}".format(model_name)
+ print("Fetching model from: {}".format(model_url))
+
+ headers = {"Authorization": f"Bearer {api_key}"} if api_key is not None else {}
+
+ # Checking if model exists, and if so, it gets the pipeline
+ response = requests.request("GET", api_url, headers=headers)
+ assert (
+ response.status_code == 200
+ ), f"Could not find model: {model_name}. If it is a private or gated model, please provide your Hugging Face access token (https://huggingface.co/settings/tokens) as the argument for the `api_key` parameter."
+ p = response.json().get("pipeline_tag")
+ pipelines = {
+ "audio-classification": {
+ # example model: ehcalabres/wav2vec2-lg-xlsr-en-speech-emotion-recognition
+ "inputs": components.Audio(source="upload", type="filepath", label="Input"),
+ "outputs": components.Label(label="Class"),
+ "preprocess": lambda i: to_binary,
+ "postprocess": lambda r: postprocess_label(
+ {i["label"].split(", ")[0]: i["score"] for i in r.json()}
+ ),
+ },
+ "audio-to-audio": {
+ # example model: facebook/xm_transformer_sm_all-en
+ "inputs": components.Audio(source="upload", type="filepath", label="Input"),
+ "outputs": components.Audio(label="Output"),
+ "preprocess": to_binary,
+ "postprocess": encode_to_base64,
+ },
+ "automatic-speech-recognition": {
+ # example model: facebook/wav2vec2-base-960h
+ "inputs": components.Audio(source="upload", type="filepath", label="Input"),
+ "outputs": components.Textbox(label="Output"),
+ "preprocess": to_binary,
+ "postprocess": lambda r: r.json()["text"],
+ },
+ "conversational": {
+ "inputs": [components.Textbox(), components.State()], # type: ignore
+ "outputs": [components.Chatbot(), components.State()], # type: ignore
+ "preprocess": chatbot_preprocess,
+ "postprocess": chatbot_postprocess,
+ },
+ "feature-extraction": {
+ # example model: julien-c/distilbert-feature-extraction
+ "inputs": components.Textbox(label="Input"),
+ "outputs": components.Dataframe(label="Output"),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r.json()[0],
+ },
+ "fill-mask": {
+ "inputs": components.Textbox(label="Input"),
+ "outputs": components.Label(label="Classification"),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: postprocess_label(
+ {i["token_str"]: i["score"] for i in r.json()}
+ ),
+ },
+ "image-classification": {
+ # Example: google/vit-base-patch16-224
+ "inputs": components.Image(type="filepath", label="Input Image"),
+ "outputs": components.Label(label="Classification"),
+ "preprocess": to_binary,
+ "postprocess": lambda r: postprocess_label(
+ {i["label"].split(", ")[0]: i["score"] for i in r.json()}
+ ),
+ },
+ "image-to-text": {
+ "inputs": components.Image(type="filepath", label="Input Image"),
+ "outputs": components.Textbox(),
+ "preprocess": to_binary,
+ "postprocess": lambda r: r.json()[0]["generated_text"],
+ },
+ "question-answering": {
+ # Example: deepset/xlm-roberta-base-squad2
+ "inputs": [
+ components.Textbox(lines=7, label="Context"),
+ components.Textbox(label="Question"),
+ ],
+ "outputs": [
+ components.Textbox(label="Answer"),
+ components.Label(label="Score"),
+ ],
+ "preprocess": lambda c, q: {"inputs": {"context": c, "question": q}},
+ "postprocess": lambda r: (r.json()["answer"], {"label": r.json()["score"]}),
+ },
+ "summarization": {
+ # Example: facebook/bart-large-cnn
+ "inputs": components.Textbox(label="Input"),
+ "outputs": components.Textbox(label="Summary"),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r.json()[0]["summary_text"],
+ },
+ "text-classification": {
+ # Example: distilbert-base-uncased-finetuned-sst-2-english
+ "inputs": components.Textbox(label="Input"),
+ "outputs": components.Label(label="Classification"),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: postprocess_label(
+ {i["label"].split(", ")[0]: i["score"] for i in r.json()[0]}
+ ),
+ },
+ "text-generation": {
+ # Example: gpt2
+ "inputs": components.Textbox(label="Input"),
+ "outputs": components.Textbox(label="Output"),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r.json()[0]["generated_text"],
+ },
+ "text2text-generation": {
+ # Example: valhalla/t5-small-qa-qg-hl
+ "inputs": components.Textbox(label="Input"),
+ "outputs": components.Textbox(label="Generated Text"),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r.json()[0]["generated_text"],
+ },
+ "translation": {
+ "inputs": components.Textbox(label="Input"),
+ "outputs": components.Textbox(label="Translation"),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r.json()[0]["translation_text"],
+ },
+ "zero-shot-classification": {
+ # Example: facebook/bart-large-mnli
+ "inputs": [
+ components.Textbox(label="Input"),
+ components.Textbox(label="Possible class names (" "comma-separated)"),
+ components.Checkbox(label="Allow multiple true classes"),
+ ],
+ "outputs": components.Label(label="Classification"),
+ "preprocess": lambda i, c, m: {
+ "inputs": i,
+ "parameters": {"candidate_labels": c, "multi_class": m},
+ },
+ "postprocess": lambda r: postprocess_label(
+ {
+ r.json()["labels"][i]: r.json()["scores"][i]
+ for i in range(len(r.json()["labels"]))
+ }
+ ),
+ },
+ "sentence-similarity": {
+ # Example: sentence-transformers/distilbert-base-nli-stsb-mean-tokens
+ "inputs": [
+ components.Textbox(
+ value="That is a happy person", label="Source Sentence"
+ ),
+ components.Textbox(
+ lines=7,
+ placeholder="Separate each sentence by a newline",
+ label="Sentences to compare to",
+ ),
+ ],
+ "outputs": components.Label(label="Classification"),
+ "preprocess": lambda src, sentences: {
+ "inputs": {
+ "source_sentence": src,
+ "sentences": [s for s in sentences.splitlines() if s != ""],
+ }
+ },
+ "postprocess": lambda r: postprocess_label(
+ {f"sentence {i}": v for i, v in enumerate(r.json())}
+ ),
+ },
+ "text-to-speech": {
+ # Example: julien-c/ljspeech_tts_train_tacotron2_raw_phn_tacotron_g2p_en_no_space_train
+ "inputs": components.Textbox(label="Input"),
+ "outputs": components.Audio(label="Audio"),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": encode_to_base64,
+ },
+ "text-to-image": {
+ # example model: osanseviero/BigGAN-deep-128
+ "inputs": components.Textbox(label="Input"),
+ "outputs": components.Image(label="Output"),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": encode_to_base64,
+ },
+ "token-classification": {
+ # example model: huggingface-course/bert-finetuned-ner
+ "inputs": components.Textbox(label="Input"),
+ "outputs": components.HighlightedText(label="Output"),
+ "preprocess": lambda x: {"inputs": x},
+ "postprocess": lambda r: r, # Handled as a special case in query_huggingface_api()
+ },
+ }
+
+ if p in ["tabular-classification", "tabular-regression"]:
+ example_data = get_tabular_examples(model_name)
+ col_names, example_data = cols_to_rows(example_data)
+ example_data = [[example_data]] if example_data else None
+
+ pipelines[p] = {
+ "inputs": components.Dataframe(
+ label="Input Rows",
+ type="pandas",
+ headers=col_names,
+ col_count=(len(col_names), "fixed"),
+ ),
+ "outputs": components.Dataframe(
+ label="Predictions", type="array", headers=["prediction"]
+ ),
+ "preprocess": rows_to_cols,
+ "postprocess": lambda r: {
+ "headers": ["prediction"],
+ "data": [[pred] for pred in json.loads(r.text)],
+ },
+ "examples": example_data,
+ }
+
+ if p is None or not (p in pipelines):
+ raise ValueError("Unsupported pipeline type: {}".format(p))
+
+ pipeline = pipelines[p]
+
+ def query_huggingface_api(*params):
+ # Convert to a list of input components
+ data = pipeline["preprocess"](*params)
+ if isinstance(
+ data, dict
+ ): # HF doesn't allow additional parameters for binary files (e.g. images or audio files)
+ data.update({"options": {"wait_for_model": True}})
+ data = json.dumps(data)
+ response = requests.request("POST", api_url, headers=headers, data=data)
+ if not (response.status_code == 200):
+ errors_json = response.json()
+ errors, warns = "", ""
+ if errors_json.get("error"):
+ errors = f", Error: {errors_json.get('error')}"
+ if errors_json.get("warnings"):
+ warns = f", Warnings: {errors_json.get('warnings')}"
+ raise Error(
+ f"Could not complete request to HuggingFace API, Status Code: {response.status_code}"
+ + errors
+ + warns
+ )
+ if (
+ p == "token-classification"
+ ): # Handle as a special case since HF API only returns the named entities and we need the input as well
+ ner_groups = response.json()
+ input_string = params[0]
+ response = utils.format_ner_list(input_string, ner_groups)
+ output = pipeline["postprocess"](response)
+ return output
+
+ if alias is None:
+ query_huggingface_api.__name__ = model_name
+ else:
+ query_huggingface_api.__name__ = alias
+
+ interface_info = {
+ "fn": query_huggingface_api,
+ "inputs": pipeline["inputs"],
+ "outputs": pipeline["outputs"],
+ "title": model_name,
+ "examples": pipeline.get("examples"),
+ }
+
+ kwargs = dict(interface_info, **kwargs)
+
+ # So interface doesn't run pre/postprocess
+ # except for conversational interfaces which
+ # are stateful
+ kwargs["_api_mode"] = p != "conversational"
+
+ interface = gradio.Interface(**kwargs)
+ return interface
+
+
+def from_spaces(
+ space_name: str, api_key: str | None, alias: str | None, **kwargs
+) -> Blocks:
+ space_url = "https://huggingface.co/spaces/{}".format(space_name)
+
+ print("Fetching Space from: {}".format(space_url))
+
+ headers = {}
+ if api_key is not None:
+ headers["Authorization"] = f"Bearer {api_key}"
+
+ iframe_url = (
+ requests.get(
+ f"https://huggingface.co/api/spaces/{space_name}/host", headers=headers
+ )
+ .json()
+ .get("host")
+ )
+
+ if iframe_url is None:
+ raise ValueError(
+ f"Could not find Space: {space_name}. If it is a private or gated Space, please provide your Hugging Face access token (https://huggingface.co/settings/tokens) as the argument for the `api_key` parameter."
+ )
+
+ r = requests.get(iframe_url, headers=headers)
+
+ result = re.search(
+ r"window.gradio_config = (.*?);[\s]*", r.text
+ ) # some basic regex to extract the config
+ try:
+ config = json.loads(result.group(1)) # type: ignore
+ except AttributeError:
+ raise ValueError("Could not load the Space: {}".format(space_name))
+ if "allow_flagging" in config: # Create an Interface for Gradio 2.x Spaces
+ return from_spaces_interface(
+ space_name, config, alias, api_key, iframe_url, **kwargs
+ )
+ else: # Create a Blocks for Gradio 3.x Spaces
+ if kwargs:
+ warnings.warn(
+ "You cannot override parameters for this Space by passing in kwargs. "
+ "Instead, please load the Space as a function and use it to create a "
+ "Blocks or Interface locally. You may find this Guide helpful: "
+ "https://gradio.app/using_blocks_like_functions/"
+ )
+ return from_spaces_blocks(config, api_key, iframe_url)
+
+
+def from_spaces_blocks(config: Dict, api_key: str | None, iframe_url: str) -> Blocks:
+ api_url = "{}/api/predict/".format(iframe_url)
+
+ headers = {"Content-Type": "application/json"}
+ if api_key is not None:
+ headers["Authorization"] = f"Bearer {api_key}"
+ ws_url = "{}/queue/join".format(iframe_url).replace("https", "wss")
+
+ ws_fn = get_ws_fn(ws_url, headers)
+
+ fns = []
+ for d, dependency in enumerate(config["dependencies"]):
+ if dependency["backend_fn"]:
+
+ def get_fn(outputs, fn_index, use_ws):
+ def fn(*data):
+ data = json.dumps({"data": data, "fn_index": fn_index})
+ hash_data = json.dumps(
+ {"fn_index": fn_index, "session_hash": str(uuid.uuid4())}
+ )
+ if use_ws:
+ result = utils.synchronize_async(ws_fn, data, hash_data)
+ output = result["data"]
+ else:
+ response = requests.post(api_url, headers=headers, data=data)
+ result = json.loads(response.content.decode("utf-8"))
+ try:
+ output = result["data"]
+ except KeyError:
+ if "error" in result and "429" in result["error"]:
+ raise TooManyRequestsError(
+ "Too many requests to the Hugging Face API"
+ )
+ raise KeyError(
+ f"Could not find 'data' key in response from external Space. Response received: {result}"
+ )
+ if len(outputs) == 1:
+ output = output[0]
+ return output
+
+ return fn
+
+ fn = get_fn(
+ deepcopy(dependency["outputs"]), d, use_websocket(config, dependency)
+ )
+ fns.append(fn)
+ else:
+ fns.append(None)
+ return gradio.Blocks.from_config(config, fns, iframe_url)
+
+
+def from_spaces_interface(
+ model_name: str,
+ config: Dict,
+ alias: str | None,
+ api_key: str | None,
+ iframe_url: str,
+ **kwargs,
+) -> Interface:
+
+ config = streamline_spaces_interface(config)
+ api_url = "{}/api/predict/".format(iframe_url)
+ headers = {"Content-Type": "application/json"}
+ if api_key is not None:
+ headers["Authorization"] = f"Bearer {api_key}"
+
+ # The function should call the API with preprocessed data
+ def fn(*data):
+ data = json.dumps({"data": data})
+ response = requests.post(api_url, headers=headers, data=data)
+ result = json.loads(response.content.decode("utf-8"))
+ try:
+ output = result["data"]
+ except KeyError:
+ if "error" in result and "429" in result["error"]:
+ raise TooManyRequestsError("Too many requests to the Hugging Face API")
+ raise KeyError(
+ f"Could not find 'data' key in response from external Space. Response received: {result}"
+ )
+ if (
+ len(config["outputs"]) == 1
+ ): # if the fn is supposed to return a single value, pop it
+ output = output[0]
+ if len(config["outputs"]) == 1 and isinstance(
+ output, list
+ ): # Needed to support Output.Image() returning bounding boxes as well (TODO: handle different versions of gradio since they have slightly different APIs)
+ output = output[0]
+ return output
+
+ fn.__name__ = alias if (alias is not None) else model_name
+ config["fn"] = fn
+
+ kwargs = dict(config, **kwargs)
+ kwargs["_api_mode"] = True
+ interface = gradio.Interface(**kwargs)
+ return interface
diff --git a/gradio/external_utils.py b/gradio/external_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..82294add0fe12ea33f6e7e9846488f7338e6d14e
--- /dev/null
+++ b/gradio/external_utils.py
@@ -0,0 +1,185 @@
+"""Utility function for gradio/external.py"""
+
+import base64
+import json
+import math
+import operator
+import re
+import warnings
+from typing import Any, Dict, List, Tuple
+
+import requests
+import websockets
+import yaml
+from packaging import version
+from websockets.legacy.protocol import WebSocketCommonProtocol
+
+from gradio import components, exceptions
+
+##################
+# Helper functions for processing tabular data
+##################
+
+
+def get_tabular_examples(model_name: str) -> Dict[str, List[float]]:
+ readme = requests.get(f"https://huggingface.co/{model_name}/resolve/main/README.md")
+ if readme.status_code != 200:
+ warnings.warn(f"Cannot load examples from README for {model_name}", UserWarning)
+ example_data = {}
+ else:
+ yaml_regex = re.search(
+ "(?:^|[\r\n])---[\n\r]+([\\S\\s]*?)[\n\r]+---([\n\r]|$)", readme.text
+ )
+ if yaml_regex is None:
+ example_data = {}
+ else:
+ example_yaml = next(
+ yaml.safe_load_all(readme.text[: yaml_regex.span()[-1]])
+ )
+ example_data = example_yaml.get("widget", {}).get("structuredData", {})
+ if not example_data:
+ raise ValueError(
+ f"No example data found in README.md of {model_name} - Cannot build gradio demo. "
+ "See the README.md here: https://huggingface.co/scikit-learn/tabular-playground/blob/main/README.md "
+ "for a reference on how to provide example data to your model."
+ )
+ # replace nan with string NaN for inference API
+ for data in example_data.values():
+ for i, val in enumerate(data):
+ if isinstance(val, float) and math.isnan(val):
+ data[i] = "NaN"
+ return example_data
+
+
+def cols_to_rows(
+ example_data: Dict[str, List[float]]
+) -> Tuple[List[str], List[List[float]]]:
+ headers = list(example_data.keys())
+ n_rows = max(len(example_data[header] or []) for header in headers)
+ data = []
+ for row_index in range(n_rows):
+ row_data = []
+ for header in headers:
+ col = example_data[header] or []
+ if row_index >= len(col):
+ row_data.append("NaN")
+ else:
+ row_data.append(col[row_index])
+ data.append(row_data)
+ return headers, data
+
+
+def rows_to_cols(incoming_data: Dict) -> Dict[str, Dict[str, Dict[str, List[str]]]]:
+ data_column_wise = {}
+ for i, header in enumerate(incoming_data["headers"]):
+ data_column_wise[header] = [str(row[i]) for row in incoming_data["data"]]
+ return {"inputs": {"data": data_column_wise}}
+
+
+##################
+# Helper functions for processing other kinds of data
+##################
+
+
+def postprocess_label(scores: Dict) -> Dict:
+ sorted_pred = sorted(scores.items(), key=operator.itemgetter(1), reverse=True)
+ return {
+ "label": sorted_pred[0][0],
+ "confidences": [
+ {"label": pred[0], "confidence": pred[1]} for pred in sorted_pred
+ ],
+ }
+
+
+def encode_to_base64(r: requests.Response) -> str:
+ # Handles the different ways HF API returns the prediction
+ base64_repr = base64.b64encode(r.content).decode("utf-8")
+ data_prefix = ";base64,"
+ # Case 1: base64 representation already includes data prefix
+ if data_prefix in base64_repr:
+ return base64_repr
+ else:
+ content_type = r.headers.get("content-type")
+ # Case 2: the data prefix is a key in the response
+ if content_type == "application/json":
+ try:
+ content_type = r.json()[0]["content-type"]
+ base64_repr = r.json()[0]["blob"]
+ except KeyError:
+ raise ValueError(
+ "Cannot determine content type returned" "by external API."
+ )
+ # Case 3: the data prefix is included in the response headers
+ else:
+ pass
+ new_base64 = "data:{};base64,".format(content_type) + base64_repr
+ return new_base64
+
+
+##################
+# Helper functions for connecting to websockets
+##################
+
+
+async def get_pred_from_ws(
+ websocket: WebSocketCommonProtocol, data: str, hash_data: str
+) -> Dict[str, Any]:
+ completed = False
+ resp = {}
+ while not completed:
+ msg = await websocket.recv()
+ resp = json.loads(msg)
+ if resp["msg"] == "queue_full":
+ raise exceptions.Error("Queue is full! Please try again.")
+ if resp["msg"] == "send_hash":
+ await websocket.send(hash_data)
+ elif resp["msg"] == "send_data":
+ await websocket.send(data)
+ completed = resp["msg"] == "process_completed"
+ return resp["output"]
+
+
+def get_ws_fn(ws_url, headers):
+ async def ws_fn(data, hash_data):
+ async with websockets.connect( # type: ignore
+ ws_url, open_timeout=10, extra_headers=headers
+ ) as websocket:
+ return await get_pred_from_ws(websocket, data, hash_data)
+
+ return ws_fn
+
+
+def use_websocket(config, dependency):
+ queue_enabled = config.get("enable_queue", False)
+ queue_uses_websocket = version.parse(
+ config.get("version", "2.0")
+ ) >= version.Version("3.2")
+ dependency_uses_queue = dependency.get("queue", False) is not False
+ return queue_enabled and queue_uses_websocket and dependency_uses_queue
+
+
+##################
+# Helper function for cleaning up an Interface loaded from HF Spaces
+##################
+
+
+def streamline_spaces_interface(config: Dict) -> Dict:
+ """Streamlines the interface config dictionary to remove unnecessary keys."""
+ config["inputs"] = [
+ components.get_component_instance(component)
+ for component in config["input_components"]
+ ]
+ config["outputs"] = [
+ components.get_component_instance(component)
+ for component in config["output_components"]
+ ]
+ parameters = {
+ "article",
+ "description",
+ "flagging_options",
+ "inputs",
+ "outputs",
+ "title",
+ }
+ config = {k: config[k] for k in parameters}
+ return config
diff --git a/gradio/flagging.py b/gradio/flagging.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc19927d9812ed00826145b221240b969170f5a1
--- /dev/null
+++ b/gradio/flagging.py
@@ -0,0 +1,555 @@
+from __future__ import annotations
+
+import csv
+import datetime
+import json
+import os
+import time
+import uuid
+from abc import ABC, abstractmethod
+from distutils.version import StrictVersion
+from pathlib import Path
+from typing import TYPE_CHECKING, Any, List
+
+import pkg_resources
+
+import gradio as gr
+from gradio import utils
+from gradio.documentation import document, set_documentation_group
+
+if TYPE_CHECKING:
+ from gradio.components import IOComponent
+
+set_documentation_group("flagging")
+
+
+def _get_dataset_features_info(is_new, components):
+ """
+ Takes in a list of components and returns a dataset features info
+
+ Parameters:
+ is_new: boolean, whether the dataset is new or not
+ components: list of components
+
+ Returns:
+ infos: a dictionary of the dataset features
+ file_preview_types: dictionary mapping of gradio components to appropriate string.
+ header: list of header strings
+
+ """
+ infos = {"flagged": {"features": {}}}
+ # File previews for certain input and output types
+ file_preview_types = {gr.Audio: "Audio", gr.Image: "Image"}
+ headers = []
+
+ # Generate the headers and dataset_infos
+ if is_new:
+
+ for component in components:
+ headers.append(component.label)
+ infos["flagged"]["features"][component.label] = {
+ "dtype": "string",
+ "_type": "Value",
+ }
+ if isinstance(component, tuple(file_preview_types)):
+ headers.append(component.label + " file")
+ for _component, _type in file_preview_types.items():
+ if isinstance(component, _component):
+ infos["flagged"]["features"][
+ (component.label or "") + " file"
+ ] = {"_type": _type}
+ break
+
+ headers.append("flag")
+ infos["flagged"]["features"]["flag"] = {
+ "dtype": "string",
+ "_type": "Value",
+ }
+
+ return infos, file_preview_types, headers
+
+
+class FlaggingCallback(ABC):
+ """
+ An abstract class for defining the methods that any FlaggingCallback should have.
+ """
+
+ @abstractmethod
+ def setup(self, components: List[IOComponent], flagging_dir: str):
+ """
+ This method should be overridden and ensure that everything is set up correctly for flag().
+ This method gets called once at the beginning of the Interface.launch() method.
+ Parameters:
+ components: Set of components that will provide flagged data.
+ flagging_dir: A string, typically containing the path to the directory where the flagging file should be storied (provided as an argument to Interface.__init__()).
+ """
+ pass
+
+ @abstractmethod
+ def flag(
+ self,
+ flag_data: List[Any],
+ flag_option: str = "",
+ username: str | None = None,
+ ) -> int:
+ """
+ This method should be overridden by the FlaggingCallback subclass and may contain optional additional arguments.
+ This gets called every time the button is pressed.
+ Parameters:
+ interface: The Interface object that is being used to launch the flagging interface.
+ flag_data: The data to be flagged.
+ flag_option (optional): In the case that flagging_options are provided, the flag option that is being used.
+ username (optional): The username of the user that is flagging the data, if logged in.
+ Returns:
+ (int) The total number of samples that have been flagged.
+ """
+ pass
+
+
+@document()
+class SimpleCSVLogger(FlaggingCallback):
+ """
+ A simplified implementation of the FlaggingCallback abstract class
+ provided for illustrative purposes. Each flagged sample (both the input and output data)
+ is logged to a CSV file on the machine running the gradio app.
+ Example:
+ import gradio as gr
+ def image_classifier(inp):
+ return {'cat': 0.3, 'dog': 0.7}
+ demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label",
+ flagging_callback=SimpleCSVLogger())
+ """
+
+ def __init__(self):
+ pass
+
+ def setup(self, components: List[IOComponent], flagging_dir: str | Path):
+ self.components = components
+ self.flagging_dir = flagging_dir
+ os.makedirs(flagging_dir, exist_ok=True)
+
+ def flag(
+ self,
+ flag_data: List[Any],
+ flag_option: str = "",
+ username: str | None = None,
+ ) -> int:
+ flagging_dir = self.flagging_dir
+ log_filepath = Path(flagging_dir) / "log.csv"
+
+ csv_data = []
+ for component, sample in zip(self.components, flag_data):
+ save_dir = Path(flagging_dir) / utils.strip_invalid_filename_characters(
+ component.label or ""
+ )
+ csv_data.append(
+ component.deserialize(
+ sample,
+ save_dir,
+ None,
+ )
+ )
+
+ with open(log_filepath, "a", newline="") as csvfile:
+ writer = csv.writer(csvfile)
+ writer.writerow(utils.sanitize_list_for_csv(csv_data))
+
+ with open(log_filepath, "r") as csvfile:
+ line_count = len([None for row in csv.reader(csvfile)]) - 1
+ return line_count
+
+
+@document()
+class CSVLogger(FlaggingCallback):
+ """
+ The default implementation of the FlaggingCallback abstract class. Each flagged
+ sample (both the input and output data) is logged to a CSV file with headers on the machine running the gradio app.
+ Example:
+ import gradio as gr
+ def image_classifier(inp):
+ return {'cat': 0.3, 'dog': 0.7}
+ demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label",
+ flagging_callback=CSVLogger())
+ Guides: using_flagging
+ """
+
+ def __init__(self):
+ pass
+
+ def setup(
+ self,
+ components: List[IOComponent],
+ flagging_dir: str | Path,
+ ):
+ self.components = components
+ self.flagging_dir = flagging_dir
+ os.makedirs(flagging_dir, exist_ok=True)
+
+ def flag(
+ self,
+ flag_data: List[Any],
+ flag_option: str = "",
+ username: str | None = None,
+ ) -> int:
+ flagging_dir = self.flagging_dir
+ log_filepath = Path(flagging_dir) / "log.csv"
+ is_new = not Path(log_filepath).exists()
+ headers = [
+ getattr(component, "label", None) or f"component {idx}"
+ for idx, component in enumerate(self.components)
+ ] + [
+ "flag",
+ "username",
+ "timestamp",
+ ]
+
+ csv_data = []
+ for idx, (component, sample) in enumerate(zip(self.components, flag_data)):
+ save_dir = Path(flagging_dir) / utils.strip_invalid_filename_characters(
+ getattr(component, "label", None) or f"component {idx}"
+ )
+ if utils.is_update(sample):
+ csv_data.append(str(sample))
+ else:
+ csv_data.append(
+ component.deserialize(sample, save_dir=save_dir)
+ if sample is not None
+ else ""
+ )
+ csv_data.append(flag_option)
+ csv_data.append(username if username is not None else "")
+ csv_data.append(str(datetime.datetime.now()))
+
+ with open(log_filepath, "a", newline="", encoding="utf-8") as csvfile:
+ writer = csv.writer(csvfile)
+ if is_new:
+ writer.writerow(utils.sanitize_list_for_csv(headers))
+ writer.writerow(utils.sanitize_list_for_csv(csv_data))
+
+ with open(log_filepath, "r", encoding="utf-8") as csvfile:
+ line_count = len([None for row in csv.reader(csvfile)]) - 1
+ return line_count
+
+
+@document()
+class HuggingFaceDatasetSaver(FlaggingCallback):
+ """
+ A callback that saves each flagged sample (both the input and output data)
+ to a HuggingFace dataset.
+ Example:
+ import gradio as gr
+ hf_writer = gr.HuggingFaceDatasetSaver(HF_API_TOKEN, "image-classification-mistakes")
+ def image_classifier(inp):
+ return {'cat': 0.3, 'dog': 0.7}
+ demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label",
+ allow_flagging="manual", flagging_callback=hf_writer)
+ Guides: using_flagging
+ """
+
+ def __init__(
+ self,
+ hf_token: str,
+ dataset_name: str,
+ organization: str | None = None,
+ private: bool = False,
+ ):
+ """
+ Parameters:
+ hf_token: The HuggingFace token to use to create (and write the flagged sample to) the HuggingFace dataset.
+ dataset_name: The name of the dataset to save the data to, e.g. "image-classifier-1"
+ organization: The organization to save the dataset under. The hf_token must provide write access to this organization. If not provided, saved under the name of the user corresponding to the hf_token.
+ private: Whether the dataset should be private (defaults to False).
+ """
+ self.hf_token = hf_token
+ self.dataset_name = dataset_name
+ self.organization_name = organization
+ self.dataset_private = private
+
+ def setup(self, components: List[IOComponent], flagging_dir: str):
+ """
+ Params:
+ flagging_dir (str): local directory where the dataset is cloned,
+ updated, and pushed from.
+ """
+ try:
+ import huggingface_hub
+ except (ImportError, ModuleNotFoundError):
+ raise ImportError(
+ "Package `huggingface_hub` not found is needed "
+ "for HuggingFaceDatasetSaver. Try 'pip install huggingface_hub'."
+ )
+ hh_version = pkg_resources.get_distribution("huggingface_hub").version
+ try:
+ if StrictVersion(hh_version) < StrictVersion("0.6.0"):
+ raise ImportError(
+ "The `huggingface_hub` package must be version 0.6.0 or higher"
+ "for HuggingFaceDatasetSaver. Try 'pip install huggingface_hub --upgrade'."
+ )
+ except ValueError:
+ pass
+ repo_id = huggingface_hub.get_full_repo_name(
+ self.dataset_name, token=self.hf_token
+ )
+ path_to_dataset_repo = huggingface_hub.create_repo(
+ repo_id=repo_id,
+ token=self.hf_token,
+ private=self.dataset_private,
+ repo_type="dataset",
+ exist_ok=True,
+ )
+ self.path_to_dataset_repo = path_to_dataset_repo # e.g. "https://huggingface.co/datasets/abidlabs/test-audio-10"
+ self.components = components
+ self.flagging_dir = flagging_dir
+ self.dataset_dir = Path(flagging_dir) / self.dataset_name
+ self.repo = huggingface_hub.Repository(
+ local_dir=str(self.dataset_dir),
+ clone_from=path_to_dataset_repo,
+ use_auth_token=self.hf_token,
+ )
+ self.repo.git_pull(lfs=True)
+
+ # Should filename be user-specified?
+ self.log_file = Path(self.dataset_dir) / "data.csv"
+ self.infos_file = Path(self.dataset_dir) / "dataset_infos.json"
+
+ def flag(
+ self,
+ flag_data: List[Any],
+ flag_option: str = "",
+ username: str | None = None,
+ ) -> int:
+ self.repo.git_pull(lfs=True)
+
+ is_new = not Path(self.log_file).exists()
+
+ with open(self.log_file, "a", newline="", encoding="utf-8") as csvfile:
+ writer = csv.writer(csvfile)
+
+ # File previews for certain input and output types
+ infos, file_preview_types, headers = _get_dataset_features_info(
+ is_new, self.components
+ )
+
+ # Generate the headers and dataset_infos
+ if is_new:
+ writer.writerow(utils.sanitize_list_for_csv(headers))
+
+ # Generate the row corresponding to the flagged sample
+ csv_data = []
+ for component, sample in zip(self.components, flag_data):
+ save_dir = Path(
+ self.dataset_dir
+ ) / utils.strip_invalid_filename_characters(component.label or "")
+ filepath = component.deserialize(sample, save_dir, None)
+ csv_data.append(filepath)
+ if isinstance(component, tuple(file_preview_types)):
+ csv_data.append(
+ "{}/resolve/main/{}".format(self.path_to_dataset_repo, filepath)
+ )
+ csv_data.append(flag_option)
+ writer.writerow(utils.sanitize_list_for_csv(csv_data))
+
+ if is_new:
+ json.dump(infos, open(self.infos_file, "w"))
+
+ with open(self.log_file, "r", encoding="utf-8") as csvfile:
+ line_count = len([None for row in csv.reader(csvfile)]) - 1
+
+ self.repo.push_to_hub(commit_message="Flagged sample #{}".format(line_count))
+
+ return line_count
+
+
+class HuggingFaceDatasetJSONSaver(FlaggingCallback):
+ """
+ A FlaggingCallback that saves flagged data to a Hugging Face dataset in JSONL format.
+
+ Each data sample is saved in a different JSONL file,
+ allowing multiple users to use flagging simultaneously.
+ Saving to a single CSV would cause errors as only one user can edit at the same time.
+
+ """
+
+ def __init__(
+ self,
+ hf_token: str,
+ dataset_name: str,
+ organization: str | None = None,
+ private: bool = False,
+ verbose: bool = True,
+ ):
+ """
+ Params:
+ hf_token (str): The token to use to access the huggingface API.
+ dataset_name (str): The name of the dataset to save the data to, e.g.
+ "image-classifier-1"
+ organization (str): The name of the organization to which to attach
+ the datasets. If None, the dataset attaches to the user only.
+ private (bool): If the dataset does not already exist, whether it
+ should be created as a private dataset or public. Private datasets
+ may require paid huggingface.co accounts
+ verbose (bool): Whether to print out the status of the dataset
+ creation.
+ """
+ self.hf_token = hf_token
+ self.dataset_name = dataset_name
+ self.organization_name = organization
+ self.dataset_private = private
+ self.verbose = verbose
+
+ def setup(self, components: List[IOComponent], flagging_dir: str):
+ """
+ Params:
+ components List[Component]: list of components for flagging
+ flagging_dir (str): local directory where the dataset is cloned,
+ updated, and pushed from.
+ """
+ try:
+ import huggingface_hub
+ except (ImportError, ModuleNotFoundError):
+ raise ImportError(
+ "Package `huggingface_hub` not found is needed "
+ "for HuggingFaceDatasetJSONSaver. Try 'pip install huggingface_hub'."
+ )
+ hh_version = pkg_resources.get_distribution("huggingface_hub").version
+ try:
+ if StrictVersion(hh_version) < StrictVersion("0.6.0"):
+ raise ImportError(
+ "The `huggingface_hub` package must be version 0.6.0 or higher"
+ "for HuggingFaceDatasetSaver. Try 'pip install huggingface_hub --upgrade'."
+ )
+ except ValueError:
+ pass
+ repo_id = huggingface_hub.get_full_repo_name(
+ self.dataset_name, token=self.hf_token
+ )
+ path_to_dataset_repo = huggingface_hub.create_repo(
+ repo_id=repo_id,
+ token=self.hf_token,
+ private=self.dataset_private,
+ repo_type="dataset",
+ exist_ok=True,
+ )
+ self.path_to_dataset_repo = path_to_dataset_repo # e.g. "https://huggingface.co/datasets/abidlabs/test-audio-10"
+ self.components = components
+ self.flagging_dir = flagging_dir
+ self.dataset_dir = Path(flagging_dir) / self.dataset_name
+ self.repo = huggingface_hub.Repository(
+ local_dir=str(self.dataset_dir),
+ clone_from=path_to_dataset_repo,
+ use_auth_token=self.hf_token,
+ )
+ self.repo.git_pull(lfs=True)
+
+ self.infos_file = Path(self.dataset_dir) / "dataset_infos.json"
+
+ def flag(
+ self,
+ flag_data: List[Any],
+ flag_option: str = "",
+ username: str | None = None,
+ ) -> str:
+ self.repo.git_pull(lfs=True)
+
+ # Generate unique folder for the flagged sample
+ unique_name = self.get_unique_name() # unique name for folder
+ folder_name = (
+ Path(self.dataset_dir) / unique_name
+ ) # unique folder for specific example
+ os.makedirs(folder_name)
+
+ # Now uses the existence of `dataset_infos.json` to determine if new
+ is_new = not Path(self.infos_file).exists()
+
+ # File previews for certain input and output types
+ infos, file_preview_types, _ = _get_dataset_features_info(
+ is_new, self.components
+ )
+
+ # Generate the row and header corresponding to the flagged sample
+ csv_data = []
+ headers = []
+
+ for component, sample in zip(self.components, flag_data):
+ headers.append(component.label)
+
+ try:
+ save_dir = Path(folder_name) / utils.strip_invalid_filename_characters(
+ component.label or ""
+ )
+ filepath = component.deserialize(sample, save_dir, None)
+ except Exception:
+ # Could not parse 'sample' (mostly) because it was None and `component.save_flagged`
+ # does not handle None cases.
+ # for example: Label (line 3109 of components.py raises an error if data is None)
+ filepath = None
+
+ if isinstance(component, tuple(file_preview_types)):
+ headers.append(component.label or "" + " file")
+
+ csv_data.append(
+ "{}/resolve/main/{}/{}".format(
+ self.path_to_dataset_repo, unique_name, filepath
+ )
+ if filepath is not None
+ else None
+ )
+
+ csv_data.append(filepath)
+ headers.append("flag")
+ csv_data.append(flag_option)
+
+ # Creates metadata dict from row data and dumps it
+ metadata_dict = {
+ header: _csv_data for header, _csv_data in zip(headers, csv_data)
+ }
+ self.dump_json(metadata_dict, Path(folder_name) / "metadata.jsonl")
+
+ if is_new:
+ json.dump(infos, open(self.infos_file, "w"))
+
+ self.repo.push_to_hub(commit_message="Flagged sample {}".format(unique_name))
+ return unique_name
+
+ def get_unique_name(self):
+ id = uuid.uuid4()
+ return str(id)
+
+ def dump_json(self, thing: dict, file_path: str | Path) -> None:
+ with open(file_path, "w+", encoding="utf8") as f:
+ json.dump(thing, f)
+
+
+class FlagMethod:
+ """
+ Helper class that contains the flagging options and calls the flagging method. Also
+ provides visual feedback to the user when flag is clicked.
+ """
+
+ def __init__(
+ self,
+ flagging_callback: FlaggingCallback,
+ label: str,
+ value: str,
+ visual_feedback: bool = True,
+ ):
+ self.flagging_callback = flagging_callback
+ self.label = label
+ self.value = value
+ self.__name__ = "Flag"
+ self.visual_feedback = visual_feedback
+
+ def __call__(self, *flag_data):
+ try:
+ self.flagging_callback.flag(list(flag_data), flag_option=self.value)
+ except Exception as e:
+ print("Error while flagging: {}".format(e))
+ if self.visual_feedback:
+ return "Error!"
+ if not self.visual_feedback:
+ return
+ time.sleep(0.8) # to provide enough time for the user to observe button change
+ return self.reset()
+
+ def reset(self):
+ return gr.Button.update(value=self.label, interactive=True)
diff --git a/gradio/helpers.py b/gradio/helpers.py
new file mode 100644
index 0000000000000000000000000000000000000000..3619c40c69288611a2403bc1f5d389b3e80f6d80
--- /dev/null
+++ b/gradio/helpers.py
@@ -0,0 +1,839 @@
+"""
+Defines helper methods useful for loading and caching Interface examples.
+"""
+from __future__ import annotations
+
+import ast
+import csv
+import inspect
+import os
+import subprocess
+import tempfile
+import threading
+import warnings
+from pathlib import Path
+from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Tuple
+
+import matplotlib
+import matplotlib.pyplot as plt
+import numpy as np
+import PIL
+import PIL.Image
+
+from gradio import processing_utils, routes, utils
+from gradio.context import Context
+from gradio.documentation import document, set_documentation_group
+from gradio.flagging import CSVLogger
+
+if TYPE_CHECKING: # Only import for type checking (to avoid circular imports).
+ from gradio.blocks import Block
+ from gradio.components import IOComponent
+
+CACHED_FOLDER = "gradio_cached_examples"
+LOG_FILE = "log.csv"
+
+set_documentation_group("helpers")
+
+
+def create_examples(
+ examples: List[Any] | List[List[Any]] | str,
+ inputs: IOComponent | List[IOComponent],
+ outputs: IOComponent | List[IOComponent] | None = None,
+ fn: Callable | None = None,
+ cache_examples: bool = False,
+ examples_per_page: int = 10,
+ _api_mode: bool = False,
+ label: str | None = None,
+ elem_id: str | None = None,
+ run_on_click: bool = False,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ batch: bool = False,
+):
+ """Top-level synchronous function that creates Examples. Provided for backwards compatibility, i.e. so that gr.Examples(...) can be used to create the Examples component."""
+ examples_obj = Examples(
+ examples=examples,
+ inputs=inputs,
+ outputs=outputs,
+ fn=fn,
+ cache_examples=cache_examples,
+ examples_per_page=examples_per_page,
+ _api_mode=_api_mode,
+ label=label,
+ elem_id=elem_id,
+ run_on_click=run_on_click,
+ preprocess=preprocess,
+ postprocess=postprocess,
+ batch=batch,
+ _initiated_directly=False,
+ )
+ utils.synchronize_async(examples_obj.create)
+ return examples_obj
+
+
+@document()
+class Examples:
+ """
+ This class is a wrapper over the Dataset component and can be used to create Examples
+ for Blocks / Interfaces. Populates the Dataset component with examples and
+ assigns event listener so that clicking on an example populates the input/output
+ components. Optionally handles example caching for fast inference.
+
+ Demos: blocks_inputs, fake_gan
+ Guides: more_on_examples_and_flagging, using_hugging_face_integrations, image_classification_in_pytorch, image_classification_in_tensorflow, image_classification_with_vision_transformers, create_your_own_friends_with_a_gan
+ """
+
+ def __init__(
+ self,
+ examples: List[Any] | List[List[Any]] | str,
+ inputs: IOComponent | List[IOComponent],
+ outputs: IOComponent | List[IOComponent] | None = None,
+ fn: Callable | None = None,
+ cache_examples: bool = False,
+ examples_per_page: int = 10,
+ _api_mode: bool = False,
+ label: str | None = "Examples",
+ elem_id: str | None = None,
+ run_on_click: bool = False,
+ preprocess: bool = True,
+ postprocess: bool = True,
+ batch: bool = False,
+ _initiated_directly: bool = True,
+ ):
+ """
+ Parameters:
+ examples: example inputs that can be clicked to populate specific components. Should be nested list, in which the outer list consists of samples and each inner list consists of an input corresponding to each input component. A string path to a directory of examples can also be provided but it should be within the directory with the python file running the gradio app. If there are multiple input components and a directory is provided, a log.csv file must be present in the directory to link corresponding inputs.
+ inputs: the component or list of components corresponding to the examples
+ outputs: optionally, provide the component or list of components corresponding to the output of the examples. Required if `cache` is True.
+ fn: optionally, provide the function to run to generate the outputs corresponding to the examples. Required if `cache` is True.
+ cache_examples: if True, caches examples for fast runtime. If True, then `fn` and `outputs` need to be provided
+ examples_per_page: how many examples to show per page.
+ label: the label to use for the examples component (by default, "Examples")
+ elem_id: an optional string that is assigned as the id of this component in the HTML DOM.
+ run_on_click: if cache_examples is False, clicking on an example does not run the function when an example is clicked. Set this to True to run the function when an example is clicked. Has no effect if cache_examples is True.
+ preprocess: if True, preprocesses the example input before running the prediction function and caching the output. Only applies if cache_examples is True.
+ postprocess: if True, postprocesses the example output after running the prediction function and before caching. Only applies if cache_examples is True.
+ batch: If True, then the function should process a batch of inputs, meaning that it should accept a list of input values for each parameter. Used only if cache_examples is True.
+ """
+ if _initiated_directly:
+ warnings.warn(
+ "Please use gr.Examples(...) instead of gr.examples.Examples(...) to create the Examples.",
+ )
+
+ if cache_examples and (fn is None or outputs is None):
+ raise ValueError("If caching examples, `fn` and `outputs` must be provided")
+
+ if not isinstance(inputs, list):
+ inputs = [inputs]
+ if outputs and not isinstance(outputs, list):
+ outputs = [outputs]
+
+ working_directory = Path().absolute()
+
+ if examples is None:
+ raise ValueError("The parameter `examples` cannot be None")
+ elif isinstance(examples, list) and (
+ len(examples) == 0 or isinstance(examples[0], list)
+ ):
+ pass
+ elif (
+ isinstance(examples, list) and len(inputs) == 1
+ ): # If there is only one input component, examples can be provided as a regular list instead of a list of lists
+ examples = [[e] for e in examples]
+ elif isinstance(examples, str):
+ if not Path(examples).exists():
+ raise FileNotFoundError(
+ "Could not find examples directory: " + examples
+ )
+ working_directory = examples
+ if not (Path(examples) / LOG_FILE).exists():
+ if len(inputs) == 1:
+ examples = [[e] for e in os.listdir(examples)]
+ else:
+ raise FileNotFoundError(
+ "Could not find log file (required for multiple inputs): "
+ + LOG_FILE
+ )
+ else:
+ with open(Path(examples) / LOG_FILE) as logs:
+ examples = list(csv.reader(logs))
+ examples = [
+ examples[i][: len(inputs)] for i in range(1, len(examples))
+ ] # remove header and unnecessary columns
+
+ else:
+ raise ValueError(
+ "The parameter `examples` must either be a string directory or a list"
+ "(if there is only 1 input component) or (more generally), a nested "
+ "list, where each sublist represents a set of inputs."
+ )
+
+ input_has_examples = [False] * len(inputs)
+ for example in examples:
+ for idx, example_for_input in enumerate(example):
+ if not (example_for_input is None):
+ try:
+ input_has_examples[idx] = True
+ except IndexError:
+ pass # If there are more example components than inputs, ignore. This can sometimes be intentional (e.g. loading from a log file where outputs and timestamps are also logged)
+
+ inputs_with_examples = [
+ inp for (inp, keep) in zip(inputs, input_has_examples) if keep
+ ]
+ non_none_examples = [
+ [ex for (ex, keep) in zip(example, input_has_examples) if keep]
+ for example in examples
+ ]
+
+ self.examples = examples
+ self.non_none_examples = non_none_examples
+ self.inputs = inputs
+ self.inputs_with_examples = inputs_with_examples
+ self.outputs = outputs
+ self.fn = fn
+ self.cache_examples = cache_examples
+ self._api_mode = _api_mode
+ self.preprocess = preprocess
+ self.postprocess = postprocess
+ self.batch = batch
+
+ with utils.set_directory(working_directory):
+ self.processed_examples = [
+ [
+ component.postprocess(sample)
+ for component, sample in zip(inputs, example)
+ ]
+ for example in examples
+ ]
+ self.non_none_processed_examples = [
+ [ex for (ex, keep) in zip(example, input_has_examples) if keep]
+ for example in self.processed_examples
+ ]
+ if cache_examples:
+ for example in self.examples:
+ if len([ex for ex in example if ex is not None]) != len(self.inputs):
+ warnings.warn(
+ "Examples are being cached but not all input components have "
+ "example values. This may result in an exception being thrown by "
+ "your function. If you do get an error while caching examples, make "
+ "sure all of your inputs have example values for all of your examples "
+ "or you provide default values for those particular parameters in your function."
+ )
+ break
+
+ from gradio import components
+
+ with utils.set_directory(working_directory):
+ self.dataset = components.Dataset(
+ components=inputs_with_examples,
+ samples=non_none_examples,
+ type="index",
+ label=label,
+ samples_per_page=examples_per_page,
+ elem_id=elem_id,
+ )
+
+ self.cached_folder = Path(CACHED_FOLDER) / str(self.dataset._id)
+ self.cached_file = Path(self.cached_folder) / "log.csv"
+ self.cache_examples = cache_examples
+ self.run_on_click = run_on_click
+
+ async def create(self) -> None:
+ """Caches the examples if self.cache_examples is True and creates the Dataset
+ component to hold the examples"""
+
+ async def load_example(example_id):
+ if self.cache_examples:
+ processed_example = self.non_none_processed_examples[
+ example_id
+ ] + await self.load_from_cache(example_id)
+ else:
+ processed_example = self.non_none_processed_examples[example_id]
+ return utils.resolve_singleton(processed_example)
+
+ if Context.root_block:
+ if self.cache_examples and self.outputs:
+ targets = self.inputs_with_examples + self.outputs
+ else:
+ targets = self.inputs_with_examples
+ self.dataset.click(
+ load_example,
+ inputs=[self.dataset],
+ outputs=targets, # type: ignore
+ show_progress=False,
+ postprocess=False,
+ queue=False,
+ )
+ if self.run_on_click and not self.cache_examples:
+ if self.fn is None:
+ raise ValueError("Cannot run_on_click if no function is provided")
+ self.dataset.click(
+ self.fn,
+ inputs=self.inputs, # type: ignore
+ outputs=self.outputs, # type: ignore
+ )
+
+ if self.cache_examples:
+ await self.cache()
+
+ async def cache(self) -> None:
+ """
+ Caches all of the examples so that their predictions can be shown immediately.
+ """
+ if Path(self.cached_file).exists():
+ print(
+ f"Using cache from '{utils.abspath(self.cached_folder)}' directory. If method or examples have changed since last caching, delete this folder to clear cache."
+ )
+ else:
+ if Context.root_block is None:
+ raise ValueError("Cannot cache examples if not in a Blocks context")
+
+ print(f"Caching examples at: '{utils.abspath(self.cached_folder)}'")
+ cache_logger = CSVLogger()
+
+ # create a fake dependency to process the examples and get the predictions
+ dependency, fn_index = Context.root_block.set_event_trigger(
+ event_name="fake_event",
+ fn=self.fn,
+ inputs=self.inputs_with_examples, # type: ignore
+ outputs=self.outputs, # type: ignore
+ preprocess=self.preprocess and not self._api_mode,
+ postprocess=self.postprocess and not self._api_mode,
+ batch=self.batch,
+ )
+
+ assert self.outputs is not None
+ cache_logger.setup(self.outputs, self.cached_folder)
+ for example_id, _ in enumerate(self.examples):
+ processed_input = self.processed_examples[example_id]
+ if self.batch:
+ processed_input = [[value] for value in processed_input]
+ prediction = await Context.root_block.process_api(
+ fn_index=fn_index, inputs=processed_input, request=None, state={}
+ )
+ output = prediction["data"]
+ if self.batch:
+ output = [value[0] for value in output]
+ cache_logger.flag(output)
+ # Remove the "fake_event" to prevent bugs in loading interfaces from spaces
+ Context.root_block.dependencies.remove(dependency)
+ Context.root_block.fns.pop(fn_index)
+
+ async def load_from_cache(self, example_id: int) -> List[Any]:
+ """Loads a particular cached example for the interface.
+ Parameters:
+ example_id: The id of the example to process (zero-indexed).
+ """
+ with open(self.cached_file, encoding="utf-8") as cache:
+ examples = list(csv.reader(cache))
+ example = examples[example_id + 1] # +1 to adjust for header
+ output = []
+ assert self.outputs is not None
+ for component, value in zip(self.outputs, example):
+ try:
+ value_as_dict = ast.literal_eval(value)
+ assert utils.is_update(value_as_dict)
+ output.append(value_as_dict)
+ except (ValueError, TypeError, SyntaxError, AssertionError):
+ output.append(component.serialize(value, self.cached_folder))
+ return output
+
+
+class TrackedIterable:
+ def __init__(
+ self,
+ iterable: Iterable | None,
+ index: int | None,
+ length: int | None,
+ desc: str | None,
+ unit: str | None,
+ _tqdm=None,
+ progress: float | None = None,
+ ) -> None:
+ self.iterable = iterable
+ self.index = index
+ self.length = length
+ self.desc = desc
+ self.unit = unit
+ self._tqdm = _tqdm
+ self.progress = progress
+
+
+@document("__call__", "tqdm")
+class Progress(Iterable):
+ """
+ The Progress class provides a custom progress tracker that is used in a function signature.
+ To attach a Progress tracker to a function, simply add a parameter right after the input parameters that has a default value set to a `gradio.Progress()` instance.
+ The Progress tracker can then be updated in the function by calling the Progress object or using the `tqdm` method on an Iterable.
+ The Progress tracker is currently only available with `queue()`.
+ Example:
+ import gradio as gr
+ import time
+ def my_function(x, progress=gr.Progress()):
+ progress(0, desc="Starting...")
+ time.sleep(1)
+ for i in progress.tqdm(range(100)):
+ time.sleep(0.1)
+ return x
+ gr.Interface(my_function, gr.Textbox(), gr.Textbox()).queue().launch()
+ Demos: progress
+ """
+
+ def __init__(
+ self,
+ track_tqdm: bool = False,
+ _callback: Callable | None = None, # for internal use only
+ _event_id: str | None = None,
+ ):
+ """
+ Parameters:
+ track_tqdm: If True, the Progress object will track any tqdm.tqdm iterations with the tqdm library in the function.
+ """
+ self.track_tqdm = track_tqdm
+ self._callback = _callback
+ self._event_id = _event_id
+ self.iterables: List[TrackedIterable] = []
+
+ def __len__(self):
+ return self.iterables[-1].length
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ """
+ Updates progress tracker with next item in iterable.
+ """
+ if self._callback:
+ current_iterable = self.iterables[-1]
+ while (
+ not hasattr(current_iterable.iterable, "__next__")
+ and len(self.iterables) > 0
+ ):
+ current_iterable = self.iterables.pop()
+ self._callback(
+ event_id=self._event_id,
+ iterables=self.iterables,
+ )
+ assert current_iterable.index is not None, "Index not set."
+ current_iterable.index += 1
+ try:
+ return next(current_iterable.iterable) # type: ignore
+ except StopIteration:
+ self.iterables.pop()
+ raise StopIteration
+ else:
+ return self
+
+ def __call__(
+ self,
+ progress: float | Tuple[int, int | None] | None,
+ desc: str | None = None,
+ total: int | None = None,
+ unit: str = "steps",
+ _tqdm=None,
+ ):
+ """
+ Updates progress tracker with progress and message text.
+ Parameters:
+ progress: If float, should be between 0 and 1 representing completion. If Tuple, first number represents steps completed, and second value represents total steps or None if unknown. If None, hides progress bar.
+ desc: description to display.
+ total: estimated total number of steps.
+ unit: unit of iterations.
+ """
+ if self._callback:
+ if isinstance(progress, tuple):
+ index, total = progress
+ progress = None
+ else:
+ index = None
+ self._callback(
+ event_id=self._event_id,
+ iterables=self.iterables
+ + [TrackedIterable(None, index, total, desc, unit, _tqdm, progress)],
+ )
+ else:
+ return progress
+
+ def tqdm(
+ self,
+ iterable: Iterable | None,
+ desc: str | None = None,
+ total: int | None = None,
+ unit: str = "steps",
+ _tqdm=None,
+ *args,
+ **kwargs,
+ ):
+ """
+ Attaches progress tracker to iterable, like tqdm.
+ Parameters:
+ iterable: iterable to attach progress tracker to.
+ desc: description to display.
+ total: estimated total number of steps.
+ unit: unit of iterations.
+ """
+ if self._callback:
+ if iterable is None:
+ new_iterable = TrackedIterable(None, 0, total, desc, unit, _tqdm)
+ self.iterables.append(new_iterable)
+ self._callback(event_id=self._event_id, iterables=self.iterables)
+ return self
+ length = len(iterable) if hasattr(iterable, "__len__") else None # type: ignore
+ self.iterables.append(
+ TrackedIterable(iter(iterable), 0, length, desc, unit, _tqdm)
+ )
+ return self
+
+ def update(self, n=1):
+ """
+ Increases latest iterable with specified number of steps.
+ Parameters:
+ n: number of steps completed.
+ """
+ if self._callback and len(self.iterables) > 0:
+ current_iterable = self.iterables[-1]
+ assert current_iterable.index is not None, "Index not set."
+ current_iterable.index += n
+ self._callback(
+ event_id=self._event_id,
+ iterables=self.iterables,
+ )
+ else:
+ return
+
+ def close(self, _tqdm):
+ """
+ Removes iterable with given _tqdm.
+ """
+ if self._callback:
+ for i in range(len(self.iterables)):
+ if id(self.iterables[i]._tqdm) == id(_tqdm):
+ self.iterables.pop(i)
+ break
+ self._callback(
+ event_id=self._event_id,
+ iterables=self.iterables,
+ )
+ else:
+ return
+
+
+def create_tracker(root_blocks, event_id, fn, track_tqdm):
+
+ progress = Progress(_callback=root_blocks._queue.set_progress, _event_id=event_id)
+ if not track_tqdm:
+ return progress, fn
+
+ try:
+ _tqdm = __import__("tqdm")
+ except ModuleNotFoundError:
+ return progress, fn
+ if not hasattr(root_blocks, "_progress_tracker_per_thread"):
+ root_blocks._progress_tracker_per_thread = {}
+
+ def init_tqdm(self, iterable=None, desc=None, *args, **kwargs):
+ self._progress = root_blocks._progress_tracker_per_thread.get(
+ threading.get_ident()
+ )
+ if self._progress is not None:
+ self._progress.event_id = event_id
+ self._progress.tqdm(iterable, desc, _tqdm=self, *args, **kwargs)
+ kwargs["file"] = open(os.devnull, "w")
+ self.__init__orig__(iterable, desc, *args, **kwargs)
+
+ def iter_tqdm(self):
+ if self._progress is not None:
+ return self._progress
+ else:
+ return self.__iter__orig__()
+
+ def update_tqdm(self, n=1):
+ if self._progress is not None:
+ self._progress.update(n)
+ return self.__update__orig__(n)
+
+ def close_tqdm(self):
+ if self._progress is not None:
+ self._progress.close(self)
+ return self.__close__orig__()
+
+ def exit_tqdm(self, exc_type, exc_value, traceback):
+ if self._progress is not None:
+ self._progress.close(self)
+ return self.__exit__orig__(exc_type, exc_value, traceback)
+
+ if not hasattr(_tqdm.tqdm, "__init__orig__"):
+ _tqdm.tqdm.__init__orig__ = _tqdm.tqdm.__init__
+ _tqdm.tqdm.__init__ = init_tqdm
+ if not hasattr(_tqdm.tqdm, "__update__orig__"):
+ _tqdm.tqdm.__update__orig__ = _tqdm.tqdm.update
+ _tqdm.tqdm.update = update_tqdm
+ if not hasattr(_tqdm.tqdm, "__close__orig__"):
+ _tqdm.tqdm.__close__orig__ = _tqdm.tqdm.close
+ _tqdm.tqdm.close = close_tqdm
+ if not hasattr(_tqdm.tqdm, "__exit__orig__"):
+ _tqdm.tqdm.__exit__orig__ = _tqdm.tqdm.__exit__
+ _tqdm.tqdm.__exit__ = exit_tqdm
+ if not hasattr(_tqdm.tqdm, "__iter__orig__"):
+ _tqdm.tqdm.__iter__orig__ = _tqdm.tqdm.__iter__
+ _tqdm.tqdm.__iter__ = iter_tqdm
+ if hasattr(_tqdm, "auto") and hasattr(_tqdm.auto, "tqdm"):
+ _tqdm.auto.tqdm = _tqdm.tqdm
+
+ def tracked_fn(*args):
+ thread_id = threading.get_ident()
+ root_blocks._progress_tracker_per_thread[thread_id] = progress
+ response = fn(*args)
+ del root_blocks._progress_tracker_per_thread[thread_id]
+ return response
+
+ return progress, tracked_fn
+
+
+def special_args(
+ fn: Callable,
+ inputs: List[Any] | None = None,
+ request: routes.Request | None = None,
+ event_data: EventData | None = None,
+):
+ """
+ Checks if function has special arguments Request or EventData (via annotation) or Progress (via default value).
+ If inputs is provided, these values will be loaded into the inputs array.
+ Parameters:
+ block_fn: function to check.
+ inputs: array to load special arguments into.
+ request: request to load into inputs.
+ Returns:
+ updated inputs, progress index, event data index.
+ """
+ signature = inspect.signature(fn)
+ positional_args = []
+ for i, param in enumerate(signature.parameters.values()):
+ if param.kind not in (param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD):
+ break
+ positional_args.append(param)
+ progress_index = None
+ event_data_index = None
+ for i, param in enumerate(positional_args):
+ if isinstance(param.default, Progress):
+ progress_index = i
+ if inputs is not None:
+ inputs.insert(i, param.default)
+ elif param.annotation == routes.Request:
+ if inputs is not None:
+ inputs.insert(i, request)
+ elif isinstance(param.annotation, type) and issubclass(
+ param.annotation, EventData
+ ):
+ event_data_index = i
+ if inputs is not None and event_data is not None:
+ inputs.insert(i, param.annotation(event_data.target, event_data._data))
+ if inputs is not None:
+ while len(inputs) < len(positional_args):
+ i = len(inputs)
+ param = positional_args[i]
+ if param.default == param.empty:
+ warnings.warn("Unexpected argument. Filling with None.")
+ inputs.append(None)
+ else:
+ inputs.append(param.default)
+ return inputs or [], progress_index, event_data_index
+
+
+@document()
+def update(**kwargs) -> dict:
+ """
+ Updates component properties. When a function passed into a Gradio Interface or a Blocks events returns a typical value, it updates the value of the output component. But it is also possible to update the properties of an output component (such as the number of lines of a `Textbox` or the visibility of an `Image`) by returning the component's `update()` function, which takes as parameters any of the constructor parameters for that component.
+ This is a shorthand for using the update method on a component.
+ For example, rather than using gr.Number.update(...) you can just use gr.update(...).
+ Note that your editor's autocompletion will suggest proper parameters
+ if you use the update method on the component.
+ Demos: blocks_essay, blocks_update, blocks_essay_update
+
+ Parameters:
+ kwargs: Key-word arguments used to update the component's properties.
+ Example:
+ # Blocks Example
+ import gradio as gr
+ with gr.Blocks() as demo:
+ radio = gr.Radio([1, 2, 4], label="Set the value of the number")
+ number = gr.Number(value=2, interactive=True)
+ radio.change(fn=lambda value: gr.update(value=value), inputs=radio, outputs=number)
+ demo.launch()
+
+ # Interface example
+ import gradio as gr
+ def change_textbox(choice):
+ if choice == "short":
+ return gr.Textbox.update(lines=2, visible=True)
+ elif choice == "long":
+ return gr.Textbox.update(lines=8, visible=True)
+ else:
+ return gr.Textbox.update(visible=False)
+ gr.Interface(
+ change_textbox,
+ gr.Radio(
+ ["short", "long", "none"], label="What kind of essay would you like to write?"
+ ),
+ gr.Textbox(lines=2),
+ live=True,
+ ).launch()
+ """
+ kwargs["__type__"] = "generic_update"
+ return kwargs
+
+
+def skip() -> dict:
+ return update()
+
+
+@document()
+def make_waveform(
+ audio: str | Tuple[int, np.ndarray],
+ *,
+ bg_color: str = "#f3f4f6",
+ bg_image: str | None = None,
+ fg_alpha: float = 0.75,
+ bars_color: str | Tuple[str, str] = ("#fbbf24", "#ea580c"),
+ bar_count: int = 50,
+ bar_width: float = 0.6,
+):
+ """
+ Generates a waveform video from an audio file. Useful for creating an easy to share audio visualization. The output should be passed into a `gr.Video` component.
+ Parameters:
+ audio: Audio file path or tuple of (sample_rate, audio_data)
+ bg_color: Background color of waveform (ignored if bg_image is provided)
+ bg_image: Background image of waveform
+ fg_alpha: Opacity of foreground waveform
+ bars_color: Color of waveform bars. Can be a single color or a tuple of (start_color, end_color) of gradient
+ bar_count: Number of bars in waveform
+ bar_width: Width of bars in waveform. 1 represents full width, 0.5 represents half width, etc.
+ Returns:
+ A filepath to the output video.
+ """
+ if isinstance(audio, str):
+ audio_file = audio
+ audio = processing_utils.audio_from_file(audio)
+ else:
+ tmp_wav = tempfile.NamedTemporaryFile(suffix=".wav", delete=False)
+ processing_utils.audio_to_file(audio[0], audio[1], tmp_wav.name)
+ audio_file = tmp_wav.name
+ duration = round(len(audio[1]) / audio[0], 4)
+
+ # Helper methods to create waveform
+ def hex_to_RGB(hex_str):
+ return [int(hex_str[i : i + 2], 16) for i in range(1, 6, 2)]
+
+ def get_color_gradient(c1, c2, n):
+ assert n > 1
+ c1_rgb = np.array(hex_to_RGB(c1)) / 255
+ c2_rgb = np.array(hex_to_RGB(c2)) / 255
+ mix_pcts = [x / (n - 1) for x in range(n)]
+ rgb_colors = [((1 - mix) * c1_rgb + (mix * c2_rgb)) for mix in mix_pcts]
+ return [
+ "#" + "".join([format(int(round(val * 255)), "02x") for val in item])
+ for item in rgb_colors
+ ]
+
+ # Reshape audio to have a fixed number of bars
+ samples = audio[1]
+ if len(samples.shape) > 1:
+ samples = np.mean(samples, 1)
+ bins_to_pad = bar_count - (len(samples) % bar_count)
+ samples = np.pad(samples, [(0, bins_to_pad)])
+ samples = np.reshape(samples, (bar_count, -1))
+ samples = np.abs(samples)
+ samples = np.max(samples, 1)
+
+ matplotlib.use("Agg")
+ plt.clf()
+ # Plot waveform
+ color = (
+ bars_color
+ if isinstance(bars_color, str)
+ else get_color_gradient(bars_color[0], bars_color[1], bar_count)
+ )
+ plt.bar(
+ np.arange(0, bar_count),
+ samples * 2,
+ bottom=(-1 * samples),
+ width=bar_width,
+ color=color,
+ )
+ plt.axis("off")
+ plt.margins(x=0)
+ tmp_img = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
+ savefig_kwargs: Dict[str, Any] = {"bbox_inches": "tight"}
+ if bg_image is not None:
+ savefig_kwargs["transparent"] = True
+ else:
+ savefig_kwargs["facecolor"] = bg_color
+ plt.savefig(tmp_img.name, **savefig_kwargs)
+ waveform_img = PIL.Image.open(tmp_img.name)
+ waveform_img = waveform_img.resize((1000, 200))
+
+ # Composite waveform with background image
+ if bg_image is not None:
+ waveform_array = np.array(waveform_img)
+ waveform_array[:, :, 3] = waveform_array[:, :, 3] * fg_alpha
+ waveform_img = PIL.Image.fromarray(waveform_array)
+
+ bg_img = PIL.Image.open(bg_image)
+ waveform_width, waveform_height = waveform_img.size
+ bg_width, bg_height = bg_img.size
+ if waveform_width != bg_width:
+ bg_img = bg_img.resize(
+ (waveform_width, 2 * int(bg_height * waveform_width / bg_width / 2))
+ )
+ bg_width, bg_height = bg_img.size
+ composite_height = max(bg_height, waveform_height)
+ composite = PIL.Image.new("RGBA", (waveform_width, composite_height), "#FFFFFF")
+ composite.paste(bg_img, (0, composite_height - bg_height))
+ composite.paste(
+ waveform_img, (0, composite_height - waveform_height), waveform_img
+ )
+ composite.save(tmp_img.name)
+ img_width, img_height = composite.size
+ else:
+ img_width, img_height = waveform_img.size
+ waveform_img.save(tmp_img.name)
+
+ # Convert waveform to video with ffmpeg
+ output_mp4 = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
+
+ ffmpeg_cmd = f"""ffmpeg -loop 1 -i {tmp_img.name} -i {audio_file} -vf "color=c=#FFFFFF77:s={img_width}x{img_height}[bar];[0][bar]overlay=-w+(w/{duration})*t:H-h:shortest=1" -t {duration} -y {output_mp4.name}"""
+
+ subprocess.call(ffmpeg_cmd, shell=True)
+ return output_mp4.name
+
+
+@document()
+class EventData:
+ """
+ When a subclass of EventData is added as a type hint to an argument of an event listener method, this object will be passed as that argument.
+ It contains information about the event that triggered the listener, such the target object, and other data related to the specific event that are attributes of the subclass.
+
+ Example:
+ table = gr.Dataframe([[1, 2, 3], [4, 5, 6]])
+ gallery = gr.Gallery([("cat.jpg", "Cat"), ("dog.jpg", "Dog")])
+ textbox = gr.Textbox("Hello World!")
+
+ statement = gr.Textbox()
+
+ def on_select(evt: gr.SelectData): # SelectData is a subclass of EventData
+ return f"You selected {evt.value} at {evt.index} from {evt.target}"
+
+ table.select(on_select, None, statement)
+ gallery.select(on_select, None, statement)
+ textbox.select(on_select, None, statement)
+ Demos: gallery_selections, tictactoe
+ """
+
+ def __init__(self, target: Block | None, _data: Any):
+ """
+ Parameters:
+ target: The target object that triggered the event. Can be used to distinguish if multiple components are bound to the same listener.
+ """
+ self.target = target
+ self._data = _data
diff --git a/gradio/inputs.py b/gradio/inputs.py
new file mode 100644
index 0000000000000000000000000000000000000000..ae7c6c25dbbce899551e8e4f1559e43823a7b028
--- /dev/null
+++ b/gradio/inputs.py
@@ -0,0 +1,473 @@
+# type: ignore
+"""
+This module defines various classes that can serve as the `input` to an interface. Each class must inherit from
+`InputComponent`, and each class must define a path to its template. All of the subclasses of `InputComponent` are
+automatically added to a registry, which allows them to be easily referenced in other parts of the code.
+"""
+
+from __future__ import annotations
+
+import warnings
+from typing import Any, List, Optional, Tuple
+
+from gradio import components
+
+
+class Textbox(components.Textbox):
+ def __init__(
+ self,
+ lines: int = 1,
+ placeholder: Optional[str] = None,
+ default: str = "",
+ numeric: Optional[bool] = False,
+ type: Optional[str] = "text",
+ label: Optional[str] = None,
+ optional: bool = False,
+ ):
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your component from gradio.components",
+ )
+ super().__init__(
+ value=default,
+ lines=lines,
+ placeholder=placeholder,
+ label=label,
+ numeric=numeric,
+ type=type,
+ optional=optional,
+ )
+
+
+class Number(components.Number):
+ """
+ Component creates a field for user to enter numeric input. Provides a number as an argument to the wrapped function.
+ Input type: float
+ """
+
+ def __init__(
+ self,
+ default: Optional[float] = None,
+ label: Optional[str] = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ default (float): default value.
+ label (str): component name in interface.
+ optional (bool): If True, the interface can be submitted with no value for this component.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your component from gradio.components",
+ )
+ super().__init__(value=default, label=label, optional=optional)
+
+
+class Slider(components.Slider):
+ """
+ Component creates a slider that ranges from `minimum` to `maximum`. Provides number as an argument to the wrapped function.
+ Input type: float
+ """
+
+ def __init__(
+ self,
+ minimum: float = 0,
+ maximum: float = 100,
+ step: Optional[float] = None,
+ default: Optional[float] = None,
+ label: Optional[str] = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ minimum (float): minimum value for slider.
+ maximum (float): maximum value for slider.
+ step (float): increment between slider values.
+ default (float): default value.
+ label (str): component name in interface.
+ optional (bool): this parameter is ignored.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your component from gradio.components",
+ )
+
+ super().__init__(
+ value=default,
+ minimum=minimum,
+ maximum=maximum,
+ step=step,
+ label=label,
+ optional=optional,
+ )
+
+
+class Checkbox(components.Checkbox):
+ """
+ Component creates a checkbox that can be set to `True` or `False`. Provides a boolean as an argument to the wrapped function.
+ Input type: bool
+ """
+
+ def __init__(
+ self,
+ default: bool = False,
+ label: Optional[str] = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ label (str): component name in interface.
+ default (bool): if True, checked by default.
+ optional (bool): this parameter is ignored.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your component from gradio.components",
+ )
+ super().__init__(value=default, label=label, optional=optional)
+
+
+class CheckboxGroup(components.CheckboxGroup):
+ """
+ Component creates a set of checkboxes of which a subset can be selected. Provides a list of strings representing the selected choices as an argument to the wrapped function.
+ Input type: Union[List[str], List[int]]
+ """
+
+ def __init__(
+ self,
+ choices: List[str],
+ default: List[str] = [],
+ type: str = "value",
+ label: Optional[str] = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ choices (List[str]): list of options to select from.
+ default (List[str]): default selected list of options.
+ type (str): Type of value to be returned by component. "value" returns the list of strings of the choices selected, "index" returns the list of indicies of the choices selected.
+ label (str): component name in interface.
+ optional (bool): this parameter is ignored.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your component from gradio.components",
+ )
+ super().__init__(
+ value=default,
+ choices=choices,
+ type=type,
+ label=label,
+ optional=optional,
+ )
+
+
+class Radio(components.Radio):
+ """
+ Component creates a set of radio buttons of which only one can be selected. Provides string representing selected choice as an argument to the wrapped function.
+ Input type: Union[str, int]
+ """
+
+ def __init__(
+ self,
+ choices: List[str],
+ type: str = "value",
+ default: Optional[str] = None,
+ label: Optional[str] = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ choices (List[str]): list of options to select from.
+ type (str): Type of value to be returned by component. "value" returns the string of the choice selected, "index" returns the index of the choice selected.
+ default (str): the button selected by default. If None, no button is selected by default.
+ label (str): component name in interface.
+ optional (bool): this parameter is ignored.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your component from gradio.components",
+ )
+ super().__init__(
+ choices=choices,
+ type=type,
+ value=default,
+ label=label,
+ optional=optional,
+ )
+
+
+class Dropdown(components.Dropdown):
+ """
+ Component creates a dropdown of which only one can be selected. Provides string representing selected choice as an argument to the wrapped function.
+ Input type: Union[str, int]
+ """
+
+ def __init__(
+ self,
+ choices: List[str],
+ type: str = "value",
+ default: Optional[str] = None,
+ label: Optional[str] = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ choices (List[str]): list of options to select from.
+ type (str): Type of value to be returned by component. "value" returns the string of the choice selected, "index" returns the index of the choice selected.
+ default (str): default value selected in dropdown. If None, no value is selected by default.
+ label (str): component name in interface.
+ optional (bool): this parameter is ignored.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your component from gradio.components",
+ )
+ super().__init__(
+ choices=choices,
+ type=type,
+ value=default,
+ label=label,
+ optional=optional,
+ )
+
+
+class Image(components.Image):
+ """
+ Component creates an image upload box with editing capabilities.
+ Input type: Union[numpy.array, PIL.Image, file-object]
+ """
+
+ def __init__(
+ self,
+ shape: Tuple[int, int] = None,
+ image_mode: str = "RGB",
+ invert_colors: bool = False,
+ source: str = "upload",
+ tool: str = "editor",
+ type: str = "numpy",
+ label: str = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ shape (Tuple[int, int]): (width, height) shape to crop and resize image to; if None, matches input image size.
+ image_mode (str): How to process the uploaded image. Accepts any of the PIL image modes, e.g. "RGB" for color images, "RGBA" to include the transparency mask, "L" for black-and-white images.
+ invert_colors (bool): whether to invert the image as a preprocessing step.
+ source (str): Source of image. "upload" creates a box where user can drop an image file, "webcam" allows user to take snapshot from their webcam, "canvas" defaults to a white image that can be edited and drawn upon with tools.
+ tool (str): Tools used for editing. "editor" allows a full screen editor, "select" provides a cropping and zoom tool.
+ type (str): Type of value to be returned by component. "numpy" returns a numpy array with shape (width, height, 3) and values from 0 to 255, "pil" returns a PIL image object, "file" returns a temporary file object whose path can be retrieved by file_obj.name, "filepath" returns the path directly.
+ label (str): component name in interface.
+ optional (bool): If True, the interface can be submitted with no uploaded image, in which case the input value is None.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your component from gradio.components",
+ )
+ super().__init__(
+ shape=shape,
+ image_mode=image_mode,
+ invert_colors=invert_colors,
+ source=source,
+ tool=tool,
+ type=type,
+ label=label,
+ optional=optional,
+ )
+
+
+class Video(components.Video):
+ """
+ Component creates a video file upload that is converted to a file path.
+
+ Input type: filepath
+ """
+
+ def __init__(
+ self,
+ type: Optional[str] = None,
+ source: str = "upload",
+ label: Optional[str] = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ type (str): Type of video format to be returned by component, such as 'avi' or 'mp4'. If set to None, video will keep uploaded format.
+ source (str): Source of video. "upload" creates a box where user can drop an video file, "webcam" allows user to record a video from their webcam.
+ label (str): component name in interface.
+ optional (bool): If True, the interface can be submitted with no uploaded video, in which case the input value is None.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your components from gradio.components",
+ )
+ super().__init__(format=type, source=source, label=label, optional=optional)
+
+
+class Audio(components.Audio):
+ """
+ Component accepts audio input files.
+ Input type: Union[Tuple[int, numpy.array], file-object, numpy.array]
+ """
+
+ def __init__(
+ self,
+ source: str = "upload",
+ type: str = "numpy",
+ label: str = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ source (str): Source of audio. "upload" creates a box where user can drop an audio file, "microphone" creates a microphone input.
+ type (str): Type of value to be returned by component. "numpy" returns a 2-set tuple with an integer sample_rate and the data numpy.array of shape (samples, 2), "file" returns a temporary file object whose path can be retrieved by file_obj.name, "filepath" returns the path directly.
+ label (str): component name in interface.
+ optional (bool): If True, the interface can be submitted with no uploaded audio, in which case the input value is None.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your components from gradio.components",
+ )
+ super().__init__(source=source, type=type, label=label, optional=optional)
+
+
+class File(components.File):
+ """
+ Component accepts generic file uploads.
+ Input type: Union[file-object, bytes, List[Union[file-object, bytes]]]
+ """
+
+ def __init__(
+ self,
+ file_count: str = "single",
+ type: str = "file",
+ label: Optional[str] = None,
+ keep_filename: bool = True,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ file_count (str): if single, allows user to upload one file. If "multiple", user uploads multiple files. If "directory", user uploads all files in selected directory. Return type will be list for each file in case of "multiple" or "directory".
+ type (str): Type of value to be returned by component. "file" returns a temporary file object whose path can be retrieved by file_obj.name, "binary" returns an bytes object.
+ label (str): component name in interface.
+ keep_filename (bool): DEPRECATED. Original filename always kept.
+ optional (bool): If True, the interface can be submitted with no uploaded image, in which case the input value is None.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your components from gradio.components",
+ )
+ super().__init__(
+ file_count=file_count,
+ type=type,
+ label=label,
+ keep_filename=keep_filename,
+ optional=optional,
+ )
+
+
+class Dataframe(components.Dataframe):
+ """
+ Component accepts 2D input through a spreadsheet interface.
+ Input type: Union[pandas.DataFrame, numpy.array, List[Union[str, float]], List[List[Union[str, float]]]]
+ """
+
+ def __init__(
+ self,
+ headers: Optional[List[str]] = None,
+ row_count: int = 3,
+ col_count: Optional[int] = 3,
+ datatype: str | List[str] = "str",
+ col_width: int | List[int] = None,
+ default: Optional[List[List[Any]]] = None,
+ type: str = "pandas",
+ label: Optional[str] = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ headers (List[str]): Header names to dataframe. If None, no headers are shown.
+ row_count (int): Limit number of rows for input.
+ col_count (int): Limit number of columns for input. If equal to 1, return data will be one-dimensional. Ignored if `headers` is provided.
+ datatype (Union[str, List[str]]): Datatype of values in sheet. Can be provided per column as a list of strings, or for the entire sheet as a single string. Valid datatypes are "str", "number", "bool", and "date".
+ col_width (Union[int, List[int]]): Width of columns in pixels. Can be provided as single value or list of values per column.
+ default (List[List[Any]]): Default value
+ type (str): Type of value to be returned by component. "pandas" for pandas dataframe, "numpy" for numpy array, or "array" for a Python array.
+ label (str): component name in interface.
+ optional (bool): this parameter is ignored.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your components from gradio.components",
+ )
+ super().__init__(
+ value=default,
+ headers=headers,
+ row_count=row_count,
+ col_count=col_count,
+ datatype=datatype,
+ col_width=col_width,
+ type=type,
+ label=label,
+ optional=optional,
+ )
+
+
+class Timeseries(components.Timeseries):
+ """
+ Component accepts pandas.DataFrame uploaded as a timeseries csv file.
+ Input type: pandas.DataFrame
+ """
+
+ def __init__(
+ self,
+ x: Optional[str] = None,
+ y: str | List[str] = None,
+ label: Optional[str] = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ x (str): Column name of x (time) series. None if csv has no headers, in which case first column is x series.
+ y (Union[str, List[str]]): Column name of y series, or list of column names if multiple series. None if csv has no headers, in which case every column after first is a y series.
+ label (str): component name in interface.
+ optional (bool): If True, the interface can be submitted with no uploaded csv file, in which case the input value is None.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your components from gradio.components",
+ )
+ super().__init__(x=x, y=y, label=label, optional=optional)
+
+
+class State(components.State):
+ """
+ Special hidden component that stores state across runs of the interface.
+ Input type: Any
+ """
+
+ def __init__(
+ self,
+ label: str = None,
+ default: Any = None,
+ ):
+ """
+ Parameters:
+ label (str): component name in interface (not used).
+ default (Any): the initial value of the state.
+ optional (bool): this parameter is ignored.
+ """
+ warnings.warn(
+ "Usage of gradio.inputs is deprecated, and will not be supported in the future, please import this component as gr.State() from gradio.components",
+ )
+ super().__init__(value=default, label=label)
+
+
+class Image3D(components.Model3D):
+ """
+ Used for 3D image model output.
+ Input type: File object of type (.obj, glb, or .gltf)
+ """
+
+ def __init__(
+ self,
+ label: Optional[str] = None,
+ optional: bool = False,
+ ):
+ """
+ Parameters:
+ label (str): component name in interface.
+ optional (bool): If True, the interface can be submitted with no uploaded image, in which case the input value is None.
+ """
+ warnings.warn(
+ "Usage of gradio.outputs is deprecated, and will not be supported in the future, please import your components from gradio.components",
+ )
+ super().__init__(label=label, optional=optional)
diff --git a/gradio/interface.py b/gradio/interface.py
new file mode 100644
index 0000000000000000000000000000000000000000..28321641ba0054673314470bd36adbdfbd03e20f
--- /dev/null
+++ b/gradio/interface.py
@@ -0,0 +1,888 @@
+"""
+This is the core file in the `gradio` package, and defines the Interface class,
+including various methods for constructing an interface and then launching it.
+"""
+
+from __future__ import annotations
+
+import inspect
+import json
+import os
+import re
+import warnings
+import weakref
+from typing import TYPE_CHECKING, Any, Callable, List, Tuple
+
+from gradio import Examples, interpretation, utils
+from gradio.blocks import Blocks
+from gradio.components import (
+ Button,
+ Interpretation,
+ IOComponent,
+ Markdown,
+ State,
+ get_component_instance,
+)
+from gradio.data_classes import InterfaceTypes
+from gradio.documentation import document, set_documentation_group
+from gradio.events import Changeable, Streamable
+from gradio.flagging import CSVLogger, FlaggingCallback, FlagMethod
+from gradio.layouts import Column, Row, Tab, Tabs
+from gradio.pipelines import load_from_pipeline
+from gradio.themes import ThemeClass as Theme
+from gradio.utils import GRADIO_VERSION
+
+set_documentation_group("interface")
+
+if TYPE_CHECKING: # Only import for type checking (is False at runtime).
+ from transformers.pipelines.base import Pipeline
+
+
+@document("launch", "load", "from_pipeline", "integrate", "queue")
+class Interface(Blocks):
+ """
+ Interface is Gradio's main high-level class, and allows you to create a web-based GUI / demo
+ around a machine learning model (or any Python function) in a few lines of code.
+ You must specify three parameters: (1) the function to create a GUI for (2) the desired input components and
+ (3) the desired output components. Additional parameters can be used to control the appearance
+ and behavior of the demo.
+
+ Example:
+ import gradio as gr
+
+ def image_classifier(inp):
+ return {'cat': 0.3, 'dog': 0.7}
+
+ demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label")
+ demo.launch()
+ Demos: hello_world, hello_world_3, gpt_j
+ Guides: quickstart, key_features, sharing_your_app, interface_state, reactive_interfaces, advanced_interface_features, setting_up_a_gradio_demo_for_maximum_performance
+ """
+
+ # stores references to all currently existing Interface instances
+ instances: weakref.WeakSet = weakref.WeakSet()
+
+ @classmethod
+ def get_instances(cls) -> List[Interface]:
+ """
+ :return: list of all current instances.
+ """
+ return list(Interface.instances)
+
+ @classmethod
+ def load(
+ cls,
+ name: str,
+ src: str | None = None,
+ api_key: str | None = None,
+ alias: str | None = None,
+ **kwargs,
+ ) -> Interface:
+ """
+ Class method that constructs an Interface from a Hugging Face repo. Can accept
+ model repos (if src is "models") or Space repos (if src is "spaces"). The input
+ and output components are automatically loaded from the repo.
+ Parameters:
+ name: the name of the model (e.g. "gpt2" or "facebook/bart-base") or space (e.g. "flax-community/spanish-gpt2"), can include the `src` as prefix (e.g. "models/facebook/bart-base")
+ src: the source of the model: `models` or `spaces` (or leave empty if source is provided as a prefix in `name`)
+ api_key: optional access token for loading private Hugging Face Hub models or spaces. Find your token here: https://huggingface.co/settings/tokens
+ alias: optional string used as the name of the loaded model instead of the default name (only applies if loading a Space running Gradio 2.x)
+ Returns:
+ a Gradio Interface object for the given model
+ Example:
+ import gradio as gr
+ description = "Story generation with GPT"
+ examples = [["An adventurer is approached by a mysterious stranger in the tavern for a new quest."]]
+ demo = gr.Interface.load("models/EleutherAI/gpt-neo-1.3B", description=description, examples=examples)
+ demo.launch()
+ """
+ return super().load(name=name, src=src, api_key=api_key, alias=alias, **kwargs)
+
+ @classmethod
+ def from_pipeline(cls, pipeline: Pipeline, **kwargs) -> Interface:
+ """
+ Class method that constructs an Interface from a Hugging Face transformers.Pipeline object.
+ The input and output components are automatically determined from the pipeline.
+ Parameters:
+ pipeline: the pipeline object to use.
+ Returns:
+ a Gradio Interface object from the given Pipeline
+ Example:
+ import gradio as gr
+ from transformers import pipeline
+ pipe = pipeline("image-classification")
+ gr.Interface.from_pipeline(pipe).launch()
+ """
+ interface_info = load_from_pipeline(pipeline)
+ kwargs = dict(interface_info, **kwargs)
+ interface = cls(**kwargs)
+ return interface
+
+ def __init__(
+ self,
+ fn: Callable,
+ inputs: str | IOComponent | List[str | IOComponent] | None,
+ outputs: str | IOComponent | List[str | IOComponent] | None,
+ examples: List[Any] | List[List[Any]] | str | None = None,
+ cache_examples: bool | None = None,
+ examples_per_page: int = 10,
+ live: bool = False,
+ interpretation: Callable | str | None = None,
+ num_shap: float = 2.0,
+ title: str | None = None,
+ description: str | None = None,
+ article: str | None = None,
+ thumbnail: str | None = None,
+ theme: Theme | None = None,
+ css: str | None = None,
+ allow_flagging: str | None = None,
+ flagging_options: List[str] | List[Tuple[str, str]] | None = None,
+ flagging_dir: str = "flagged",
+ flagging_callback: FlaggingCallback = CSVLogger(),
+ analytics_enabled: bool | None = None,
+ batch: bool = False,
+ max_batch_size: int = 4,
+ _api_mode: bool = False,
+ **kwargs,
+ ):
+ """
+ Parameters:
+ fn: the function to wrap an interface around. Often a machine learning model's prediction function. Each parameter of the function corresponds to one input component, and the function should return a single value or a tuple of values, with each element in the tuple corresponding to one output component.
+ inputs: a single Gradio component, or list of Gradio components. Components can either be passed as instantiated objects, or referred to by their string shortcuts. The number of input components should match the number of parameters in fn. If set to None, then only the output components will be displayed.
+ outputs: a single Gradio component, or list of Gradio components. Components can either be passed as instantiated objects, or referred to by their string shortcuts. The number of output components should match the number of values returned by fn. If set to None, then only the input components will be displayed.
+ examples: sample inputs for the function; if provided, appear below the UI components and can be clicked to populate the interface. Should be nested list, in which the outer list consists of samples and each inner list consists of an input corresponding to each input component. A string path to a directory of examples can also be provided, but it should be within the directory with the python file running the gradio app. If there are multiple input components and a directory is provided, a log.csv file must be present in the directory to link corresponding inputs.
+ cache_examples: If True, caches examples in the server for fast runtime in examples. The default option in HuggingFace Spaces is True. The default option elsewhere is False.
+ examples_per_page: If examples are provided, how many to display per page.
+ live: whether the interface should automatically rerun if any of the inputs change.
+ interpretation: function that provides interpretation explaining prediction output. Pass "default" to use simple built-in interpreter, "shap" to use a built-in shapley-based interpreter, or your own custom interpretation function. For more information on the different interpretation methods, see the Advanced Interface Features guide.
+ num_shap: a multiplier that determines how many examples are computed for shap-based interpretation. Increasing this value will increase shap runtime, but improve results. Only applies if interpretation is "shap".
+ title: a title for the interface; if provided, appears above the input and output components in large font. Also used as the tab title when opened in a browser window.
+ description: a description for the interface; if provided, appears above the input and output components and beneath the title in regular font. Accepts Markdown and HTML content.
+ article: an expanded article explaining the interface; if provided, appears below the input and output components in regular font. Accepts Markdown and HTML content.
+ thumbnail: path or url to image to use as display image when the web demo is shared on social media.
+ theme: Theme to use, loaded from gradio.themes.
+ css: custom css or path to custom css file to use with interface.
+ allow_flagging: one of "never", "auto", or "manual". If "never" or "auto", users will not see a button to flag an input and output. If "manual", users will see a button to flag. If "auto", every input the user submits will be automatically flagged (outputs are not flagged). If "manual", both the input and outputs are flagged when the user clicks flag button. This parameter can be set with environmental variable GRADIO_ALLOW_FLAGGING; otherwise defaults to "manual".
+ flagging_options: if provided, allows user to select from the list of options when flagging. Only applies if allow_flagging is "manual". Can either be a list of tuples of the form (label, value), where label is the string that will be displayed on the button and value is the string that will be stored in the flagging CSV; or it can be a list of strings ["X", "Y"], in which case the values will be the list of strings and the labels will ["Flag as X", "Flag as Y"], etc.
+ flagging_dir: what to name the directory where flagged data is stored.
+ flagging_callback: An instance of a subclass of FlaggingCallback which will be called when a sample is flagged. By default logs to a local CSV file.
+ analytics_enabled: Whether to allow basic telemetry. If None, will use GRADIO_ANALYTICS_ENABLED environment variable if defined, or default to True.
+ batch: If True, then the function should process a batch of inputs, meaning that it should accept a list of input values for each parameter. The lists should be of equal length (and be up to length `max_batch_size`). The function is then *required* to return a tuple of lists (even if there is only 1 output component), with each list in the tuple corresponding to one output component.
+ max_batch_size: Maximum number of inputs to batch together if this is called from the queue (only relevant if batch=True)
+ """
+ super().__init__(
+ analytics_enabled=analytics_enabled,
+ mode="interface",
+ css=css,
+ title=title or "Gradio",
+ theme=theme,
+ **kwargs,
+ )
+
+ if isinstance(fn, list):
+ raise DeprecationWarning(
+ "The `fn` parameter only accepts a single function, support for a list "
+ "of functions has been deprecated. Please use gradio.mix.Parallel "
+ "instead."
+ )
+
+ self.interface_type = InterfaceTypes.STANDARD
+ if (inputs is None or inputs == []) and (outputs is None or outputs == []):
+ raise ValueError("Must provide at least one of `inputs` or `outputs`")
+ elif outputs is None or outputs == []:
+ outputs = []
+ self.interface_type = InterfaceTypes.INPUT_ONLY
+ elif inputs is None or inputs == []:
+ inputs = []
+ self.interface_type = InterfaceTypes.OUTPUT_ONLY
+
+ assert isinstance(inputs, (str, list, IOComponent))
+ assert isinstance(outputs, (str, list, IOComponent))
+
+ if not isinstance(inputs, list):
+ inputs = [inputs]
+ if not isinstance(outputs, list):
+ outputs = [outputs]
+
+ if self.is_space and cache_examples is None:
+ self.cache_examples = True
+ else:
+ self.cache_examples = cache_examples or False
+
+ state_input_indexes = [
+ idx for idx, i in enumerate(inputs) if i == "state" or isinstance(i, State)
+ ]
+ state_output_indexes = [
+ idx for idx, o in enumerate(outputs) if o == "state" or isinstance(o, State)
+ ]
+
+ if len(state_input_indexes) == 0 and len(state_output_indexes) == 0:
+ pass
+ elif len(state_input_indexes) != 1 or len(state_output_indexes) != 1:
+ raise ValueError(
+ "If using 'state', there must be exactly one state input and one state output."
+ )
+ else:
+ state_input_index = state_input_indexes[0]
+ state_output_index = state_output_indexes[0]
+ if inputs[state_input_index] == "state":
+ default = utils.get_default_args(fn)[state_input_index]
+ state_variable = State(value=default) # type: ignore
+ else:
+ state_variable = inputs[state_input_index]
+
+ inputs[state_input_index] = state_variable
+ outputs[state_output_index] = state_variable
+
+ if cache_examples:
+ warnings.warn(
+ "Cache examples cannot be used with state inputs and outputs."
+ "Setting cache_examples to False."
+ )
+ self.cache_examples = False
+
+ self.input_components = [
+ get_component_instance(i, render=False) for i in inputs
+ ]
+ self.output_components = [
+ get_component_instance(o, render=False) for o in outputs
+ ]
+
+ for component in self.input_components + self.output_components:
+ if not (isinstance(component, IOComponent)):
+ raise ValueError(
+ f"{component} is not a valid input/output component for Interface."
+ )
+
+ if len(self.input_components) == len(self.output_components):
+ same_components = [
+ i is o for i, o in zip(self.input_components, self.output_components)
+ ]
+ if all(same_components):
+ self.interface_type = InterfaceTypes.UNIFIED
+
+ if self.interface_type in [
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.OUTPUT_ONLY,
+ ]:
+ for o in self.output_components:
+ assert isinstance(o, IOComponent)
+ o.interactive = False # Force output components to be non-interactive
+
+ if (
+ interpretation is None
+ or isinstance(interpretation, list)
+ or callable(interpretation)
+ ):
+ self.interpretation = interpretation
+ elif isinstance(interpretation, str):
+ self.interpretation = [
+ interpretation.lower() for _ in self.input_components
+ ]
+ else:
+ raise ValueError("Invalid value for parameter: interpretation")
+
+ self.api_mode = _api_mode
+ self.fn = fn
+ self.fn_durations = [0, 0]
+ self.__name__ = getattr(fn, "__name__", "fn")
+ self.live = live
+ self.title = title
+
+ CLEANER = re.compile("<.*?>")
+
+ def clean_html(raw_html):
+ cleantext = re.sub(CLEANER, "", raw_html)
+ return cleantext
+
+ md = utils.get_markdown_parser()
+ simple_description = None
+ if description is not None:
+ description = md.render(description)
+ simple_description = clean_html(description)
+ self.simple_description = simple_description
+ self.description = description
+ if article is not None:
+ article = utils.readme_to_html(article)
+ article = md.render(article)
+ self.article = article
+
+ self.thumbnail = thumbnail
+ self.theme = theme
+
+ self.examples = examples
+ self.num_shap = num_shap
+ self.examples_per_page = examples_per_page
+
+ self.simple_server = None
+
+ # For allow_flagging: (1) first check for parameter,
+ # (2) check for env variable, (3) default to True/"manual"
+ if allow_flagging is None:
+ allow_flagging = os.getenv("GRADIO_ALLOW_FLAGGING", "manual")
+ if allow_flagging is True:
+ warnings.warn(
+ "The `allow_flagging` parameter in `Interface` now"
+ "takes a string value ('auto', 'manual', or 'never')"
+ ", not a boolean. Setting parameter to: 'manual'."
+ )
+ self.allow_flagging = "manual"
+ elif allow_flagging == "manual":
+ self.allow_flagging = "manual"
+ elif allow_flagging is False:
+ warnings.warn(
+ "The `allow_flagging` parameter in `Interface` now"
+ "takes a string value ('auto', 'manual', or 'never')"
+ ", not a boolean. Setting parameter to: 'never'."
+ )
+ self.allow_flagging = "never"
+ elif allow_flagging == "never":
+ self.allow_flagging = "never"
+ elif allow_flagging == "auto":
+ self.allow_flagging = "auto"
+ else:
+ raise ValueError(
+ "Invalid value for `allow_flagging` parameter."
+ "Must be: 'auto', 'manual', or 'never'."
+ )
+
+ if flagging_options is None:
+ self.flagging_options = [("Flag", "")]
+ elif not (isinstance(flagging_options, list)):
+ raise ValueError(
+ "flagging_options must be a list of strings or list of (string, string) tuples."
+ )
+ elif all([isinstance(x, str) for x in flagging_options]):
+ self.flagging_options = [(f"Flag as {x}", x) for x in flagging_options]
+ elif all([isinstance(x, tuple) for x in flagging_options]):
+ self.flagging_options = flagging_options
+ else:
+ raise ValueError(
+ "flagging_options must be a list of strings or list of (string, string) tuples."
+ )
+
+ self.flagging_callback = flagging_callback
+ self.flagging_dir = flagging_dir
+ self.batch = batch
+ self.max_batch_size = max_batch_size
+
+ self.save_to = None # Used for selenium tests
+ self.share = None
+ self.share_url = None
+ self.local_url = None
+
+ self.favicon_path = None
+
+ if self.analytics_enabled:
+ data = {
+ "mode": self.mode,
+ "fn": fn,
+ "inputs": inputs,
+ "outputs": outputs,
+ "live": live,
+ "interpretation": interpretation,
+ "allow_flagging": allow_flagging,
+ "custom_css": self.css is not None,
+ "theme": self.theme,
+ "version": GRADIO_VERSION,
+ }
+ utils.initiated_analytics(data)
+
+ utils.version_check()
+ Interface.instances.add(self)
+
+ param_names = inspect.getfullargspec(self.fn)[0]
+ if len(param_names) > 0 and inspect.ismethod(self.fn):
+ param_names = param_names[1:]
+ for component, param_name in zip(self.input_components, param_names):
+ assert isinstance(component, IOComponent)
+ if component.label is None:
+ component.label = param_name
+ for i, component in enumerate(self.output_components):
+ assert isinstance(component, IOComponent)
+ if component.label is None:
+ if len(self.output_components) == 1:
+ component.label = "output"
+ else:
+ component.label = "output " + str(i)
+
+ if self.allow_flagging != "never":
+ if (
+ self.interface_type == InterfaceTypes.UNIFIED
+ or self.allow_flagging == "auto"
+ ):
+ self.flagging_callback.setup(self.input_components, self.flagging_dir) # type: ignore
+ elif self.interface_type == InterfaceTypes.INPUT_ONLY:
+ pass
+ else:
+ self.flagging_callback.setup(
+ self.input_components + self.output_components, self.flagging_dir # type: ignore
+ )
+
+ # Render the Gradio UI
+ with self:
+ self.render_title_description()
+
+ submit_btn, clear_btn, stop_btn, flag_btns = None, None, None, None
+ interpretation_btn, interpretation_set = None, None
+ input_component_column, interpret_component_column = None, None
+
+ with Row().style(equal_height=False):
+ if self.interface_type in [
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.INPUT_ONLY,
+ InterfaceTypes.UNIFIED,
+ ]:
+ (
+ submit_btn,
+ clear_btn,
+ stop_btn,
+ flag_btns,
+ input_component_column,
+ interpret_component_column,
+ interpretation_set,
+ ) = self.render_input_column()
+ if self.interface_type in [
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.OUTPUT_ONLY,
+ ]:
+ (
+ submit_btn_out,
+ clear_btn_2_out,
+ stop_btn_2_out,
+ flag_btns_out,
+ interpretation_btn,
+ ) = self.render_output_column(submit_btn)
+ submit_btn = submit_btn or submit_btn_out
+ clear_btn = clear_btn or clear_btn_2_out
+ stop_btn = stop_btn or stop_btn_2_out
+ flag_btns = flag_btns or flag_btns_out
+
+ assert clear_btn is not None, "Clear button not rendered"
+
+ self.attach_submit_events(submit_btn, stop_btn)
+ self.attach_clear_events(
+ clear_btn, input_component_column, interpret_component_column
+ )
+ self.attach_interpretation_events(
+ interpretation_btn,
+ interpretation_set,
+ input_component_column,
+ interpret_component_column,
+ )
+
+ self.attach_flagging_events(flag_btns, clear_btn)
+ self.render_examples()
+ self.render_article()
+
+ self.config = self.get_config_file()
+
+ def render_title_description(self) -> None:
+ if self.title:
+ Markdown(
+ "
"
+ + self.title
+ + "
"
+ )
+ if self.description:
+ Markdown(self.description)
+
+ def render_flag_btns(self) -> List[Button]:
+ return [Button(label) for label, _ in self.flagging_options]
+
+ def render_input_column(
+ self,
+ ) -> Tuple[
+ Button | None,
+ Button | None,
+ Button | None,
+ List[Button] | None,
+ Column,
+ Column | None,
+ List[Interpretation] | None,
+ ]:
+ submit_btn, clear_btn, stop_btn, flag_btns = None, None, None, None
+ interpret_component_column, interpretation_set = None, None
+
+ with Column(variant="panel"):
+ input_component_column = Column()
+ with input_component_column:
+ for component in self.input_components:
+ component.render()
+ if self.interpretation:
+ interpret_component_column = Column(visible=False)
+ interpretation_set = []
+ with interpret_component_column:
+ for component in self.input_components:
+ interpretation_set.append(Interpretation(component))
+ with Row():
+ if self.interface_type in [
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.INPUT_ONLY,
+ ]:
+ clear_btn = Button("Clear")
+ if not self.live:
+ submit_btn = Button("Submit", variant="primary")
+ # Stopping jobs only works if the queue is enabled
+ # We don't know if the queue is enabled when the interface
+ # is created. We use whether a generator function is provided
+ # as a proxy of whether the queue will be enabled.
+ # Using a generator function without the queue will raise an error.
+ if inspect.isgeneratorfunction(self.fn):
+ stop_btn = Button("Stop", variant="stop", visible=False)
+ elif self.interface_type == InterfaceTypes.UNIFIED:
+ clear_btn = Button("Clear")
+ submit_btn = Button("Submit", variant="primary")
+ if inspect.isgeneratorfunction(self.fn) and not self.live:
+ stop_btn = Button("Stop", variant="stop")
+ if self.allow_flagging == "manual":
+ flag_btns = self.render_flag_btns()
+ elif self.allow_flagging == "auto":
+ flag_btns = [submit_btn]
+ return (
+ submit_btn,
+ clear_btn,
+ stop_btn,
+ flag_btns,
+ input_component_column,
+ interpret_component_column,
+ interpretation_set,
+ )
+
+ def render_output_column(
+ self,
+ submit_btn_in: Button | None,
+ ) -> Tuple[Button | None, Button | None, Button | None, List | None, Button | None]:
+ submit_btn = submit_btn_in
+ interpretation_btn, clear_btn, flag_btns, stop_btn = None, None, None, None
+
+ with Column(variant="panel"):
+ for component in self.output_components:
+ if not (isinstance(component, State)):
+ component.render()
+ with Row():
+ if self.interface_type == InterfaceTypes.OUTPUT_ONLY:
+ clear_btn = Button("Clear")
+ submit_btn = Button("Generate", variant="primary")
+ if inspect.isgeneratorfunction(self.fn) and not self.live:
+ # Stopping jobs only works if the queue is enabled
+ # We don't know if the queue is enabled when the interface
+ # is created. We use whether a generator function is provided
+ # as a proxy of whether the queue will be enabled.
+ # Using a generator function without the queue will raise an error.
+ stop_btn = Button("Stop", variant="stop", visible=False)
+ if self.allow_flagging == "manual":
+ flag_btns = self.render_flag_btns()
+ elif self.allow_flagging == "auto":
+ assert submit_btn is not None, "Submit button not rendered"
+ flag_btns = [submit_btn]
+ if self.interpretation:
+ interpretation_btn = Button("Interpret")
+
+ return submit_btn, clear_btn, stop_btn, flag_btns, interpretation_btn
+
+ def render_article(self):
+ if self.article:
+ Markdown(self.article)
+
+ def attach_submit_events(self, submit_btn: Button | None, stop_btn: Button | None):
+ if self.live:
+ if self.interface_type == InterfaceTypes.OUTPUT_ONLY:
+ assert submit_btn is not None, "Submit button not rendered"
+ super().load(self.fn, None, self.output_components)
+ # For output-only interfaces, the user probably still want a "generate"
+ # button even if the Interface is live
+ submit_btn.click(
+ self.fn,
+ None,
+ self.output_components,
+ api_name="predict",
+ preprocess=not (self.api_mode),
+ postprocess=not (self.api_mode),
+ batch=self.batch,
+ max_batch_size=self.max_batch_size,
+ )
+ else:
+ for component in self.input_components:
+ if isinstance(component, Streamable) and component.streaming:
+ component.stream(
+ self.fn,
+ self.input_components,
+ self.output_components,
+ api_name="predict",
+ preprocess=not (self.api_mode),
+ postprocess=not (self.api_mode),
+ )
+ continue
+ if isinstance(component, Changeable):
+ component.change(
+ self.fn,
+ self.input_components,
+ self.output_components,
+ api_name="predict",
+ preprocess=not (self.api_mode),
+ postprocess=not (self.api_mode),
+ )
+ else:
+ assert submit_btn is not None, "Submit button not rendered"
+ fn = self.fn
+ extra_output = []
+ if stop_btn:
+
+ # Wrap the original function to show/hide the "Stop" button
+ def fn(*args):
+ # The main idea here is to call the original function
+ # and append some updates to keep the "Submit" button
+ # hidden and the "Stop" button visible
+ # The 'finally' block hides the "Stop" button and
+ # shows the "submit" button. Having a 'finally' block
+ # will make sure the UI is "reset" even if there is an exception
+ try:
+ for output in self.fn(*args):
+ if len(self.output_components) == 1 and not self.batch:
+ output = [output]
+ output = [o for o in output]
+ yield output + [
+ Button.update(visible=False),
+ Button.update(visible=True),
+ ]
+ finally:
+ yield [
+ {"__type__": "generic_update"}
+ for _ in self.output_components
+ ] + [Button.update(visible=True), Button.update(visible=False)]
+
+ extra_output = [submit_btn, stop_btn]
+ pred = submit_btn.click(
+ fn,
+ self.input_components,
+ self.output_components + extra_output,
+ api_name="predict",
+ scroll_to_output=True,
+ preprocess=not (self.api_mode),
+ postprocess=not (self.api_mode),
+ batch=self.batch,
+ max_batch_size=self.max_batch_size,
+ )
+ if stop_btn:
+ submit_btn.click(
+ lambda: (
+ submit_btn.update(visible=False),
+ stop_btn.update(visible=True),
+ ),
+ inputs=None,
+ outputs=[submit_btn, stop_btn],
+ queue=False,
+ )
+ stop_btn.click(
+ lambda: (
+ submit_btn.update(visible=True),
+ stop_btn.update(visible=False),
+ ),
+ inputs=None,
+ outputs=[submit_btn, stop_btn],
+ cancels=[pred],
+ queue=False,
+ )
+
+ def attach_clear_events(
+ self,
+ clear_btn: Button,
+ input_component_column: Column | None,
+ interpret_component_column: Column | None,
+ ):
+ clear_btn.click(
+ None,
+ [],
+ (
+ self.input_components
+ + self.output_components
+ + ([input_component_column] if input_component_column else [])
+ + ([interpret_component_column] if self.interpretation else [])
+ ), # type: ignore
+ _js=f"""() => {json.dumps(
+ [getattr(component, "cleared_value", None)
+ for component in self.input_components + self.output_components] + (
+ [Column.update(visible=True)]
+ if self.interface_type
+ in [
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.INPUT_ONLY,
+ InterfaceTypes.UNIFIED,
+ ]
+ else []
+ )
+ + ([Column.update(visible=False)] if self.interpretation else [])
+ )}
+ """,
+ )
+
+ def attach_interpretation_events(
+ self,
+ interpretation_btn: Button | None,
+ interpretation_set: List[Interpretation] | None,
+ input_component_column: Column | None,
+ interpret_component_column: Column | None,
+ ):
+ if interpretation_btn:
+ interpretation_btn.click(
+ self.interpret_func,
+ inputs=self.input_components + self.output_components,
+ outputs=(interpretation_set or []) + [input_component_column, interpret_component_column], # type: ignore
+ preprocess=False,
+ )
+
+ def attach_flagging_events(self, flag_btns: List[Button] | None, clear_btn: Button):
+ if flag_btns:
+ if self.interface_type in [
+ InterfaceTypes.STANDARD,
+ InterfaceTypes.OUTPUT_ONLY,
+ InterfaceTypes.UNIFIED,
+ ]:
+ if self.allow_flagging == "auto":
+ flag_method = FlagMethod(
+ self.flagging_callback, "", "", visual_feedback=False
+ )
+ flag_btns[0].click( # flag_btns[0] is just the "Submit" button
+ flag_method,
+ inputs=self.input_components,
+ outputs=None,
+ preprocess=False,
+ queue=False,
+ )
+ return
+
+ if self.interface_type == InterfaceTypes.UNIFIED:
+ flag_components = self.input_components
+ else:
+ flag_components = self.input_components + self.output_components
+
+ for flag_btn, (label, value) in zip(flag_btns, self.flagging_options):
+ assert isinstance(value, str)
+ flag_method = FlagMethod(self.flagging_callback, label, value)
+ flag_btn.click(
+ lambda: Button.update(value="Saving...", interactive=False),
+ None,
+ flag_btn,
+ queue=False,
+ )
+ flag_btn.click(
+ flag_method,
+ inputs=flag_components,
+ outputs=flag_btn,
+ preprocess=False,
+ queue=False,
+ )
+ clear_btn.click(
+ flag_method.reset,
+ None,
+ flag_btn,
+ queue=False,
+ )
+
+ def render_examples(self):
+ if self.examples:
+ non_state_inputs = [
+ c for c in self.input_components if not isinstance(c, State)
+ ]
+ non_state_outputs = [
+ c for c in self.output_components if not isinstance(c, State)
+ ]
+ self.examples_handler = Examples(
+ examples=self.examples,
+ inputs=non_state_inputs, # type: ignore
+ outputs=non_state_outputs, # type: ignore
+ fn=self.fn,
+ cache_examples=self.cache_examples,
+ examples_per_page=self.examples_per_page,
+ _api_mode=self.api_mode,
+ batch=self.batch,
+ )
+
+ def __str__(self):
+ return self.__repr__()
+
+ def __repr__(self):
+ repr = f"Gradio Interface for: {self.__name__}"
+ repr += "\n" + "-" * len(repr)
+ repr += "\ninputs:"
+ for component in self.input_components:
+ repr += "\n|-{}".format(str(component))
+ repr += "\noutputs:"
+ for component in self.output_components:
+ repr += "\n|-{}".format(str(component))
+ return repr
+
+ async def interpret_func(self, *args):
+ return await self.interpret(list(args)) + [
+ Column.update(visible=False),
+ Column.update(visible=True),
+ ]
+
+ async def interpret(self, raw_input: List[Any]) -> List[Any]:
+ return [
+ {"original": raw_value, "interpretation": interpretation}
+ for interpretation, raw_value in zip(
+ (await interpretation.run_interpret(self, raw_input))[0], raw_input
+ )
+ ]
+
+ def test_launch(self) -> None:
+ """
+ Deprecated.
+ """
+ warnings.warn("The Interface.test_launch() function is deprecated.")
+
+
+@document()
+class TabbedInterface(Blocks):
+ """
+ A TabbedInterface is created by providing a list of Interfaces, each of which gets
+ rendered in a separate tab.
+ Demos: stt_or_tts
+ """
+
+ def __init__(
+ self,
+ interface_list: List[Interface],
+ tab_names: List[str] | None = None,
+ title: str | None = None,
+ theme: Theme | None = None,
+ analytics_enabled: bool | None = None,
+ css: str | None = None,
+ ):
+ """
+ Parameters:
+ interface_list: a list of interfaces to be rendered in tabs.
+ tab_names: a list of tab names. If None, the tab names will be "Tab 1", "Tab 2", etc.
+ title: a title for the interface; if provided, appears above the input and output components in large font. Also used as the tab title when opened in a browser window.
+ analytics_enabled: whether to allow basic telemetry. If None, will use GRADIO_ANALYTICS_ENABLED environment variable or default to True.
+ css: custom css or path to custom css file to apply to entire Blocks
+ Returns:
+ a Gradio Tabbed Interface for the given interfaces
+ """
+ super().__init__(
+ title=title or "Gradio",
+ theme=theme,
+ analytics_enabled=analytics_enabled,
+ mode="tabbed_interface",
+ css=css,
+ )
+ if tab_names is None:
+ tab_names = ["Tab {}".format(i) for i in range(len(interface_list))]
+ with self:
+ if title:
+ Markdown(
+ "
\n\n\n"],"names":[],"mappings":"yUAwBE,gDANM,gDAHM,qBACG,gCAFjB,SAMC,+DAIC,8BANM,uBAHM,0BACG,4IAbL,QAAuB,SACvB,WACA,aAAsB,OACtB,UAAmB,OACnB,QAAiB,uNAEtB,UAAW,GAAa,iBAAkB,IAC/C,iBAAF"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/BlockTitle.39fa370e.js b/gradio/templates/cdn/assets/BlockTitle.39fa370e.js
new file mode 100644
index 0000000000000000000000000000000000000000..aba837f7721191bdc30056513f0d8bcbb28dfc50
--- /dev/null
+++ b/gradio/templates/cdn/assets/BlockTitle.39fa370e.js
@@ -0,0 +1,2 @@
+import{S as d,i as h,s as k,W as g,c as w,m as $,o as r,t as m,l as B,F as I,G as S,e as j,B as q,O as _,f as c,X as C,Y as F,Z as G,k as H,n as J,p,H as N,J as O}from"./index.7a68216a.js";import{I as T}from"./Info.4b69e77f.js";import"./Empty.svelte_svelte_type_style_lang.d7a3af78.js";function b(o){let e,n;return e=new T({props:{$$slots:{default:[W]},$$scope:{ctx:o}}}),{c(){w(e.$$.fragment)},m(l,f){$(e,l,f),n=!0},p(l,f){const u={};f&10&&(u.$$scope={dirty:f,ctx:l}),e.$set(u)},i(l){n||(r(e.$$.fragment,l),n=!0)},o(l){m(e.$$.fragment,l),n=!1},d(l){B(e,l)}}}function W(o){let e;return{c(){e=N(o[1])},m(n,l){c(n,e,l)},p(n,l){l&2&&O(e,n[1])},d(n){n&&p(e)}}}function X(o){let e,n,l,f;const u=o[2].default,a=g(u,o,o[3],null);let s=o[1]&&b(o);return{c(){e=I("span"),a&&a.c(),n=S(),s&&s.c(),l=j(),q(e,"class","svelte-1gfkn6j"),_(e,"sr-only",!o[0]),_(e,"hide",!o[0]),_(e,"has-info",o[1]!=null)},m(t,i){c(t,e,i),a&&a.m(e,null),c(t,n,i),s&&s.m(t,i),c(t,l,i),f=!0},p(t,[i]){a&&a.p&&(!f||i&8)&&C(a,u,t,t[3],f?G(u,t[3],i,null):F(t[3]),null),i&1&&_(e,"sr-only",!t[0]),i&1&&_(e,"hide",!t[0]),i&2&&_(e,"has-info",t[1]!=null),t[1]?s?(s.p(t,i),i&2&&r(s,1)):(s=b(t),s.c(),r(s,1),s.m(l.parentNode,l)):s&&(H(),m(s,1,1,()=>{s=null}),J())},i(t){f||(r(a,t),r(s),f=!0)},o(t){m(a,t),m(s),f=!1},d(t){t&&p(e),a&&a.d(t),t&&p(n),s&&s.d(t),t&&p(l)}}}function Y(o,e,n){let{$$slots:l={},$$scope:f}=e,{show_label:u=!0}=e,{info:a=void 0}=e;return o.$$set=s=>{"show_label"in s&&n(0,u=s.show_label),"info"in s&&n(1,a=s.info),"$$scope"in s&&n(3,f=s.$$scope)},[u,a,l,f]}class A extends d{constructor(e){super(),h(this,e,Y,X,k,{show_label:0,info:1})}}export{A as B};
+//# sourceMappingURL=BlockTitle.39fa370e.js.map
diff --git a/gradio/templates/cdn/assets/BlockTitle.39fa370e.js.map b/gradio/templates/cdn/assets/BlockTitle.39fa370e.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..76a56d2a5ea9a6b31e20dd6f6b966a373cd82831
--- /dev/null
+++ b/gradio/templates/cdn/assets/BlockTitle.39fa370e.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"BlockTitle.39fa370e.js","sources":["../../../../ui/packages/atoms/src/BlockTitle.svelte"],"sourcesContent":["\n\n\n\t\n\n{#if info}\n\t{info}\n{/if}\n\n\n"],"names":[],"mappings":"klBAcQ,wCAAA,8FADH,6GANY,kBACH,qBACG,MAAQ,IAAI,UAH7B,0JACiB,uBACH,0BACG,MAAQ,IAAI,EAIxB,mQAXO,aAAsB,OACtB,OAA2B"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/Blocks.15437627.css b/gradio/templates/cdn/assets/Blocks.15437627.css
new file mode 100644
index 0000000000000000000000000000000000000000..ab575d8fe732de741b21bb174b517b7f95a83e79
--- /dev/null
+++ b/gradio/templates/cdn/assets/Blocks.15437627.css
@@ -0,0 +1 @@
+.wrap.svelte-1i3r921.svelte-1i3r921{padding:var(--size-6)}.attention.svelte-1i3r921.svelte-1i3r921{font-weight:var(--weight-bold);font-size:var(--text-lg)}.attention.svelte-1i3r921 code.svelte-1i3r921{border:none;background:none;color:var(--color-accent);font-weight:var(--weight-bold)}button.svelte-1i3r921.svelte-1i3r921{position:absolute;top:var(--size-5);right:var(--size-6);width:var(--size-4);color:var(--body-text-color)}button.svelte-1i3r921.svelte-1i3r921:hover{color:var(--color-accent)}@media (min-width: 768px){button.svelte-1i3r921.svelte-1i3r921{top:var(--size-6)}}h2.svelte-155na5k.svelte-155na5k{display:flex;color:var(--body-text-color);font-weight:var(--weight-semibold)}h2.svelte-155na5k img.svelte-155na5k{margin-right:var(--size-2);width:var(--size-4)}span.svelte-155na5k.svelte-155na5k{color:var(--color-accent)}button.svelte-155na5k.svelte-155na5k{position:absolute;top:var(--size-5);right:var(--size-6);width:var(--size-4);color:var(--body-text-color)}button.svelte-155na5k.svelte-155na5k:hover{color:var(--color-accent)}@media (min-width: 768px){button.svelte-155na5k.svelte-155na5k{top:var(--size-6)}h2.svelte-155na5k img.svelte-155na5k{width:var(--size-5)}}h3.svelte-vs3f38{color:var(--body-text-color);font-weight:var(--section-header-text-weight);font-size:var(--text-lg)}.post.svelte-vs3f38{margin-right:var(--size-2);border:1px solid var(--border-color-accent);border-radius:var(--radius-sm);background:var(--color-accent-soft);padding-right:var(--size-1);padding-left:var(--size-1);color:var(--color-accent);font-weight:var(--weight-semibold)}.endpoint.svelte-vs3f38{margin-bottom:var(--size-6);color:var(--body-text-color)}.url.svelte-vs3f38{display:inline-block;border:none;background:none;padding:var(--size-0-5);font-family:var(--font-mono)}.payload-details.svelte-j5il63{font-family:var(--font-mono)}.space.svelte-j5il63{display:flex;flex-basis:1;margin-top:var(--size-4)}h4.svelte-j5il63{display:flex;align-items:center;margin-top:var(--size-6);margin-bottom:var(--size-3);color:var(--body-text-color);font-weight:var(--weight-bold)}.toggle-icon.svelte-j5il63{display:flex;align-items:center;margin-right:var(--size-2);border-radius:var(--radius-full);background:var(--color-grey-300);width:12px;height:4px}.toggle-dot.svelte-j5il63{border-radius:var(--radius-full);background:var(--color-grey-700);width:6px;height:6px}.dark .toggle-icon.svelte-j5il63{background:var(--color-grey-500)}.dark .toggle-dot.svelte-j5il63{background:var(--color-grey-400)}input[type=text].svelte-j5il63{--ring-color:transparent;margin:var(--size-1) 0;outline:none!important;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--radius-lg);background:var(--input-background-fill);padding:var(--size-1-5);color:var(--body-text-color);font-weight:var(--input-text-weight);font-size:var(--input-text-size);line-height:var(--line-sm)}input.svelte-j5il63:focus{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}.error.svelte-j5il63{color:var(--error-text-color)}.type.svelte-j5il63{color:var(--block-label-text-color)}.desc.svelte-j5il63{color:var(--body-text-color-subdued)}.name.svelte-j5il63{text-transform:capitalize}.first-level.svelte-j5il63{margin-left:1rem}.second-level.svelte-j5il63{margin-left:2rem}.load-wrap.svelte-fxtbel{display:flex;justify-content:center;align-items:center}h4.svelte-fxtbel{display:flex;align-items:center;margin-top:var(--size-6);margin-bottom:var(--size-3);color:var(--body-text-color);font-weight:var(--weight-bold)}.toggle-icon.svelte-fxtbel{display:flex;align-items:center;margin-right:var(--size-2);border-radius:var(--radius-full);background:var(--color-grey-300);width:12px;height:4px}.toggle-dot.svelte-fxtbel{margin-left:auto;border-radius:var(--radius-full);background:var(--color-grey-700);width:6px;height:6px}.response-wrap.svelte-fxtbel{font-family:var(--font-mono)}input[type=text].svelte-fxtbel{--ring-color:transparent;margin:var(--size-1) 0;outline:none!important;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--radius-lg);background:var(--input-background-fill);padding:var(--size-1-5);color:var(--body-text-color);font-weight:var(--input-text-weight);font-size:var(--input-text-size);line-height:var(--line-sm)}input.svelte-fxtbel:focus{box-shadow:var(--input-shadow);border-color:var(--input-border-color-focus)}.type.svelte-fxtbel{color:var(--block-label-text-color)}.desc.svelte-fxtbel{color:var(--body-text-color-subdued)}.name.svelte-fxtbel{text-transform:capitalize}.hide.svelte-fxtbel{display:none}.first-level.svelte-fxtbel{margin-left:1rem}.second-level.svelte-fxtbel{margin-left:2rem}h4.svelte-dks0o4.svelte-dks0o4.svelte-dks0o4{display:flex;align-items:center;margin-top:var(--size-8);margin-bottom:var(--size-3);color:var(--body-text-color);font-weight:var(--weight-bold)}h4.svelte-dks0o4 svg.svelte-dks0o4.svelte-dks0o4{margin-right:var(--size-1-5)}.snippets.svelte-dks0o4.svelte-dks0o4.svelte-dks0o4{display:flex;align-items:center;margin-bottom:var(--size-3)}.snippets.svelte-dks0o4>.svelte-dks0o4+.svelte-dks0o4{margin-left:var(--size-2)}.snippet.svelte-dks0o4.svelte-dks0o4.svelte-dks0o4{display:flex;align-items:center;border:1px solid var(--border-color-primary);border-radius:var(--radius-md);padding:var(--size-1) var(--size-1-5);color:var(--body-text-color-subdued);color:var(--body-text-color);line-height:1;user-select:none;text-transform:capitalize}.current-lang.svelte-dks0o4.svelte-dks0o4.svelte-dks0o4{border:1px solid var(--body-text-color-subdued);color:var(--body-text-color)}.inactive-lang.svelte-dks0o4.svelte-dks0o4.svelte-dks0o4{cursor:pointer;color:var(--body-text-color-subdued)}.inactive-lang.svelte-dks0o4.svelte-dks0o4.svelte-dks0o4:hover,.inactive-lang.svelte-dks0o4.svelte-dks0o4.svelte-dks0o4:focus{box-shadow:var(--shadow-drop);color:var(--body-text-color)}.snippet.svelte-dks0o4 img.svelte-dks0o4.svelte-dks0o4{margin-right:var(--size-1-5);width:var(--size-3)}code.svelte-dks0o4 pre.svelte-dks0o4.svelte-dks0o4{overflow-x:auto;color:var(--body-text-color);font-family:var(--font-mono);tab-size:2}.client.svelte-dks0o4.svelte-dks0o4.svelte-dks0o4{white-space:pre-wrap;overflow-wrap:break-word}.token.string.svelte-dks0o4.svelte-dks0o4.svelte-dks0o4{display:contents;color:var(--color-accent-base)}code.svelte-dks0o4.svelte-dks0o4.svelte-dks0o4{position:relative}.copy.svelte-dks0o4.svelte-dks0o4.svelte-dks0o4{position:absolute;top:0;right:0;margin:1rem}.banner-wrap.svelte-1kj0q1l{position:relative;border-bottom:1px solid var(--border-color-primary);padding:var(--size-4) var(--size-6);font-size:var(--text-md)}@media (min-width: 768px){.banner-wrap.svelte-1kj0q1l{font-size:var(--text-xl)}}.docs-wrap.svelte-1kj0q1l{display:flex;flex-direction:column;gap:var(--spacing-xxl)}.endpoint.svelte-1kj0q1l{border-radius:var(--radius-md);background:var(--background-fill-primary);padding:var(--size-6);font-size:var(--text-md)}.wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;flex-grow:1;flex-direction:column;width:var(--size-full);font-weight:var(--body-text-weight);font-size:var(--body-text-size)}footer.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;justify-content:center;margin-top:var(--size-4);color:var(--body-text-color-subdued)}footer.svelte-1lyswbr>.svelte-1lyswbr+.svelte-1lyswbr{margin-left:var(--size-2)}.show-api.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;align-items:center}.show-api.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr:hover{color:var(--body-text-color)}.show-api.svelte-1lyswbr img.svelte-1lyswbr.svelte-1lyswbr{margin-right:var(--size-1);margin-left:var(--size-2);width:var(--size-3)}.built-with.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;align-items:center}.built-with.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr:hover{color:var(--body-text-color)}.built-with.svelte-1lyswbr img.svelte-1lyswbr.svelte-1lyswbr{margin-right:var(--size-1);margin-left:var(--size-2);width:var(--size-3)}.api-docs.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;position:fixed;top:0;right:0;z-index:var(--layer-5);background:rgba(0,0,0,.5);width:var(--size-screen);height:var(--size-screen-h)}.backdrop.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{flex:1 1 0%;backdrop-filter:blur(4px)}.api-docs-wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{box-shadow:var(--shadow-drop-lg);background:var(--background-fill-primary);overflow-x:hidden;overflow-y:auto}@media (min-width: 768px){.api-docs-wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{border-top-left-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg);width:950px}}@media (min-width: 1536px){.api-docs-wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{width:1150px}}
diff --git a/gradio/templates/cdn/assets/Blocks.1c8a32b7.js b/gradio/templates/cdn/assets/Blocks.1c8a32b7.js
new file mode 100644
index 0000000000000000000000000000000000000000..866c05bc8e42a6b6241a6c42cfa50e9ab1345c3e
--- /dev/null
+++ b/gradio/templates/cdn/assets/Blocks.1c8a32b7.js
@@ -0,0 +1,76 @@
+const VERSION_RE = new RegExp("3.23.0/", "g");function import_fix(mod, base) {const url = new URL(mod, base); return import(`https://gradio.s3-us-west-2.amazonaws.com/3.23.0/${url.pathname?.startsWith('/') ? url.pathname.substring(1).replace(VERSION_RE, "") : url.pathname.replace(VERSION_RE, "")}`);}import{d as be,w as rt,_ as j,S as K,i as $,s as ee,b as we,a as mt,c as V,e as ne,m as z,f as I,g as fo,h as co,j as _o,k as oe,t as D,l as X,n as ae,o as x,p as S,q as it,r as on,u as po,v as mo,x as je,y as ho,z as go,A as xe,B as E,C as ie,D as h,E as re,F as w,G as L,H as P,I as _e,J as B,K as Pe,L as vo,M as De,N as ye,O as ht,P as bo,Q as yo,R as Eo,T as So,U as To,V as wo}from"./index.7a68216a.js";import{B as ot,a as at}from"./Empty.svelte_svelte_type_style_lang.d7a3af78.js";var Io=function(t){return Ao(t)&&!Po(t)};function Ao(e){return!!e&&typeof e=="object"}function Po(e){var t=Object.prototype.toString.call(e);return t==="[object RegExp]"||t==="[object Date]"||ko(e)}var Co=typeof Symbol=="function"&&Symbol.for,Oo=Co?Symbol.for("react.element"):60103;function ko(e){return e.$$typeof===Oo}function xo(e){return Array.isArray(e)?[]:{}}function Ie(e,t){return t.clone!==!1&&t.isMergeableObject(e)?de(xo(e),e,t):e}function Lo(e,t,n){return e.concat(t).map(function(r){return Ie(r,n)})}function Ro(e,t){if(!t.customMerge)return de;var n=t.customMerge(e);return typeof n=="function"?n:de}function No(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(t){return e.propertyIsEnumerable(t)}):[]}function gt(e){return Object.keys(e).concat(No(e))}function an(e,t){try{return t in e}catch{return!1}}function jo(e,t){return an(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))}function Do(e,t,n){var r={};return n.isMergeableObject(e)&>(e).forEach(function(i){r[i]=Ie(e[i],n)}),gt(t).forEach(function(i){jo(e,i)||(an(e,i)&&n.isMergeableObject(t[i])?r[i]=Ro(i,n)(e[i],t[i],n):r[i]=Ie(t[i],n))}),r}function de(e,t,n){n=n||{},n.arrayMerge=n.arrayMerge||Lo,n.isMergeableObject=n.isMergeableObject||Io,n.cloneUnlessOtherwiseSpecified=Ie;var r=Array.isArray(t),i=Array.isArray(e),o=r===i;return o?r?n.arrayMerge(e,t,n):Do(e,t,n):Ie(t,n)}de.all=function(t,n){if(!Array.isArray(t))throw new Error("first argument should be an array");return t.reduce(function(r,i){return de(r,i,n)},{})};var Mo=de,Fo=Mo;/*! *****************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */var Je=function(e,t){return Je=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(n,r){n.__proto__=r}||function(n,r){for(var i in r)Object.prototype.hasOwnProperty.call(r,i)&&(n[i]=r[i])},Je(e,t)};function Fe(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");Je(e,t);function n(){this.constructor=e}e.prototype=t===null?Object.create(t):(n.prototype=t.prototype,new n)}var G=function(){return G=Object.assign||function(t){for(var n,r=1,i=arguments.length;r0}),n=[],r=0,i=t;r1)throw new RangeError("integer-width stems only accept a single optional option");i.options[0].replace(Ho,function(f,l,u,_,c,g){if(l)t.minimumIntegerDigits=u.length;else{if(_&&c)throw new Error("We currently do not support maximum integer digits");if(g)throw new Error("We currently do not support exact integer digits")}return""});continue}if(hn.test(i.stem)){t.minimumIntegerDigits=i.stem.length;continue}if(bt.test(i.stem)){if(i.options.length>1)throw new RangeError("Fraction-precision stems only accept a single optional option");i.stem.replace(bt,function(f,l,u,_,c,g){return u==="*"?t.minimumFractionDigits=l.length:_&&_[0]==="#"?t.maximumFractionDigits=_.length:c&&g?(t.minimumFractionDigits=c.length,t.maximumFractionDigits=c.length+g.length):(t.minimumFractionDigits=l.length,t.maximumFractionDigits=l.length),""});var o=i.options[0];o==="w"?t=G(G({},t),{trailingZeroDisplay:"stripIfInteger"}):o&&(t=G(G({},t),yt(o)));continue}if(mn.test(i.stem)){t=G(G({},t),yt(i.stem));continue}var s=gn(i.stem);s&&(t=G(G({},t),s));var a=Wo(i.stem);a&&(t=G(G({},t),a))}return t}var Be,Jo=new RegExp("^".concat(dn.source,"*")),Yo=new RegExp("".concat(dn.source,"*$"));function F(e,t){return{start:e,end:t}}var Qo=!!String.prototype.startsWith,Ko=!!String.fromCodePoint,$o=!!Object.fromEntries,ea=!!String.prototype.codePointAt,ta=!!String.prototype.trimStart,na=!!String.prototype.trimEnd,ra=!!Number.isSafeInteger,ia=ra?Number.isSafeInteger:function(e){return typeof e=="number"&&isFinite(e)&&Math.floor(e)===e&&Math.abs(e)<=9007199254740991},Qe=!0;try{var oa=bn("([^\\p{White_Space}\\p{Pattern_Syntax}]*)","yu");Qe=((Be=oa.exec("a"))===null||Be===void 0?void 0:Be[0])==="a"}catch{Qe=!1}var St=Qo?function(t,n,r){return t.startsWith(n,r)}:function(t,n,r){return t.slice(r,r+n.length)===n},Ke=Ko?String.fromCodePoint:function(){for(var t=[],n=0;no;){if(s=t[o++],s>1114111)throw RangeError(s+" is not a valid code point");r+=s<65536?String.fromCharCode(s):String.fromCharCode(((s-=65536)>>10)+55296,s%1024+56320)}return r},Tt=$o?Object.fromEntries:function(t){for(var n={},r=0,i=t;r=r)){var i=t.charCodeAt(n),o;return i<55296||i>56319||n+1===r||(o=t.charCodeAt(n+1))<56320||o>57343?i:(i-55296<<10)+(o-56320)+65536}},aa=ta?function(t){return t.trimStart()}:function(t){return t.replace(Jo,"")},la=na?function(t){return t.trimEnd()}:function(t){return t.replace(Yo,"")};function bn(e,t){return new RegExp(e,t)}var $e;if(Qe){var wt=bn("([^\\p{White_Space}\\p{Pattern_Syntax}]*)","yu");$e=function(t,n){var r;wt.lastIndex=n;var i=wt.exec(t);return(r=i[1])!==null&&r!==void 0?r:""}}else $e=function(t,n){for(var r=[];;){var i=vn(t,n);if(i===void 0||yn(i)||ca(i))break;r.push(i),n+=i>=65536?2:1}return Ke.apply(void 0,r)};var sa=function(){function e(t,n){n===void 0&&(n={}),this.message=t,this.position={offset:0,line:1,column:1},this.ignoreTag=!!n.ignoreTag,this.requiresOtherClause=!!n.requiresOtherClause,this.shouldParseSkeletons=!!n.shouldParseSkeletons}return e.prototype.parse=function(){if(this.offset()!==0)throw Error("parser can only be used once");return this.parseMessage(0,"",!1)},e.prototype.parseMessage=function(t,n,r){for(var i=[];!this.isEOF();){var o=this.char();if(o===123){var s=this.parseArgument(t,r);if(s.err)return s;i.push(s.val)}else{if(o===125&&t>0)break;if(o===35&&(n==="plural"||n==="selectordinal")){var a=this.clonePosition();this.bump(),i.push({type:U.pound,location:F(a,this.clonePosition())})}else if(o===60&&!this.ignoreTag&&this.peek()===47){if(r)break;return this.error(M.UNMATCHED_CLOSING_TAG,F(this.clonePosition(),this.clonePosition()))}else if(o===60&&!this.ignoreTag&&et(this.peek()||0)){var s=this.parseTag(t,n);if(s.err)return s;i.push(s.val)}else{var s=this.parseLiteral(t,n);if(s.err)return s;i.push(s.val)}}}return{val:i,err:null}},e.prototype.parseTag=function(t,n){var r=this.clonePosition();this.bump();var i=this.parseTagName();if(this.bumpSpace(),this.bumpIf("/>"))return{val:{type:U.literal,value:"<".concat(i,"/>"),location:F(r,this.clonePosition())},err:null};if(this.bumpIf(">")){var o=this.parseMessage(t+1,n,!0);if(o.err)return o;var s=o.val,a=this.clonePosition();if(this.bumpIf("")){if(this.isEOF()||!et(this.char()))return this.error(M.INVALID_TAG,F(a,this.clonePosition()));var f=this.clonePosition(),l=this.parseTagName();return i!==l?this.error(M.UNMATCHED_CLOSING_TAG,F(f,this.clonePosition())):(this.bumpSpace(),this.bumpIf(">")?{val:{type:U.tag,value:i,children:s,location:F(r,this.clonePosition())},err:null}:this.error(M.INVALID_TAG,F(a,this.clonePosition())))}else return this.error(M.UNCLOSED_TAG,F(r,this.clonePosition()))}else return this.error(M.INVALID_TAG,F(r,this.clonePosition()))},e.prototype.parseTagName=function(){var t=this.offset();for(this.bump();!this.isEOF()&&fa(this.char());)this.bump();return this.message.slice(t,this.offset())},e.prototype.parseLiteral=function(t,n){for(var r=this.clonePosition(),i="";;){var o=this.tryParseQuote(n);if(o){i+=o;continue}var s=this.tryParseUnquoted(t,n);if(s){i+=s;continue}var a=this.tryParseLeftAngleBracket();if(a){i+=a;continue}break}var f=F(r,this.clonePosition());return{val:{type:U.literal,value:i,location:f},err:null}},e.prototype.tryParseLeftAngleBracket=function(){return!this.isEOF()&&this.char()===60&&(this.ignoreTag||!ua(this.peek()||0))?(this.bump(),"<"):null},e.prototype.tryParseQuote=function(t){if(this.isEOF()||this.char()!==39)return null;switch(this.peek()){case 39:return this.bump(),this.bump(),"'";case 123:case 60:case 62:case 125:break;case 35:if(t==="plural"||t==="selectordinal")break;return null;default:return null}this.bump();var n=[this.char()];for(this.bump();!this.isEOF();){var r=this.char();if(r===39)if(this.peek()===39)n.push(39),this.bump();else{this.bump();break}else n.push(r);this.bump()}return Ke.apply(void 0,n)},e.prototype.tryParseUnquoted=function(t,n){if(this.isEOF())return null;var r=this.char();return r===60||r===123||r===35&&(n==="plural"||n==="selectordinal")||r===125&&t>0?null:(this.bump(),Ke(r))},e.prototype.parseArgument=function(t,n){var r=this.clonePosition();if(this.bump(),this.bumpSpace(),this.isEOF())return this.error(M.EXPECT_ARGUMENT_CLOSING_BRACE,F(r,this.clonePosition()));if(this.char()===125)return this.bump(),this.error(M.EMPTY_ARGUMENT,F(r,this.clonePosition()));var i=this.parseIdentifierIfPossible().value;if(!i)return this.error(M.MALFORMED_ARGUMENT,F(r,this.clonePosition()));if(this.bumpSpace(),this.isEOF())return this.error(M.EXPECT_ARGUMENT_CLOSING_BRACE,F(r,this.clonePosition()));switch(this.char()){case 125:return this.bump(),{val:{type:U.argument,value:i,location:F(r,this.clonePosition())},err:null};case 44:return this.bump(),this.bumpSpace(),this.isEOF()?this.error(M.EXPECT_ARGUMENT_CLOSING_BRACE,F(r,this.clonePosition())):this.parseArgumentOptions(t,n,i,r);default:return this.error(M.MALFORMED_ARGUMENT,F(r,this.clonePosition()))}},e.prototype.parseIdentifierIfPossible=function(){var t=this.clonePosition(),n=this.offset(),r=$e(this.message,n),i=n+r.length;this.bumpTo(i);var o=this.clonePosition(),s=F(t,o);return{value:r,location:s}},e.prototype.parseArgumentOptions=function(t,n,r,i){var o,s=this.clonePosition(),a=this.parseIdentifierIfPossible().value,f=this.clonePosition();switch(a){case"":return this.error(M.EXPECT_ARGUMENT_TYPE,F(s,f));case"number":case"date":case"time":{this.bumpSpace();var l=null;if(this.bumpIf(",")){this.bumpSpace();var u=this.clonePosition(),_=this.parseSimpleArgStyleIfPossible();if(_.err)return _;var c=la(_.val);if(c.length===0)return this.error(M.EXPECT_ARGUMENT_STYLE,F(this.clonePosition(),this.clonePosition()));var g=F(u,this.clonePosition());l={style:c,styleLocation:g}}var p=this.tryParseArgumentClose(i);if(p.err)return p;var m=F(i,this.clonePosition());if(l&&St(l?.style,"::",0)){var d=aa(l.style.slice(2));if(a==="number"){var _=this.parseNumberSkeletonFromString(d,l.styleLocation);return _.err?_:{val:{type:U.number,value:r,location:m,style:_.val},err:null}}else{if(d.length===0)return this.error(M.EXPECT_DATE_TIME_SKELETON,m);var c={type:me.dateTime,pattern:d,location:l.styleLocation,parsedOptions:this.shouldParseSkeletons?zo(d):{}},C=a==="date"?U.date:U.time;return{val:{type:C,value:r,location:m,style:c},err:null}}}return{val:{type:a==="number"?U.number:a==="date"?U.date:U.time,value:r,location:m,style:(o=l?.style)!==null&&o!==void 0?o:null},err:null}}case"plural":case"selectordinal":case"select":{var T=this.clonePosition();if(this.bumpSpace(),!this.bumpIf(","))return this.error(M.EXPECT_SELECT_ARGUMENT_OPTIONS,F(T,G({},T)));this.bumpSpace();var y=this.parseIdentifierIfPossible(),b=0;if(a!=="select"&&y.value==="offset"){if(!this.bumpIf(":"))return this.error(M.EXPECT_PLURAL_ARGUMENT_OFFSET_VALUE,F(this.clonePosition(),this.clonePosition()));this.bumpSpace();var _=this.tryParseDecimalInteger(M.EXPECT_PLURAL_ARGUMENT_OFFSET_VALUE,M.INVALID_PLURAL_ARGUMENT_OFFSET_VALUE);if(_.err)return _;this.bumpSpace(),y=this.parseIdentifierIfPossible(),b=_.val}var A=this.tryParsePluralOrSelectOptions(t,a,n,y);if(A.err)return A;var p=this.tryParseArgumentClose(i);if(p.err)return p;var O=F(i,this.clonePosition());return a==="select"?{val:{type:U.select,value:r,options:Tt(A.val),location:O},err:null}:{val:{type:U.plural,value:r,options:Tt(A.val),offset:b,pluralType:a==="plural"?"cardinal":"ordinal",location:O},err:null}}default:return this.error(M.INVALID_ARGUMENT_TYPE,F(s,f))}},e.prototype.tryParseArgumentClose=function(t){return this.isEOF()||this.char()!==125?this.error(M.EXPECT_ARGUMENT_CLOSING_BRACE,F(t,this.clonePosition())):(this.bump(),{val:!0,err:null})},e.prototype.parseSimpleArgStyleIfPossible=function(){for(var t=0,n=this.clonePosition();!this.isEOF();){var r=this.char();switch(r){case 39:{this.bump();var i=this.clonePosition();if(!this.bumpUntil("'"))return this.error(M.UNCLOSED_QUOTE_IN_ARGUMENT_STYLE,F(i,this.clonePosition()));this.bump();break}case 123:{t+=1,this.bump();break}case 125:{if(t>0)t-=1;else return{val:this.message.slice(n.offset,this.offset()),err:null};break}default:this.bump();break}}return{val:this.message.slice(n.offset,this.offset()),err:null}},e.prototype.parseNumberSkeletonFromString=function(t,n){var r=[];try{r=Bo(t)}catch{return this.error(M.INVALID_NUMBER_SKELETON,n)}return{val:{type:me.number,tokens:r,location:n,parsedOptions:this.shouldParseSkeletons?Zo(r):{}},err:null}},e.prototype.tryParsePluralOrSelectOptions=function(t,n,r,i){for(var o,s=!1,a=[],f=new Set,l=i.value,u=i.location;;){if(l.length===0){var _=this.clonePosition();if(n!=="select"&&this.bumpIf("=")){var c=this.tryParseDecimalInteger(M.EXPECT_PLURAL_ARGUMENT_SELECTOR,M.INVALID_PLURAL_ARGUMENT_SELECTOR);if(c.err)return c;u=F(_,this.clonePosition()),l=this.message.slice(_.offset,this.offset())}else break}if(f.has(l))return this.error(n==="select"?M.DUPLICATE_SELECT_ARGUMENT_SELECTOR:M.DUPLICATE_PLURAL_ARGUMENT_SELECTOR,u);l==="other"&&(s=!0),this.bumpSpace();var g=this.clonePosition();if(!this.bumpIf("{"))return this.error(n==="select"?M.EXPECT_SELECT_ARGUMENT_SELECTOR_FRAGMENT:M.EXPECT_PLURAL_ARGUMENT_SELECTOR_FRAGMENT,F(this.clonePosition(),this.clonePosition()));var p=this.parseMessage(t+1,n,r);if(p.err)return p;var m=this.tryParseArgumentClose(g);if(m.err)return m;a.push([l,{value:p.val,location:F(g,this.clonePosition())}]),f.add(l),this.bumpSpace(),o=this.parseIdentifierIfPossible(),l=o.value,u=o.location}return a.length===0?this.error(n==="select"?M.EXPECT_SELECT_ARGUMENT_SELECTOR:M.EXPECT_PLURAL_ARGUMENT_SELECTOR,F(this.clonePosition(),this.clonePosition())):this.requiresOtherClause&&!s?this.error(M.MISSING_OTHER_CLAUSE,F(this.clonePosition(),this.clonePosition())):{val:a,err:null}},e.prototype.tryParseDecimalInteger=function(t,n){var r=1,i=this.clonePosition();this.bumpIf("+")||this.bumpIf("-")&&(r=-1);for(var o=!1,s=0;!this.isEOF();){var a=this.char();if(a>=48&&a<=57)o=!0,s=s*10+(a-48),this.bump();else break}var f=F(i,this.clonePosition());return o?(s*=r,ia(s)?{val:s,err:null}:this.error(n,f)):this.error(t,f)},e.prototype.offset=function(){return this.position.offset},e.prototype.isEOF=function(){return this.offset()===this.message.length},e.prototype.clonePosition=function(){return{offset:this.position.offset,line:this.position.line,column:this.position.column}},e.prototype.char=function(){var t=this.position.offset;if(t>=this.message.length)throw Error("out of bound");var n=vn(this.message,t);if(n===void 0)throw Error("Offset ".concat(t," is at invalid UTF-16 code unit boundary"));return n},e.prototype.error=function(t,n){return{val:null,err:{kind:t,message:this.message,location:n}}},e.prototype.bump=function(){if(!this.isEOF()){var t=this.char();t===10?(this.position.line+=1,this.position.column=1,this.position.offset+=1):(this.position.column+=1,this.position.offset+=t<65536?1:2)}},e.prototype.bumpIf=function(t){if(St(this.message,t,this.offset())){for(var n=0;n=0?(this.bumpTo(r),!0):(this.bumpTo(this.message.length),!1)},e.prototype.bumpTo=function(t){if(this.offset()>t)throw Error("targetOffset ".concat(t," must be greater than or equal to the current offset ").concat(this.offset()));for(t=Math.min(t,this.message.length);;){var n=this.offset();if(n===t)break;if(n>t)throw Error("targetOffset ".concat(t," is at invalid UTF-16 code unit boundary"));if(this.bump(),this.isEOF())break}},e.prototype.bumpSpace=function(){for(;!this.isEOF()&&yn(this.char());)this.bump()},e.prototype.peek=function(){if(this.isEOF())return null;var t=this.char(),n=this.offset(),r=this.message.charCodeAt(n+(t>=65536?2:1));return r??null},e}();function et(e){return e>=97&&e<=122||e>=65&&e<=90}function ua(e){return et(e)||e===47}function fa(e){return e===45||e===46||e>=48&&e<=57||e===95||e>=97&&e<=122||e>=65&&e<=90||e==183||e>=192&&e<=214||e>=216&&e<=246||e>=248&&e<=893||e>=895&&e<=8191||e>=8204&&e<=8205||e>=8255&&e<=8256||e>=8304&&e<=8591||e>=11264&&e<=12271||e>=12289&&e<=55295||e>=63744&&e<=64975||e>=65008&&e<=65533||e>=65536&&e<=983039}function yn(e){return e>=9&&e<=13||e===32||e===133||e>=8206&&e<=8207||e===8232||e===8233}function ca(e){return e>=33&&e<=35||e===36||e>=37&&e<=39||e===40||e===41||e===42||e===43||e===44||e===45||e>=46&&e<=47||e>=58&&e<=59||e>=60&&e<=62||e>=63&&e<=64||e===91||e===92||e===93||e===94||e===96||e===123||e===124||e===125||e===126||e===161||e>=162&&e<=165||e===166||e===167||e===169||e===171||e===172||e===174||e===176||e===177||e===182||e===187||e===191||e===215||e===247||e>=8208&&e<=8213||e>=8214&&e<=8215||e===8216||e===8217||e===8218||e>=8219&&e<=8220||e===8221||e===8222||e===8223||e>=8224&&e<=8231||e>=8240&&e<=8248||e===8249||e===8250||e>=8251&&e<=8254||e>=8257&&e<=8259||e===8260||e===8261||e===8262||e>=8263&&e<=8273||e===8274||e===8275||e>=8277&&e<=8286||e>=8592&&e<=8596||e>=8597&&e<=8601||e>=8602&&e<=8603||e>=8604&&e<=8607||e===8608||e>=8609&&e<=8610||e===8611||e>=8612&&e<=8613||e===8614||e>=8615&&e<=8621||e===8622||e>=8623&&e<=8653||e>=8654&&e<=8655||e>=8656&&e<=8657||e===8658||e===8659||e===8660||e>=8661&&e<=8691||e>=8692&&e<=8959||e>=8960&&e<=8967||e===8968||e===8969||e===8970||e===8971||e>=8972&&e<=8991||e>=8992&&e<=8993||e>=8994&&e<=9e3||e===9001||e===9002||e>=9003&&e<=9083||e===9084||e>=9085&&e<=9114||e>=9115&&e<=9139||e>=9140&&e<=9179||e>=9180&&e<=9185||e>=9186&&e<=9254||e>=9255&&e<=9279||e>=9280&&e<=9290||e>=9291&&e<=9311||e>=9472&&e<=9654||e===9655||e>=9656&&e<=9664||e===9665||e>=9666&&e<=9719||e>=9720&&e<=9727||e>=9728&&e<=9838||e===9839||e>=9840&&e<=10087||e===10088||e===10089||e===10090||e===10091||e===10092||e===10093||e===10094||e===10095||e===10096||e===10097||e===10098||e===10099||e===10100||e===10101||e>=10132&&e<=10175||e>=10176&&e<=10180||e===10181||e===10182||e>=10183&&e<=10213||e===10214||e===10215||e===10216||e===10217||e===10218||e===10219||e===10220||e===10221||e===10222||e===10223||e>=10224&&e<=10239||e>=10240&&e<=10495||e>=10496&&e<=10626||e===10627||e===10628||e===10629||e===10630||e===10631||e===10632||e===10633||e===10634||e===10635||e===10636||e===10637||e===10638||e===10639||e===10640||e===10641||e===10642||e===10643||e===10644||e===10645||e===10646||e===10647||e===10648||e>=10649&&e<=10711||e===10712||e===10713||e===10714||e===10715||e>=10716&&e<=10747||e===10748||e===10749||e>=10750&&e<=11007||e>=11008&&e<=11055||e>=11056&&e<=11076||e>=11077&&e<=11078||e>=11079&&e<=11084||e>=11085&&e<=11123||e>=11124&&e<=11125||e>=11126&&e<=11157||e===11158||e>=11159&&e<=11263||e>=11776&&e<=11777||e===11778||e===11779||e===11780||e===11781||e>=11782&&e<=11784||e===11785||e===11786||e===11787||e===11788||e===11789||e>=11790&&e<=11798||e===11799||e>=11800&&e<=11801||e===11802||e===11803||e===11804||e===11805||e>=11806&&e<=11807||e===11808||e===11809||e===11810||e===11811||e===11812||e===11813||e===11814||e===11815||e===11816||e===11817||e>=11818&&e<=11822||e===11823||e>=11824&&e<=11833||e>=11834&&e<=11835||e>=11836&&e<=11839||e===11840||e===11841||e===11842||e>=11843&&e<=11855||e>=11856&&e<=11857||e===11858||e>=11859&&e<=11903||e>=12289&&e<=12291||e===12296||e===12297||e===12298||e===12299||e===12300||e===12301||e===12302||e===12303||e===12304||e===12305||e>=12306&&e<=12307||e===12308||e===12309||e===12310||e===12311||e===12312||e===12313||e===12314||e===12315||e===12316||e===12317||e>=12318&&e<=12319||e===12320||e===12336||e===64830||e===64831||e>=65093&&e<=65094}function tt(e){e.forEach(function(t){if(delete t.location,fn(t)||cn(t))for(var n in t.options)delete t.options[n].location,tt(t.options[n].value);else ln(t)&&pn(t.style)||(sn(t)||un(t))&&Ye(t.style)?delete t.style.location:_n(t)&&tt(t.children)})}function _a(e,t){t===void 0&&(t={}),t=G({shouldParseSkeletons:!0,requiresOtherClause:!0},t);var n=new sa(e,t).parse();if(n.err){var r=SyntaxError(M[n.err.kind]);throw r.location=n.err.location,r.originalMessage=n.err.message,r}return t?.captureLocation||tt(n.val),n.val}function qe(e,t){var n=t&&t.cache?t.cache:va,r=t&&t.serializer?t.serializer:ga,i=t&&t.strategy?t.strategy:da;return i(e,{cache:n,serializer:r})}function pa(e){return e==null||typeof e=="number"||typeof e=="boolean"}function En(e,t,n,r){var i=pa(r)?r:n(r),o=t.get(i);return typeof o>"u"&&(o=e.call(this,r),t.set(i,o)),o}function Sn(e,t,n){var r=Array.prototype.slice.call(arguments,3),i=n(r),o=t.get(i);return typeof o>"u"&&(o=e.apply(this,r),t.set(i,o)),o}function lt(e,t,n,r,i){return n.bind(t,e,r,i)}function da(e,t){var n=e.length===1?En:Sn;return lt(e,this,n,t.cache.create(),t.serializer)}function ma(e,t){return lt(e,this,Sn,t.cache.create(),t.serializer)}function ha(e,t){return lt(e,this,En,t.cache.create(),t.serializer)}var ga=function(){return JSON.stringify(arguments)};function st(){this.cache=Object.create(null)}st.prototype.get=function(e){return this.cache[e]};st.prototype.set=function(e,t){this.cache[e]=t};var va={create:function(){return new st}},He={variadic:ma,monadic:ha},he;(function(e){e.MISSING_VALUE="MISSING_VALUE",e.INVALID_VALUE="INVALID_VALUE",e.MISSING_INTL_API="MISSING_INTL_API"})(he||(he={}));var Ge=function(e){Fe(t,e);function t(n,r,i){var o=e.call(this,n)||this;return o.code=r,o.originalMessage=i,o}return t.prototype.toString=function(){return"[formatjs Error: ".concat(this.code,"] ").concat(this.message)},t}(Error),It=function(e){Fe(t,e);function t(n,r,i,o){return e.call(this,'Invalid values for "'.concat(n,'": "').concat(r,'". Options are "').concat(Object.keys(i).join('", "'),'"'),he.INVALID_VALUE,o)||this}return t}(Ge),ba=function(e){Fe(t,e);function t(n,r,i){return e.call(this,'Value for "'.concat(n,'" must be of type ').concat(r),he.INVALID_VALUE,i)||this}return t}(Ge),ya=function(e){Fe(t,e);function t(n,r){return e.call(this,'The intl string context variable "'.concat(n,'" was not provided to the string "').concat(r,'"'),he.MISSING_VALUE,r)||this}return t}(Ge),Z;(function(e){e[e.literal=0]="literal",e[e.object=1]="object"})(Z||(Z={}));function Ea(e){return e.length<2?e:e.reduce(function(t,n){var r=t[t.length-1];return!r||r.type!==Z.literal||n.type!==Z.literal?t.push(n):r.value+=n.value,t},[])}function Sa(e){return typeof e=="function"}function Le(e,t,n,r,i,o,s){if(e.length===1&&vt(e[0]))return[{type:Z.literal,value:e[0].value}];for(var a=[],f=0,l=e;fn&&(t in fe||(fe[t]={}),e in fe[t]||(fe[t][e]=n),n),Tn=(e,t)=>{if(t==null)return;if(t in fe&&e in fe[t])return fe[t][e];const n=Oe(t);for(let r=0;r0){const a=i.slice(s,i.length).join(".");if(a in o){o=o[a];break}}o=o[i[s]]}else o=void 0;return o}(function(n){return ut[n]||null}(e),t):null}function In(e,...t){delete fe[e],Ce.update(n=>(n[e]=Fo.all([n[e]||{},...t]),n))}be([Ce],([e])=>Object.keys(e));Ce.subscribe(e=>ut=e);const Re={};function An(e){return Re[e]}function Me(e){return e!=null&&Oe(e).some(t=>{var n;return(n=An(t))===null||n===void 0?void 0:n.size})}function ka(e,t){return Promise.all(t.map(n=>(function(r,i){Re[r].delete(i),Re[r].size===0&&delete Re[r]}(e,n),n().then(r=>r.default||r)))).then(n=>In(e,...n))}const Se={};function Pn(e){if(!Me(e))return e in Se?Se[e]:Promise.resolve();const t=function(n){return Oe(n).map(r=>{const i=An(r);return[r,i?[...i]:[]]}).filter(([,r])=>r.length>0)}(e);return Se[e]=Promise.all(t.map(([n,r])=>ka(n,r))).then(()=>{if(Me(e))return Pn(e);delete Se[e]}),Se[e]}/*! *****************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */function pe(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function"){var i=0;for(r=Object.getOwnPropertySymbols(e);ir.slice(0,n+1).join("-")).reverse()}function Oe(e,t=ge().fallbackLocale){const n=At(e);return t?[...new Set([...n,...At(t)])]:n}function ce(){return nt??void 0}Ne.subscribe(e=>{nt=e??void 0,typeof window<"u"&&e!=null&&document.documentElement.setAttribute("lang",e)});const Ee=Object.assign(Object.assign({},Ne),{set:e=>{if(e&&function(t){if(t==null)return;const n=Oe(t);for(let r=0;rZe.set(!0),t):Ze.set(!0),Pn(e).then(()=>{Ne.set(e)}).finally(()=>{clearTimeout(n),Ze.set(!1)})}return Ne.set(e)}}),La=()=>typeof window>"u"?null:window.navigator.language||window.navigator.languages[0],Ue=e=>{const t=Object.create(null);return n=>{const r=JSON.stringify(n);return r in t?t[r]:t[r]=e(n)}},Ae=(e,t)=>{const{formats:n}=ge();if(e in n&&t in n[e])return n[e][t];throw new Error(`[svelte-i18n] Unknown "${t}" ${e} format.`)},Ra=Ue(e=>{var{locale:t,format:n}=e,r=pe(e,["locale","format"]);if(t==null)throw new Error('[svelte-i18n] A "locale" must be set to format numbers');return n&&(r=Ae("number",n)),new Intl.NumberFormat(t,r)}),Na=Ue(e=>{var{locale:t,format:n}=e,r=pe(e,["locale","format"]);if(t==null)throw new Error('[svelte-i18n] A "locale" must be set to format dates');return n?r=Ae("date",n):Object.keys(r).length===0&&(r=Ae("date","short")),new Intl.DateTimeFormat(t,r)}),ja=Ue(e=>{var{locale:t,format:n}=e,r=pe(e,["locale","format"]);if(t==null)throw new Error('[svelte-i18n] A "locale" must be set to format time values');return n?r=Ae("time",n):Object.keys(r).length===0&&(r=Ae("time","short")),new Intl.DateTimeFormat(t,r)}),Da=(e={})=>{var{locale:t=ce()}=e,n=pe(e,["locale"]);return Ra(Object.assign({locale:t},n))},Ma=(e={})=>{var{locale:t=ce()}=e,n=pe(e,["locale"]);return Na(Object.assign({locale:t},n))},Fa=(e={})=>{var{locale:t=ce()}=e,n=pe(e,["locale"]);return ja(Object.assign({locale:t},n))},Ga=Ue((e,t=ce())=>new Pa(e,t,ge().formats,{ignoreTag:ge().ignoreTag})),Ua=(e,t={})=>{let n=t;typeof e=="object"&&(n=e,e=n.id);const{values:r,locale:i=ce(),default:o}=n;if(i==null)throw new Error("[svelte-i18n] Cannot format a message without first setting the initial locale.");let s=Tn(e,i);if(s){if(typeof s!="string")return console.warn(`[svelte-i18n] Message with id "${e}" must be of type "string", found: "${typeof s}". Gettin its value through the "$format" method is deprecated; use the "json" method instead.`),s}else ge().warnOnMissingMessages&&console.warn(`[svelte-i18n] The message "${e}" was not found in "${Oe(i).join('", "')}".${Me(ce())?`
+
+Note: there are at least one loader still registered to this locale that wasn't executed.`:""}`),s=o??e;if(!r)return s;let a=s;try{a=Ga(s,i).format(r)}catch(f){console.warn(`[svelte-i18n] Message "${e}" has syntax error:`,f.message)}return a},Va=(e,t)=>Fa(t).format(e),za=(e,t)=>Ma(t).format(e),Xa=(e,t)=>Da(t).format(e),Ba=(e,t=ce())=>Tn(e,t),Ds=be([Ee,Ce],()=>Ua);be([Ee],()=>Va);be([Ee],()=>za);be([Ee],()=>Xa);be([Ee,Ce],()=>Ba);const qa={accordion:()=>j(()=>import_fix("./index.40b39df7.js", import.meta.url),["assets/index.40b39df7.js","assets/index.5aa71568.css","assets/Column.svelte_svelte_type_style_lang.c4c23b6e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/Column.69198682.js"]),audio:()=>j(()=>import_fix("./index.e1c9d5ed.js", import.meta.url),["assets/index.e1c9d5ed.js","assets/index.949232a2.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/UploadText.e78ad6f6.js","assets/UploadText.41b55f5d.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/Upload.c051b7dd.js","assets/ModifyUpload.svelte_svelte_type_style_lang.e946db2d.js","assets/ModifyUpload.svelte_svelte_type_style_lang.8c17392b.css","assets/ModifyUpload.06b7f9d9.js","assets/BlockLabel.fd555cfa.js","assets/Empty.092ff864.js"]),box:()=>j(()=>import_fix("./index.3da5988a.js", import.meta.url),["assets/index.3da5988a.js","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css"]),button:()=>j(()=>import_fix("./index.e0b9fbc0.js", import.meta.url),["assets/index.e0b9fbc0.js","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css"]),chatbot:()=>j(()=>import_fix("./index.af23fb3b.js", import.meta.url),["assets/index.af23fb3b.js","assets/index.c402ae1d.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockLabel.fd555cfa.js","assets/ModifyUpload.svelte_svelte_type_style_lang.e946db2d.js","assets/ModifyUpload.svelte_svelte_type_style_lang.8c17392b.css"]),checkbox:()=>j(()=>import_fix("./index.80349daf.js", import.meta.url),["assets/index.80349daf.js","assets/ColorPicker.svelte_svelte_type_style_lang.adee3b52.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/Info.4b69e77f.js"]),checkboxgroup:()=>j(()=>import_fix("./index.83ae7361.js", import.meta.url),["assets/index.83ae7361.js","assets/ColorPicker.svelte_svelte_type_style_lang.adee3b52.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockTitle.39fa370e.js","assets/Info.4b69e77f.js"]),code:()=>j(()=>import_fix("./index.bb94c2e1.js", import.meta.url).then(function(e){return e.F}),["assets/index.bb94c2e1.js","assets/index.4d8c967c.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockLabel.fd555cfa.js","assets/Empty.092ff864.js","assets/Copy.fa9f7398.js","assets/Download.e46fa6ff.js"]),colorpicker:()=>j(()=>import_fix("./index.e2d743e9.js", import.meta.url),["assets/index.e2d743e9.js","assets/ColorPicker.svelte_svelte_type_style_lang.adee3b52.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockTitle.39fa370e.js","assets/Info.4b69e77f.js"]),column:()=>j(()=>import_fix("./index.ea70dbd1.js", import.meta.url),["assets/index.ea70dbd1.js","assets/Column.svelte_svelte_type_style_lang.c4c23b6e.css","assets/Column.69198682.js","assets/index.7a68216a.js","assets/index.f554ccc1.css"]),dataframe:()=>j(()=>import_fix("./index.85ca7b2d.js", import.meta.url),["assets/index.85ca7b2d.js","assets/index.ed3a7ba6.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Upload.c051b7dd.js","assets/ModifyUpload.svelte_svelte_type_style_lang.e946db2d.js","assets/ModifyUpload.svelte_svelte_type_style_lang.8c17392b.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/dsv.7fe76a93.js"]),dataset:()=>j(()=>import_fix("./index.3d25a9cb.js", import.meta.url),["assets/index.3d25a9cb.js","assets/index.a3fdfec5.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/_commonjsHelpers.a5007c1f.js","assets/Image.2e852803.js","assets/Image.3a14ca24.css","assets/csv.27f5436c.js","assets/dsv.7fe76a93.js","assets/Model3D.83383452.js","assets/Model3D.586493bd.css"]),dropdown:()=>j(()=>import_fix("./index.55e01de6.js", import.meta.url),["assets/index.55e01de6.js","assets/ColorPicker.svelte_svelte_type_style_lang.adee3b52.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockTitle.39fa370e.js","assets/Info.4b69e77f.js"]),file:()=>j(()=>import_fix("./index.39c24762.js", import.meta.url),["assets/index.39c24762.js","assets/index.6da2d824.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockLabel.fd555cfa.js","assets/Empty.092ff864.js","assets/File.7698c472.js","assets/Upload.c051b7dd.js","assets/ModifyUpload.svelte_svelte_type_style_lang.e946db2d.js","assets/ModifyUpload.svelte_svelte_type_style_lang.8c17392b.css","assets/ModifyUpload.06b7f9d9.js","assets/UploadText.e78ad6f6.js","assets/UploadText.41b55f5d.css"]),form:()=>j(()=>import_fix("./index.30201970.js", import.meta.url),["assets/index.30201970.js","assets/Form.c11fdf11.js","assets/Form.0a7d9dad.css","assets/index.7a68216a.js","assets/index.f554ccc1.css"]),gallery:()=>j(()=>import_fix("./index.8cea8982.js", import.meta.url),["assets/index.8cea8982.js","assets/index.5c217706.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockLabel.fd555cfa.js","assets/Empty.092ff864.js","assets/ModifyUpload.svelte_svelte_type_style_lang.e946db2d.js","assets/ModifyUpload.svelte_svelte_type_style_lang.8c17392b.css","assets/ModifyUpload.06b7f9d9.js","assets/Image.f3d382f6.js"]),group:()=>j(()=>import_fix("./index.c4b8839e.js", import.meta.url),["assets/index.c4b8839e.js","assets/index.722bec8b.css","assets/index.7a68216a.js","assets/index.f554ccc1.css"]),highlightedtext:()=>j(()=>import_fix("./index.56de6705.js", import.meta.url),["assets/index.56de6705.js","assets/index.6f761b5e.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/color.f2fbe15a.js","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockLabel.fd555cfa.js","assets/Empty.092ff864.js"]),html:()=>j(()=>import_fix("./index.878f7f07.js", import.meta.url),["assets/index.878f7f07.js","assets/index.f6ac8e97.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css"]),image:()=>j(()=>import_fix("./index.97197b8e.js", import.meta.url),["assets/index.97197b8e.js","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockLabel.fd555cfa.js","assets/Image.f3d382f6.js","assets/StaticImage.svelte_svelte_type_style_lang.8bc35352.js","assets/StaticImage.svelte_svelte_type_style_lang.b09e12d3.css","assets/ModifyUpload.06b7f9d9.js","assets/ModifyUpload.svelte_svelte_type_style_lang.e946db2d.js","assets/ModifyUpload.svelte_svelte_type_style_lang.8c17392b.css","assets/Upload.c051b7dd.js","assets/Empty.092ff864.js","assets/Download.e46fa6ff.js","assets/UploadText.e78ad6f6.js","assets/UploadText.41b55f5d.css","assets/Image.2e852803.js","assets/Image.3a14ca24.css"]),interpretation:()=>j(()=>import_fix("./index.06965fd8.js", import.meta.url),["assets/index.06965fd8.js","assets/index.8b2a7651.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockTitle.39fa370e.js","assets/Info.4b69e77f.js"]),json:()=>j(()=>import_fix("./index.64577800.js", import.meta.url),["assets/index.64577800.js","assets/index.61c7b416.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Copy.fa9f7398.js","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/Empty.092ff864.js","assets/BlockLabel.fd555cfa.js"]),label:()=>j(()=>import_fix("./index.30c92780.js", import.meta.url),["assets/index.30c92780.js","assets/index.b68d5aeb.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockLabel.fd555cfa.js","assets/Empty.092ff864.js"]),markdown:()=>j(()=>import_fix("./index.34f6d1fb.js", import.meta.url),["assets/index.34f6d1fb.js","assets/index.24229075.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css"]),model3d:()=>j(()=>import_fix("./index.a84bb2ee.js", import.meta.url),["assets/index.a84bb2ee.js","assets/index.00ec9920.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/ModifyUpload.svelte_svelte_type_style_lang.e946db2d.js","assets/ModifyUpload.svelte_svelte_type_style_lang.8c17392b.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockLabel.fd555cfa.js","assets/Empty.092ff864.js","assets/File.7698c472.js","assets/ModifyUpload.06b7f9d9.js","assets/Download.e46fa6ff.js","assets/_commonjsHelpers.a5007c1f.js","assets/Upload.c051b7dd.js","assets/UploadText.e78ad6f6.js","assets/UploadText.41b55f5d.css","assets/Model3D.83383452.js","assets/Model3D.586493bd.css"]),number:()=>j(()=>import_fix("./index.57d6d677.js", import.meta.url),["assets/index.57d6d677.js","assets/ColorPicker.svelte_svelte_type_style_lang.adee3b52.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockTitle.39fa370e.js","assets/Info.4b69e77f.js"]),plot:()=>j(()=>import_fix("./index.3c2bfbb6.js", import.meta.url),["assets/index.3c2bfbb6.js","assets/index.84ff132c.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/_commonjsHelpers.a5007c1f.js","assets/color.f2fbe15a.js","assets/linear.955f0731.js","assets/dsv.7fe76a93.js","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/Empty.092ff864.js","assets/BlockLabel.fd555cfa.js"]),radio:()=>j(()=>import_fix("./index.dfbd6dc6.js", import.meta.url),["assets/index.dfbd6dc6.js","assets/ColorPicker.svelte_svelte_type_style_lang.adee3b52.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockTitle.39fa370e.js","assets/Info.4b69e77f.js"]),row:()=>j(()=>import_fix("./index.c37730ee.js", import.meta.url),["assets/index.c37730ee.js","assets/index.1c646c8a.css","assets/index.7a68216a.js","assets/index.f554ccc1.css"]),slider:()=>j(()=>import_fix("./index.dc42f427.js", import.meta.url),["assets/index.dc42f427.js","assets/ColorPicker.svelte_svelte_type_style_lang.adee3b52.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockTitle.39fa370e.js","assets/Info.4b69e77f.js"]),state:()=>j(()=>import_fix("./index.6d5e2b84.js", import.meta.url),["assets/index.6d5e2b84.js","assets/index.7a68216a.js","assets/index.f554ccc1.css"]),statustracker:()=>j(()=>import_fix("./index.77915823.js", import.meta.url),["assets/index.77915823.js","assets/index.7a68216a.js","assets/index.f554ccc1.css"]),tabs:()=>j(()=>import_fix("./index.945a2e37.js", import.meta.url),["assets/index.945a2e37.js","assets/Column.svelte_svelte_type_style_lang.c4c23b6e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/TabItem.svelte_svelte_type_style_lang.9666256d.js","assets/TabItem.svelte_svelte_type_style_lang.8ca4f84d.css"]),tabitem:()=>j(()=>import_fix("./index.26b0dde7.js", import.meta.url),["assets/index.26b0dde7.js","assets/Column.svelte_svelte_type_style_lang.c4c23b6e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/TabItem.svelte_svelte_type_style_lang.9666256d.js","assets/TabItem.svelte_svelte_type_style_lang.8ca4f84d.css","assets/Column.69198682.js"]),textbox:()=>j(()=>import_fix("./index.98512e69.js", import.meta.url),["assets/index.98512e69.js","assets/ColorPicker.svelte_svelte_type_style_lang.adee3b52.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/Textbox.563734b0.js","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockTitle.39fa370e.js","assets/Info.4b69e77f.js","assets/Copy.fa9f7398.js"]),timeseries:()=>j(()=>import_fix("./index.894bc2f2.js", import.meta.url),["assets/index.894bc2f2.js","assets/index.8f9fffde.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Upload.c051b7dd.js","assets/ModifyUpload.svelte_svelte_type_style_lang.e946db2d.js","assets/ModifyUpload.svelte_svelte_type_style_lang.8c17392b.css","assets/ModifyUpload.06b7f9d9.js","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/BlockLabel.fd555cfa.js","assets/Empty.092ff864.js","assets/color.f2fbe15a.js","assets/linear.955f0731.js","assets/csv.27f5436c.js","assets/dsv.7fe76a93.js","assets/UploadText.e78ad6f6.js","assets/UploadText.41b55f5d.css"]),uploadbutton:()=>j(()=>import_fix("./index.cb7c1df8.js", import.meta.url),["assets/index.cb7c1df8.js","assets/index.89ce7356.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/ModifyUpload.svelte_svelte_type_style_lang.e946db2d.js","assets/ModifyUpload.svelte_svelte_type_style_lang.8c17392b.css"]),video:()=>j(()=>import_fix("./index.aef9d94a.js", import.meta.url),["assets/index.aef9d94a.js","assets/index.ff5c67e2.css","assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css","assets/index.7a68216a.js","assets/index.f554ccc1.css","assets/ModifyUpload.svelte_svelte_type_style_lang.e946db2d.js","assets/ModifyUpload.svelte_svelte_type_style_lang.8c17392b.css","assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js","assets/Empty.svelte_svelte_type_style_lang.04656a45.css","assets/Upload.c051b7dd.js","assets/ModifyUpload.06b7f9d9.js","assets/BlockLabel.fd555cfa.js","assets/StaticImage.svelte_svelte_type_style_lang.8bc35352.js","assets/StaticImage.svelte_svelte_type_style_lang.b09e12d3.css","assets/Empty.092ff864.js","assets/UploadText.e78ad6f6.js","assets/UploadText.41b55f5d.css"])},Cn="\u0623\u0631\u0633\u0644",On="\u0623\u0645\u0633\u062D",kn="\u0641\u0633\u0650\u0651\u0631",xn="\u0628\u0644\u0650\u0651\u063A",Ln="\u0623\u0645\u062B\u0644\u0629",Rn="\u0623\u0648";var Ha={interface:{drop_image:"\u0623\u0633\u0642\u0637 \u0627\u0644\u0635\u0648\u0631\u0629 \u0647\u0646\u0627",drop_video:"\u0623\u0633\u0642\u0637 \u0627\u0644\u0641\u064A\u062F\u064A\u0648 \u0647\u0646\u0627",drop_audio:"\u0623\u0633\u0642\u0637 \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0635\u0648\u062A\u064A \u0647\u0646\u0627",drop_file:"\u0623\u0633\u0642\u0637 \u0627\u0644\u0645\u0644\u0641 \u0647\u0646\u0627",drop_csv:"\u0623\u0633\u0642\u0637 \u0645\u0644\u0641 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0647\u0646\u0627",click_to_upload:"\u0625\u0636\u063A\u0637 \u0644\u0644\u062A\u062D\u0645\u064A\u0644",view_api:"\u0625\u0633\u062A\u062E\u062F\u0645 \u0648\u0627\u062C\u0647\u0629 \u0627\u0644\u0628\u0631\u0645\u062C\u0629",built_with_Gradio:"\u062A\u0645 \u0627\u0644\u0625\u0646\u0634\u0627\u0621 \u0628\u0625\u0633\u062A\u062E\u062F\u0627\u0645 Gradio"},Submit:Cn,Clear:On,Interpret:kn,Flag:xn,Examples:Ln,or:Rn},Wa=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Cn,Clear:On,Interpret:kn,Flag:xn,Examples:Ln,or:Rn,default:Ha});const Nn="Absenden",jn="L\xF6schen",Dn="Ersteller",Mn="Flag",Fn="Beispiele",Gn="oder";var Za={interface:{drop_image:"Bild hier ablegen",drop_video:"Video hier ablegen",drop_audio:"Audio hier ablegen",drop_file:"Datei hier ablegen",drop_csv:"CSV Datei hier ablegen",click_to_upload:"Hochladen",view_api:"API anschauen",built_with_Gradio:"Mit Gradio erstellt"},Submit:Nn,Clear:jn,Interpret:Dn,Flag:Mn,Examples:Fn,or:Gn},Ja=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Nn,Clear:jn,Interpret:Dn,Flag:Mn,Examples:Fn,or:Gn,default:Za});const Un="Submit",Vn="Clear",zn="Interpret",Xn="Flag",Bn="Examples",qn="or";var Ya={interface:{drop_image:"Drop Image Here",drop_video:"Drop Video Here",drop_audio:"Drop Audio Here",drop_file:"Drop File Here",drop_csv:"Drop CSV Here",click_to_upload:"Click to Upload",view_api:"view the api",built_with_Gradio:"Built with gradio",copy_to_clipboard:"copy json",loading:"Loading",error:"ERROR",empty:"Empty"},Submit:Un,Clear:Vn,Interpret:zn,Flag:Xn,Examples:Bn,or:qn},Qa=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Un,Clear:Vn,Interpret:zn,Flag:Xn,Examples:Bn,or:qn,default:Ya});const Hn="Enviar",Wn="Limpiar",Zn="Interpretar",Jn="Avisar",Yn="Ejemplos",Qn="o";var Ka={interface:{drop_image:"Coloque la imagen aqu\xED",drop_video:"Coloque el video aqu\xED",drop_audio:"Coloque el audio aqu\xED",drop_file:"Coloque el archivo aqu\xED",drop_csv:"Coloque el CSV aqu\xED",click_to_upload:"Haga click para cargar",view_api:"Ver la API",built_with_Gradio:"Construido con Gradio"},Submit:Hn,Clear:Wn,Interpret:Zn,Flag:Jn,Examples:Yn,or:Qn},$a=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Hn,Clear:Wn,Interpret:Zn,Flag:Jn,Examples:Yn,or:Qn,default:Ka});const Kn="\u0627\u0631\u0633\u0627\u0644",$n="\u062D\u0630\u0641",er="\u062A\u0641\u0633\u06CC\u0631",tr="\u067E\u0631\u0686\u0645",nr="\u0645\u062B\u0627\u0644 \u0647\u0627",rr="\u06CC\u0627";var el={interface:{drop_image:"\u062A\u0635\u0648\u06CC\u0631 \u0631\u0627 \u0627\u06CC\u0646\u062C\u0627 \u0631\u0647\u0627 \u06A9\u0646\u06CC\u062F",drop_video:"\u0648\u06CC\u062F\u06CC\u0648 \u0631\u0627 \u0627\u06CC\u0646\u062C\u0627 \u0631\u0647\u0627 \u06A9\u0646\u06CC\u062F",drop_audio:"\u0635\u0648\u062A \u0631\u0627 \u0627\u06CC\u0646\u062C\u0627 \u0631\u0647\u0627 \u06A9\u0646\u06CC\u062F",drop_file:"\u0641\u0627\u06CC\u0644 \u0631\u0627 \u0627\u06CC\u0646\u062C\u0627 \u0631\u0647\u0627 \u06A9\u0646\u06CC\u062F",drop_csv:"\u0641\u0627\u06CC\u0644 csv \u0631\u0627 \u0627\u06CC\u0646\u062C\u0627 \u0631\u0647\u0627 \u06A9\u0646\u06CC\u062F",click_to_upload:"\u0628\u0631\u0627\u06CC \u0622\u067E\u0644\u0648\u062F \u06A9\u0644\u06CC\u06A9 \u06A9\u0646\u06CC\u062F",view_api:"api \u0631\u0627 \u0645\u0634\u0627\u0647\u062F\u0647 \u06A9\u0646\u06CC\u062F",built_with_Gradio:"\u0633\u0627\u062E\u062A\u0647 \u0634\u062F\u0647 \u0628\u0627 gradio"},Submit:Kn,Clear:$n,Interpret:er,Flag:tr,Examples:nr,or:rr},tl=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Kn,Clear:$n,Interpret:er,Flag:tr,Examples:nr,or:rr,default:el});const ir="Soumettre",or="Nettoyer",ar="Interpr\xE9ter",lr="Signaler",sr="Exemples",ur="ou";var nl={interface:{drop_image:"D\xE9poser l'Image Ici",drop_video:"D\xE9poser la Vid\xE9o Ici",drop_audio:"D\xE9poser l'Audio Ici",drop_file:"D\xE9poser le Fichier Ici",drop_csv:"D\xE9poser le CSV Ici",click_to_upload:"Cliquer pour T\xE9l\xE9charger",view_api:"Voir l'API",built_with_Gradio:"Con\xE7u avec Gradio"},Submit:ir,Clear:or,Interpret:ar,Flag:lr,Examples:sr,or:ur},rl=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:ir,Clear:or,Interpret:ar,Flag:lr,Examples:sr,or:ur,default:nl});const fr="\u05E9\u05DC\u05D7",cr="\u05E0\u05E7\u05D4",_r="\u05DC\u05E4\u05E8\u05E9",pr="\u05E1\u05DE\u05DF",dr="\u05D3\u05D5\u05D2\u05DE\u05D5\u05EA",mr="\u05D0\u05D5";var il={interface:{drop_image:"\u05D2\u05E8\u05D5\u05E8 \u05E7\u05D5\u05D1\u05E5 \u05EA\u05DE\u05D5\u05E0\u05D4 \u05DC\u05DB\u05D0\u05DF",drop_video:"\u05D2\u05E8\u05D5\u05E8 \u05E7\u05D5\u05D1\u05E5 \u05E1\u05E8\u05D8\u05D5\u05DF \u05DC\u05DB\u05D0\u05DF",drop_audio:"\u05D2\u05E8\u05D5\u05E8 \u05DC\u05DB\u05D0\u05DF \u05E7\u05D5\u05D1\u05E5 \u05E9\u05DE\u05E2",drop_file:"\u05D2\u05E8\u05D5\u05E8 \u05E7\u05D5\u05D1\u05E5 \u05DC\u05DB\u05D0\u05DF",drop_csv:"\u05D2\u05E8\u05D5\u05E8 csv \u05E7\u05D5\u05D1\u05E5 \u05DC\u05DB\u05D0\u05DF",click_to_upload:"\u05DC\u05D7\u05E5 \u05DB\u05D3\u05D9 \u05DC\u05D4\u05E2\u05DC\u05D5\u05EA",view_api:"\u05E6\u05E4\u05D4 \u05D1 API",built_with_Gradio:"\u05D1\u05E0\u05D5\u05D9 \u05E2\u05DD \u05D2\u05E8\u05D3\u05D9\u05D5"},Submit:fr,Clear:cr,Interpret:_r,Flag:pr,Examples:dr,or:mr},ol=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:fr,Clear:cr,Interpret:_r,Flag:pr,Examples:dr,or:mr,default:il});const hr="\u0938\u092C\u092E\u093F\u091F \u0915\u0930\u0947",gr="\u0939\u091F\u093E\u092F\u0947",vr="\u0935\u094D\u092F\u093E\u0916\u094D\u092F\u093E \u0915\u0930\u0947",br="\u091A\u093F\u0939\u094D\u0928\u093F\u0924 \u0915\u0930\u0947",yr="\u0909\u0926\u093E\u0939\u0930\u0923",Er="\u092F\u093E";var al={interface:{drop_image:"\u092F\u0939\u093E\u0901 \u0907\u092E\u0947\u091C \u0921\u094D\u0930\u0949\u092A \u0915\u0930\u0947\u0902",drop_video:"\u092F\u0939\u093E\u0901 \u0935\u0940\u0921\u093F\u092F\u094B \u0921\u094D\u0930\u0949\u092A \u0915\u0930\u0947\u0902",drop_audio:"\u092F\u0939\u093E\u0901 \u0911\u0921\u093F\u092F\u094B \u0921\u094D\u0930\u0949\u092A \u0915\u0930\u0947\u0902",drop_file:"\u092F\u0939\u093E\u0901 File \u0921\u094D\u0930\u0949\u092A \u0915\u0930\u0947\u0902",drop_csv:"\u092F\u0939\u093E\u0901 CSV \u0921\u094D\u0930\u0949\u092A \u0915\u0930\u0947\u0902",click_to_upload:"\u0905\u092A\u0932\u094B\u0921 \u0915\u0947 \u0932\u093F\u090F \u092C\u091F\u0928 \u0926\u092C\u093E\u092F\u0947\u0902",view_api:"API \u0915\u094B \u0926\u0947\u0916\u0947",built_with_Gradio:"Gradio \u0938\u0947 \u092C\u0928\u093E"},Submit:hr,Clear:gr,Interpret:vr,Flag:br,Examples:yr,or:Er},ll=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:hr,Clear:gr,Interpret:vr,Flag:br,Examples:yr,or:Er,default:al});const Sr="\u9001\u4FE1",Tr="\u30AF\u30EA\u30A2",wr="\u89E3\u91C8",Ir="\u30D5\u30E9\u30B0\u3059\u308B",Ar="\u5165\u529B\u4F8B",Pr="\u307E\u305F\u306F";var sl={interface:{drop_image:"\u3053\u3053\u306B\u753B\u50CF\u3092\u30C9\u30ED\u30C3\u30D7",drop_video:"\u3053\u3053\u306B\u52D5\u753B\u3092\u30C9\u30ED\u30C3\u30D7",drop_audio:"\u3053\u3053\u306B\u97F3\u58F0\u3092\u30C9\u30ED\u30C3\u30D7",drop_file:"\u3053\u3053\u306B\u30D5\u30A1\u30A4\u30EB\u3092\u30C9\u30ED\u30C3\u30D7",drop_csv:"\u3053\u3053\u306BCSV\u3092\u30C9\u30ED\u30C3\u30D7",click_to_upload:"\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9",view_api:"API\u3092\u898B\u308B",built_with_Gradio:"gradio\u3067\u4F5C\u308D\u3046"},Submit:Sr,Clear:Tr,Interpret:wr,Flag:Ir,Examples:Ar,or:Pr},ul=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Sr,Clear:Tr,Interpret:wr,Flag:Ir,Examples:Ar,or:Pr,default:sl});const Cr="\uC81C\uCD9C\uD558\uAE30",Or="\uD074\uB9AC\uC5B4",kr="\uC124\uBA85\uD558\uAE30",xr="\uD50C\uB798\uADF8",Lr="\uC608\uC2DC",Rr="\uB610\uB294";var fl={interface:{drop_image:"\uC774\uBBF8\uC9C0\uB97C \uB04C\uC5B4 \uB193\uC73C\uC138\uC694",drop_video:"\uBE44\uB514\uC624\uB97C \uB04C\uC5B4 \uB193\uC73C\uC138\uC694",drop_audio:"\uC624\uB514\uC624\uB97C \uB04C\uC5B4 \uB193\uC73C\uC138\uC694",drop_file:"\uD30C\uC77C\uC744 \uB04C\uC5B4 \uB193\uC73C\uC138\uC694",drop_csv:"CSV\uD30C\uC77C\uC744 \uB04C\uC5B4 \uB193\uC73C\uC138\uC694",click_to_upload:"\uD074\uB9AD\uD574\uC11C \uC5C5\uB85C\uB4DC\uD558\uAE30",view_api:"API \uBCF4\uAE30",built_with_Gradio:"gradio\uB85C \uC81C\uC791\uB418\uC5C8\uC2B5\uB2C8\uB2E4"},Submit:Cr,Clear:Or,Interpret:kr,Flag:xr,Examples:Lr,or:Rr},cl=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Cr,Clear:Or,Interpret:kr,Flag:xr,Examples:Lr,or:Rr,default:fl});const Nr="Pateikti",jr="Trinti",Dr="Interpretuoti",Mr="Pa\u017Eym\u0117ti",Fr="Pavyzd\u017Eiai",Gr="arba";var _l={interface:{drop_image:"\u012Ekelkite paveiksl\u0117l\u012F \u010Dia",drop_video:"\u012Ekelkite vaizdo \u012Fra\u0161\u0105 \u010Dia",drop_audio:"\u012Ekelkite garso \u012Fra\u0161\u0105 \u010Dia",drop_file:"\u012Ekelkite byl\u0105 \u010Dia",drop_csv:"\u012Ekelkite CSV \u010Dia",click_to_upload:"Spustel\u0117kite nor\u0117dami \u012Fkelti",view_api:"per\u017Ei\u016Br\u0117ti api",built_with_Gradio:"sukurta su gradio"},Submit:Nr,Clear:jr,Interpret:Dr,Flag:Mr,Examples:Fr,or:Gr},pl=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Nr,Clear:jr,Interpret:Dr,Flag:Mr,Examples:Fr,or:Gr,default:_l});const Ur="Zend in",Vr="Wis",zr="Interpreteer",Xr="Vlag",Br="Voorbeelden",qr="of";var dl={interface:{drop_image:"Sleep een Afbeelding hier",drop_video:"Sleep een Video hier",drop_audio:"Sleep een Geluidsbestand hier",drop_file:"Sleep een Document hier",drop_csv:"Sleep een CSV hier",click_to_upload:"Klik om the Uploaden",view_api:"zie de api",built_with_Gradio:"gemaakt met gradio"},Submit:Ur,Clear:Vr,Interpret:zr,Flag:Xr,Examples:Br,or:qr},ml=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Ur,Clear:Vr,Interpret:zr,Flag:Xr,Examples:Br,or:qr,default:dl});const Hr="Zatwierd\u017A",Wr="Wyczy\u015B\u0107",Zr="Interpretuj",Jr="Oznacz",Yr="Przyk\u0142ady",Qr="lub";var hl={interface:{drop_image:"Przeci\u0105gnij tutaj zdj\u0119cie",drop_video:"Przeci\u0105gnij tutaj video",drop_audio:"Przeci\u0105gnij tutaj audio",drop_file:"Przeci\u0105gnij tutaj plik",drop_csv:"Przeci\u0105gnij tutaj CSV",click_to_upload:"Kliknij, aby przes\u0142a\u0107",view_api:"zobacz api",built_with_Gradio:"utworzone z gradio"},Submit:Hr,Clear:Wr,Interpret:Zr,Flag:Jr,Examples:Yr,or:Qr},gl=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Hr,Clear:Wr,Interpret:Zr,Flag:Jr,Examples:Yr,or:Qr,default:hl});const Kr="Enviar",$r="Limpar",ei="Interpretar",ti="Marcar",ni="Exemplos",ri="ou";var vl={interface:{drop_image:"Solte a Imagem Aqui",drop_video:"Solte o V\xEDdeo Aqui",drop_audio:"Solte o \xC1udio Aqui",drop_file:"Solte o Arquivo Aqui",drop_csv:"Solte o CSV Aqui",click_to_upload:"Clique para o Upload",view_api:"Veja a API",built_with_Gradio:"Constru\xEDdo com gradio",copy_to_clipboard:"copiar para o clipboard",loading:"Carregando",error:"ERRO",empty:"Vazio"},Submit:Kr,Clear:$r,Interpret:ei,Flag:ti,Examples:ni,or:ri},bl=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Kr,Clear:$r,Interpret:ei,Flag:ti,Examples:ni,or:ri,default:vl});const ii="\u0418\u0441\u043F\u043E\u043B\u043D\u0438\u0442\u044C",oi="\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u044C",ai="\u0418\u043D\u0442\u0435\u0440\u043F\u0440\u0435\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C",li="\u041F\u043E\u043C\u0435\u0442\u0438\u0442\u044C",si="\u041F\u0440\u0438\u043C\u0435\u0440\u044B",ui="\u0438\u043B\u0438";var yl={interface:{drop_image:"\u041F\u043E\u043C\u0435\u0441\u0442\u0438\u0442\u0435 \u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u0417\u0434\u0435\u0441\u044C",drop_video:"\u041F\u043E\u043C\u0435\u0441\u0442\u0438\u0442\u0435 \u0412\u0438\u0434\u0435\u043E \u0417\u0434\u0435\u0441\u044C",drop_audio:"\u041F\u043E\u043C\u0435\u0441\u0442\u0438\u0442\u0435 \u0410\u0443\u0434\u0438\u043E \u0417\u0434\u0435\u0441\u044C",drop_file:"\u041F\u043E\u043C\u0435\u0441\u0442\u0438\u0442\u0435 \u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u0417\u0434\u0435\u0441\u044C",drop_csv:"\u041F\u043E\u043C\u0435\u0441\u0442\u0438\u0442\u0435 CSV \u0417\u0434\u0435\u0441\u044C",click_to_upload:"\u041D\u0430\u0436\u043C\u0438\u0442\u0435, \u0447\u0442\u043E\u0431\u044B \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C",view_api:"\u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440 api",built_with_Gradio:"\u0441\u0434\u0435\u043B\u0430\u043D\u043E \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E gradio"},Submit:ii,Clear:oi,Interpret:ai,Flag:li,Examples:si,or:ui},El=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:ii,Clear:oi,Interpret:ai,Flag:li,Examples:si,or:ui,default:yl});const fi="\u0B9A\u0BAE\u0BB0\u0BCD\u0BAA\u0BCD\u0BAA\u0BBF",ci="\u0B85\u0BB4\u0BBF",_i="\u0B89\u0B9F\u0BCD\u0BAA\u0BCA\u0BB0\u0BC1\u0BB3\u0BCD",pi="\u0B95\u0BCA\u0B9F\u0BBF\u0BAF\u0BBF\u0B9F\u0BC1",di="\u0B8E\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0B9F\u0BCD\u0B9F\u0BC1\u0B95\u0BB3\u0BCD",mi="\u0B85\u0BB2\u0BCD\u0BB2\u0BA4\u0BC1";var Sl={interface:{drop_image:"\u0BAA\u0B9F\u0BA4\u0BCD\u0BA4\u0BC8 \u0BB5\u0BC8",drop_video:"\u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB\u0BB5\u0BC8 \u0BB5\u0BC8",drop_audio:"\u0B86\u0B9F\u0BBF\u0BAF\u0BCB\u0BB5\u0BC8 \u0BB5\u0BC8",drop_file:"\u0B95\u0BCB\u0BAA\u0BCD\u0BAA\u0BC8 \u0BB5\u0BC8",drop_csv:"\u0B9A\u0BBF\u0B8E\u0BB8\u0BCD\u0BB5\u0BBF \u0BB5\u0BC8",click_to_upload:"\u0BAA\u0BA4\u0BBF\u0BB5\u0BC7\u0BB1\u0BCD\u0BB1 \u0B95\u0BBF\u0BB3\u0BBF\u0B95\u0BCD \u0B9A\u0BC6\u0BAF\u0BCD",view_api:"\u0B85\u0BAA\u0BBF\u0BAF\u0BC8 \u0B95\u0BBE\u0BA3\u0BCD",built_with_Gradio:"\u0B95\u0BCD\u0BB0\u0BC7\u0B9F\u0BBF\u0BAF\u0BCB-\u0BB5\u0BC1\u0B9F\u0BA9\u0BCD \u0B95\u0B9F\u0BCD\u0B9F\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F\u0BA4\u0BC1"},Submit:fi,Clear:ci,Interpret:_i,Flag:pi,Examples:di,or:mi},Tl=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:fi,Clear:ci,Interpret:_i,Flag:pi,Examples:di,or:mi,default:Sl});const hi="Y\xFCkle",gi="Temizle",vi="Yorumla",bi="Etiketle",yi="\xF6rnekler",Ei="veya";var wl={interface:{drop_image:"Resmi Buraya S\xFCr\xFCkle",drop_video:"Videoyu Buraya S\xFCr\xFCkle",drop_audio:"Kayd\u0131 Buraya S\xFCr\xFCkle",drop_file:"Dosyay\u0131 Buraya S\xFCr\xFCkle",drop_csv:"CSV'yi Buraya S\xFCr\xFCkle",click_to_upload:"Y\xFCklemek i\xE7in T\u0131kla",view_api:"api'yi g\xF6r\xFCnt\xFCle",built_with_Gradio:"Gradio ile olu\u015Fturulmu\u015Ftur"},Submit:hi,Clear:gi,Interpret:vi,Flag:bi,Examples:yi,or:Ei},Il=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:hi,Clear:gi,Interpret:vi,Flag:bi,Examples:yi,or:Ei,default:wl});const Si="\u041D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438",Ti="\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u0438",wi="\u041F\u043E\u044F\u0441\u043D\u0438\u0442\u0438 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442",Ii="\u041F\u043E\u0437\u043D\u0430\u0447\u0438\u0442\u0438",Ai="\u041F\u0440\u0438\u043A\u043B\u0430\u0434\u0438",Pi="\u0430\u0431\u043E";var Al={interface:{drop_image:"\u041F\u0435\u0440\u0435\u0442\u044F\u0433\u043D\u0456\u0442\u044C \u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u0441\u044E\u0434\u0438",drop_video:"\u041F\u0435\u0440\u0435\u0442\u044F\u0433\u043D\u0456\u0442\u044C \u0432\u0456\u0434\u0435\u043E \u0441\u044E\u0434\u0438",drop_audio:"\u041F\u0435\u0440\u0435\u0442\u044F\u0433\u043D\u0456\u0442\u044C \u0430\u0443\u0434\u0456\u043E \u0441\u044E\u0434\u0438",drop_file:"\u041F\u0435\u0440\u0435\u0442\u044F\u0433\u043D\u0456\u0442\u044C \u0444\u0430\u0439\u043B \u0441\u044E\u0434\u0438",drop_csv:"\u041F\u0435\u0440\u0435\u0442\u044F\u0433\u043D\u0456\u0442\u044C CSV-\u0444\u0430\u0439\u043B \u0441\u044E\u0434\u0438",click_to_upload:"\u041D\u0430\u0442\u0438\u0441\u043D\u0456\u0442\u044C \u0449\u043E\u0431 \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438",view_api:"\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 API",built_with_Gradio:"\u0417\u0440\u043E\u0431\u043B\u0435\u043D\u043E \u043D\u0430 \u043E\u0441\u043D\u043E\u0432\u0456 gradio"},Submit:Si,Clear:Ti,Interpret:wi,Flag:Ii,Examples:Ai,or:Pi},Pl=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Si,Clear:Ti,Interpret:wi,Flag:Ii,Examples:Ai,or:Pi,default:Al});const Ci="\u062C\u0645\u0639 \u06A9\u0631\u06CC\u06BA",Oi="\u06C1\u0679\u0627 \u062F\u06CC\u06BA",ki="\u062A\u0634\u0631\u06CC\u062D \u06A9\u0631\u06CC\u06BA",xi="\u0646\u0634\u0627\u0646 \u0644\u06AF\u0627\u0626\u06CC\u06BA",Li="\u0645\u062B\u0627\u0644\u06CC\u06BA",Ri="\u06CC\u0627";var Cl={interface:{drop_image:"\u06CC\u06C1\u0627\u06BA \u062A\u0635\u0648\u06CC\u0631 \u0688\u0631\u0627\u067E \u06A9\u0631\u06CC\u06BA",drop_video:"\u06CC\u06C1\u0627\u06BA \u0648\u06CC\u0688\u06CC\u0648 \u0688\u0631\u0627\u067E \u06A9\u0631\u06CC\u06BA",drop_audio:"\u06CC\u06C1\u0627\u06BA \u0622\u0688\u06CC\u0648 \u0688\u0631\u0627\u067E \u06A9\u0631\u06CC\u06BA",drop_file:"\u06CC\u06C1\u0627\u06BA \u0641\u0627\u0626\u0644 \u0688\u0631\u0627\u067E \u06A9\u0631\u06CC\u06BA",drop_csv:"\u06CC\u06C1\u0627\u06BA \u0641\u0627\u0626\u0644 \u0688\u0631\u0627\u067E \u06A9\u0631\u06CC\u06BA",click_to_upload:"\u0627\u067E \u0644\u0648\u0688 \u06A9\u06D2 \u0644\u06CC\u06D2 \u06A9\u0644\u06A9 \u06A9\u0631\u06CC\u06BA",view_api:"API \u062F\u06CC\u06A9\u06BE\u06CC\u06BA",built_with_Gradio:"\u06A9\u06D2 \u0633\u0627\u062A\u06BE \u0628\u0646\u0627\u06CC\u0627 \u06AF\u06CC\u0627 Gradio"},Submit:Ci,Clear:Oi,Interpret:ki,Flag:xi,Examples:Li,or:Ri},Ol=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Ci,Clear:Oi,Interpret:ki,Flag:xi,Examples:Li,or:Ri,default:Cl});const Ni="Yubor",ji="Tozalash",Di="Tushuntirish",Mi="Bayroq",Fi="Namunalar",Gi="\u6216";var kl={interface:{drop_image:"Rasmni Shu Yerga Tashlang",drop_video:"Videoni Shu Yerga Tashlang",drop_audio:"Audioni Shu Yerga Tashlang",drop_file:"Faylni Shu Yerga Tashlang",drop_csv:"CSVni Shu Yerga Tashlang",click_to_upload:"Yuklash uchun Bosing",view_api:"apini ko'ring",built_with_Gradio:"gradio bilan qilingan"},Submit:Ni,Clear:ji,Interpret:Di,Flag:Mi,Examples:Fi,or:Gi},xl=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Ni,Clear:ji,Interpret:Di,Flag:Mi,Examples:Fi,or:Gi,default:kl});const Ui="\u63D0\u4EA4",Vi="\u6E05\u9664",zi="\u89E3\u91CA",Xi="\u6807\u8BB0",Bi="\u793A\u4F8B",qi="\u6216";var Ll={interface:{drop_image:"\u62D6\u653E\u56FE\u7247\u81F3\u6B64\u5904",drop_video:"\u62D6\u653E\u89C6\u9891\u81F3\u6B64\u5904",drop_audio:"\u62D6\u653E\u97F3\u9891\u81F3\u6B64\u5904",drop_file:"\u62D6\u653E\u6587\u4EF6\u81F3\u6B64\u5904",drop_csv:"\u62D6\u653ECSV\u81F3\u6B64\u5904",click_to_upload:"\u70B9\u51FB\u4E0A\u4F20",view_api:"\u67E5\u770BAPI",built_with_Gradio:"\u4F7F\u7528Gradio\u6784\u5EFA"},Submit:Ui,Clear:Vi,Interpret:zi,Flag:Xi,Examples:Bi,or:qi},Rl=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Ui,Clear:Vi,Interpret:zi,Flag:Xi,Examples:Bi,or:qi,default:Ll});const Hi="\u63D0\u4EA4",Wi="\u6E05\u9664",Zi="\u89E3\u91CB",Ji="Flag",Yi="\u7BC4\u4F8B",Qi="\u6216";var Nl={interface:{drop_image:"\u522A\u9664\u5716\u7247",drop_video:"\u522A\u9664\u5F71\u7247",drop_audio:"\u522A\u9664\u97F3\u983B",drop_file:"\u522A\u9664\u6A94\u6848",drop_csv:"\u522A\u9664CSV",click_to_upload:"\u9EDE\u64CA\u4E0A\u50B3",view_api:"\u67E5\u770BAPI",built_with_Gradio:"\u4F7F\u7528Gradio\u69CB\u5EFA"},Submit:Hi,Clear:Wi,Interpret:Zi,Flag:Ji,Examples:Yi,or:Qi},jl=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",Submit:Hi,Clear:Wi,Interpret:Zi,Flag:Ji,Examples:Yi,or:Qi,default:Nl});const Pt={"./lang/ar.json":Wa,"./lang/de.json":Ja,"./lang/en.json":Qa,"./lang/es.json":$a,"./lang/fa.json":tl,"./lang/fr.json":rl,"./lang/he.json":ol,"./lang/hi.json":ll,"./lang/ja.json":ul,"./lang/ko.json":cl,"./lang/lt.json":pl,"./lang/nl.json":ml,"./lang/pl.json":gl,"./lang/pt-BR.json":bl,"./lang/ru.json":El,"./lang/ta.json":Tl,"./lang/tr.json":Il,"./lang/uk.json":Pl,"./lang/ur.json":Ol,"./lang/uz.json":xl,"./lang/zh-cn.json":Rl,"./lang/zh-tw.json":jl};function Dl(){let e={};for(const t in Pt){const n=t.split("/").pop().split(".").shift();e[n]=Pt[t].default}return e}const Ct=Dl();for(const e in Ct)In(e,Ct[e]);function Ml(){xa({fallbackLocale:"en",initialLocale:La()})}function Ot(e,t,n){const r=e.slice();return r[8]=t[n].component,r[17]=t[n].id,r[2]=t[n].props,r[18]=t[n].children,r[9]=t[n].has_modes,r}function kt(e){let t=[],n=new Map,r,i,o=e[1];const s=a=>a[17];for(let a=0;a{r=null}),ae())},i(i){n||(x(r),n=!0)},o(i){D(r),n=!1},d(i){r&&r.d(i),i&&S(t)}}}function Gl(e){let t,n,r,i;const o=[{elem_id:"elem_id"in e[2]&&e[2].elem_id||`component-${e[4]}`},{elem_classes:"elem_classes"in e[2]&&e[2].elem_classes||[]},{target:e[6]},e[2],{theme:e[7]},{root:e[3]}];function s(l){e[15](l)}var a=e[8];function f(l){let u={$$slots:{default:[Fl]},$$scope:{ctx:l}};for(let _=0;_mt(t,"value",s)),t.$on("prop_change",e[10])),{c(){t&&V(t.$$.fragment),r=ne()},m(l,u){t&&z(t,l,u),I(l,r,u),i=!0},p(l,[u]){const _=u&220?fo(o,[u&20&&{elem_id:"elem_id"in l[2]&&l[2].elem_id||`component-${l[4]}`},u&4&&{elem_classes:"elem_classes"in l[2]&&l[2].elem_classes||[]},u&64&&{target:l[6]},u&4&&co(l[2]),u&128&&{theme:l[7]},u&8&&{root:l[3]}]):{};if(u&2097387&&(_.$$scope={dirty:u,ctx:l}),!n&&u&17&&(n=!0,_.value=l[0][l[4]].props.value,_o(()=>n=!1)),a!==(a=l[8])){if(t){oe();const c=t;D(c.$$.fragment,1,0,()=>{X(c,1)}),ae()}a?(t=new a(f(l)),l[14](t),we.push(()=>mt(t,"value",s)),t.$on("prop_change",l[10]),V(t.$$.fragment),x(t.$$.fragment,1),z(t,r.parentNode,r)):t=null}else a&&t.$set(_)},i(l){i||(t&&x(t.$$.fragment,l),i=!0)},o(l){t&&D(t.$$.fragment,l),i=!1},d(l){e[14](null),l&&S(r),t&&X(t,l)}}}function Ul(e,t,n){let{root:r}=t,{component:i}=t,{instance_map:o}=t,{id:s}=t,{props:a}=t,{children:f}=t,{dynamic_ids:l}=t,{has_modes:u}=t,{parent:_=null}=t,{target:c}=t,{theme:g}=t;const p=it();u&&(a.interactive===!1?a.mode="static":a.interactive===!0||l.has(s)?a.mode="dynamic":a.mode="static"),on(()=>(p("mount",s),()=>p("destroy",s))),po("BLOCK_KEY",_);function m(b){for(const A in b.detail)n(0,o[s].props[A]=b.detail[A],o)}function d(b){je.call(this,e,b)}function C(b){je.call(this,e,b)}function T(b){we[b?"unshift":"push"](()=>{o[s].instance=b,n(0,o)})}function y(b){e.$$.not_equal(o[s].props.value,b)&&(o[s].props.value=b,n(0,o))}return e.$$set=b=>{"root"in b&&n(3,r=b.root),"component"in b&&n(8,i=b.component),"instance_map"in b&&n(0,o=b.instance_map),"id"in b&&n(4,s=b.id),"props"in b&&n(2,a=b.props),"children"in b&&n(1,f=b.children),"dynamic_ids"in b&&n(5,l=b.dynamic_ids),"has_modes"in b&&n(9,u=b.has_modes),"parent"in b&&n(11,_=b.parent),"target"in b&&n(6,c=b.target),"theme"in b&&n(7,g=b.theme)},e.$$.update=()=>{e.$$.dirty&3&&n(1,f=f&&f.filter(b=>o[b.id].type!=="statustracker")),e.$$.dirty&19&&o[s].type==="form"&&(f?.every(b=>!b.props.visible)?n(2,a.visible=!1,a):n(2,a.visible=!0,a))},[o,f,a,r,s,l,c,g,i,u,m,_,d,C,T,y]}class Ki extends K{constructor(t){super(),$(this,t,Ul,Gl,ee,{root:3,component:8,instance_map:0,id:4,props:2,children:1,dynamic_ids:5,has_modes:9,parent:11,target:6,theme:7})}}function Vl(e){let t,n,r,i;return{c(){t=xe("svg"),n=xe("g"),r=xe("path"),i=xe("path"),E(r,"d","M3.789,0.09C3.903,-0.024 4.088,-0.024 4.202,0.09L4.817,0.705C4.931,0.819 4.931,1.004 4.817,1.118L1.118,4.817C1.004,4.931 0.819,4.931 0.705,4.817L0.09,4.202C-0.024,4.088 -0.024,3.903 0.09,3.789L3.789,0.09Z"),E(i,"d","M4.825,3.797C4.934,3.907 4.934,4.084 4.825,4.193L4.193,4.825C4.084,4.934 3.907,4.934 3.797,4.825L0.082,1.11C-0.027,1.001 -0.027,0.823 0.082,0.714L0.714,0.082C0.823,-0.027 1.001,-0.027 1.11,0.082L4.825,3.797Z"),E(t,"width","100%"),E(t,"height","100%"),E(t,"viewBox","0 0 5 5"),E(t,"version","1.1"),E(t,"xmlns","http://www.w3.org/2000/svg"),E(t,"xmlns:xlink","http://www.w3.org/1999/xlink"),E(t,"xml:space","preserve"),ie(t,"fill","currentColor"),ie(t,"fill-rule","evenodd"),ie(t,"clip-rule","evenodd"),ie(t,"stroke-linejoin","round"),ie(t,"stroke-miterlimit","2")},m(o,s){I(o,t,s),h(t,n),h(n,r),h(n,i)},p:re,i:re,o:re,d(o){o&&S(t)}}}class $i extends K{constructor(t){super(),$(this,t,null,Vl,ee,{})}}function zl(e){let t,n,r,i,o,s,a,f,l,u,_,c,g,p,m;return c=new $i({}),{c(){t=w("div"),n=w("h1"),n.textContent="API Docs",r=L(),i=w("p"),o=P(`No named API Routes found for
+ `),s=w("code"),a=P(e[0]),f=L(),l=w("p"),l.innerHTML=`To expose an API endpoint of your app in this page, set the api_name
+ parameter of the event listener.
+
+ For more information, visit the
+ API Page guide
+ . To hide the API documentation button and this page, set
+ show_api=False
+ in the
+ Blocks.launch()
+ method.`,u=L(),_=w("button"),V(c.$$.fragment),E(s,"class","svelte-1i3r921"),E(i,"class","attention svelte-1i3r921"),E(t,"class","wrap prose svelte-1i3r921"),E(_,"class","svelte-1i3r921")},m(d,C){I(d,t,C),h(t,n),h(t,r),h(t,i),h(i,o),h(i,s),h(s,a),h(t,f),h(t,l),I(d,u,C),I(d,_,C),z(c,_,null),g=!0,p||(m=_e(_,"click",e[2]),p=!0)},p(d,[C]){(!g||C&1)&&B(a,d[0])},i(d){g||(x(c.$$.fragment,d),g=!0)},o(d){D(c.$$.fragment,d),g=!1},d(d){d&&S(t),d&&S(u),d&&S(_),X(c),p=!1,m()}}}function Xl(e,t,n){const r=it();let{root:i}=t;const o=()=>r("close");return e.$$set=s=>{"root"in s&&n(0,i=s.root)},[i,r,o]}class Bl extends K{constructor(t){super(),$(this,t,Xl,zl,ee,{root:0})}}function ve(e,t,n=null){return t===void 0?n==="py"?"None":null:t==="string"?n===null?e:'"'+e+'"':t==="number"?n===null?parseFloat(e):e:t==="boolean"?n==="py"?e==="true"?"True":"False":n==="js"?e:e==="true":n===null?e===""?null:JSON.parse(e):typeof e=="string"?e===""?n==="py"?"None":"null":e:JSON.stringify(e)}var ql="https://gradio.s3-us-west-2.amazonaws.com/3.23.0/assets/api-logo.5346f193.svg";function Lt(e){let t,n,r;return{c(){t=w("div"),n=P(e[1]),r=P(" API endpoints:")},m(i,o){I(i,t,o),h(t,n),h(t,r)},p(i,o){o&2&&B(n,i[1])},d(i){i&&S(t)}}}function Hl(e){let t,n,r,i,o,s,a,f,l,u,_,c,g,p=e[1]>1&&Lt(e);return u=new $i({}),{c(){t=w("h2"),n=w("img"),i=P(`
+ API documentation for\xA0
+ `),o=w("span"),s=P(e[0]),a=L(),p&&p.c(),f=L(),l=w("button"),V(u.$$.fragment),Pe(n.src,r=ql)||E(n,"src",r),E(n,"alt",""),E(n,"class","svelte-155na5k"),E(o,"class","url svelte-155na5k"),E(t,"class","svelte-155na5k"),E(l,"class","svelte-155na5k")},m(m,d){I(m,t,d),h(t,n),h(t,i),h(t,o),h(o,s),I(m,a,d),p&&p.m(m,d),I(m,f,d),I(m,l,d),z(u,l,null),_=!0,c||(g=_e(l,"click",e[3]),c=!0)},p(m,[d]){(!_||d&1)&&B(s,m[0]),m[1]>1?p?p.p(m,d):(p=Lt(m),p.c(),p.m(f.parentNode,f)):p&&(p.d(1),p=null)},i(m){_||(x(u.$$.fragment,m),_=!0)},o(m){D(u.$$.fragment,m),_=!1},d(m){m&&S(t),m&&S(a),p&&p.d(m),m&&S(f),m&&S(l),X(u),c=!1,g()}}}function Wl(e,t,n){let{root:r}=t,{active_api_count:i}=t;const o=it(),s=()=>o("close");return e.$$set=a=>{"root"in a&&n(0,r=a.root),"active_api_count"in a&&n(1,i=a.active_api_count)},[r,i,o,s]}class Zl extends K{constructor(t){super(),$(this,t,Wl,Hl,ee,{root:0,active_api_count:1})}}function Jl(e){let t;return{c(){t=P("copy")},m(n,r){I(n,t,r)},d(n){n&&S(t)}}}function Yl(e){let t;return{c(){t=P("copied!")},m(n,r){I(n,t,r)},d(n){n&&S(t)}}}function Ql(e){let t;function n(o,s){return o[3]===o[2]?Yl:Jl}let r=n(e),i=r(e);return{c(){i.c(),t=ne()},m(o,s){i.m(o,s),I(o,t,s)},p(o,s){r!==(r=n(o))&&(i.d(1),i=r(o),i&&(i.c(),i.m(t.parentNode,t)))},d(o){i.d(o),o&&S(t)}}}function Kl(e){let t,n,r,i,o,s,a,f,l,u,_,c,g;return c=new ot({props:{size:"sm",variant:"secondary",$$slots:{default:[Ql]},$$scope:{ctx:e}}}),c.$on("click",e[4]),{c(){t=w("h3"),n=w("span"),n.textContent="POST",r=P(`
+ /run/`),i=P(e[0]),o=L(),s=w("div"),a=w("div"),f=P(e[1]),l=P("run/"),u=P(e[0]),_=L(),V(c.$$.fragment),E(n,"class","post svelte-vs3f38"),E(t,"class","svelte-vs3f38"),E(a,"class","url svelte-vs3f38"),E(s,"class","endpoint prose svelte-vs3f38")},m(p,m){I(p,t,m),h(t,n),h(t,r),h(t,i),I(p,o,m),I(p,s,m),h(s,a),h(a,f),h(a,l),h(a,u),h(a,_),z(c,a,null),g=!0},p(p,[m]){(!g||m&1)&&B(i,p[0]),(!g||m&2)&&B(f,p[1]),(!g||m&1)&&B(u,p[0]);const d={};m&44&&(d.$$scope={dirty:m,ctx:p}),c.$set(d)},i(p){g||(x(c.$$.fragment,p),g=!0)},o(p){D(c.$$.fragment,p),g=!1},d(p){p&&S(t),p&&S(o),p&&S(s),X(c)}}}function $l(e,t,n){let{api_name:r}=t,{root:i}=t,{dependency_index:o}=t,s=-1;function a(){navigator.clipboard.writeText(i+"run/"+r),n(3,s=o),setTimeout(()=>{n(3,s=-1)},1500)}return e.$$set=f=>{"api_name"in f&&n(0,r=f.api_name),"root"in f&&n(1,i=f.root),"dependency_index"in f&&n(2,o=f.dependency_index)},[r,i,o,s,a]}class es extends K{constructor(t){super(),$(this,t,$l,Kl,ee,{api_name:0,root:1,dependency_index:2})}}function Rt(e,t,n){const r=e.slice();return r[7]=t[n],r[8]=t,r[9]=n,r}function Nt(e){let t;return{c(){t=w("span"),t.textContent="ERROR",E(t,"class","error svelte-j5il63")},m(n,r){I(n,t,r)},d(n){n&&S(t)}}}function jt(e){let t,n,r,i,o,s,a=(e[4][e[7]].documentation?.type?.input_payload||e[4][e[7]].documentation?.type?.payload)+"",f,l,u,_,c,g=(e[4][e[7]].documentation?.description?.input_payload||e[4][e[7]].documentation?.description?.payload)+"",p,m,d=Dt(e[4][e[7]].props.label)+"",C,T,y,b=e[4][e[7]].props.name+"",A,O,J,ke;function q(){e[6].call(n,e[9])}let W=e[2][e[3]][e[9]]&&Nt();return{c(){t=w("div"),n=w("input"),r=L(),W&&W.c(),i=L(),o=w("span"),s=P(": "),f=P(a),l=P(","),u=L(),_=w("span"),c=P("// represents "),p=P(g),m=P(` of
+ `),C=P(d),T=L(),y=w("span"),A=P(b),O=P(`
+ component`),E(n,"class"," svelte-j5il63"),E(n,"type","text"),E(o,"class","type svelte-j5il63"),E(y,"class","name svelte-j5il63"),E(_,"class","desc svelte-j5il63"),E(t,"class","second-level svelte-j5il63")},m(le,te){I(le,t,te),h(t,n),De(n,e[0][e[3]][e[9]]),h(t,r),W&&W.m(t,null),h(t,i),h(t,o),h(o,s),h(o,f),h(o,l),h(t,u),h(t,_),h(_,c),h(_,p),h(_,m),h(_,C),h(_,T),h(_,y),h(y,A),h(_,O),J||(ke=_e(n,"input",q),J=!0)},p(le,te){e=le,te&9&&n.value!==e[0][e[3]][e[9]]&&De(n,e[0][e[3]][e[9]]),e[2][e[3]][e[9]]?W||(W=Nt(),W.c(),W.m(t,i)):W&&(W.d(1),W=null),te&18&&a!==(a=(e[4][e[7]].documentation?.type?.input_payload||e[4][e[7]].documentation?.type?.payload)+"")&&B(f,a),te&18&&g!==(g=(e[4][e[7]].documentation?.description?.input_payload||e[4][e[7]].documentation?.description?.payload)+"")&&B(p,g),te&18&&d!==(d=Dt(e[4][e[7]].props.label)+"")&&B(C,d),te&18&&b!==(b=e[4][e[7]].props.name+"")&&B(A,b)},d(le){le&&S(t),W&&W.d(),J=!1,ke()}}}function ts(e){let t,n,r,i,o,s,a,f=e[1].inputs,l=[];for(let u=0;u
+ Input Payload`,n=L(),V(r.$$.fragment),i=L(),o=w("span"),s=L(),V(a.$$.fragment),E(t,"class","svelte-j5il63"),E(o,"class","space svelte-j5il63")},m(l,u){I(l,t,u),I(l,n,u),z(r,l,u),I(l,i,u),I(l,o,u),I(l,s,u),z(a,l,u),f=!0},p(l,[u]){e=l;const _={};u&1055&&(_.$$scope={dirty:u,ctx:e}),r.$set(_);const c={};u&1024&&(c.$$scope={dirty:u,ctx:e}),a.$set(c)},i(l){f||(x(r.$$.fragment,l),x(a.$$.fragment,l),f=!0)},o(l){D(r.$$.fragment,l),D(a.$$.fragment,l),f=!1},d(l){l&&S(t),l&&S(n),X(r,l),l&&S(i),l&&S(o),l&&S(s),X(a,l)}}}function Dt(e){return e?"'"+e+"'":"the"}function is(e,t,n){let{dependency:r}=t,{dependency_failures:i}=t,{dependency_index:o}=t,{instance_map:s}=t,{run:a}=t,{dependency_inputs:f}=t;function l(u){f[o][u]=this.value,n(0,f)}return e.$$set=u=>{"dependency"in u&&n(1,r=u.dependency),"dependency_failures"in u&&n(2,i=u.dependency_failures),"dependency_index"in u&&n(3,o=u.dependency_index),"instance_map"in u&&n(4,s=u.instance_map),"run"in u&&n(5,a=u.run),"dependency_inputs"in u&&n(0,f=u.dependency_inputs)},[f,r,i,o,s,a,l]}class os extends K{constructor(t){super(),$(this,t,is,rs,ee,{dependency:1,dependency_failures:2,dependency_index:3,instance_map:4,run:5,dependency_inputs:0})}}function Mt(e,t,n){const r=e.slice();return r[8]=t[n],r[9]=t,r[10]=n,r}function Ft(e){let t,n,r,i;function o(){e[7].call(t,e[10])}return{c(){t=w("input"),n=P(`
+ :`),t.disabled=!0,E(t,"type","text"),E(t,"class","svelte-fxtbel")},m(s,a){I(s,t,a),De(t,e[0][e[2]][e[10]]),I(s,n,a),r||(i=_e(t,"input",o),r=!0)},p(s,a){e=s,a&5&&t.value!==e[0][e[2]][e[10]]&&De(t,e[0][e[2]][e[10]])},d(s){s&&S(t),s&&S(n),r=!1,i()}}}function Gt(e){let t,n,r,i=(e[3][e[8]].documentation?.type?.response_object||e[3][e[8]].documentation?.type?.payload)+"",o,s,a,f,l,u=e[5](e[3][e[8]].documentation?.description?.response_object||e[3][e[8]].documentation?.description?.payload,e[0][e[2]][e[10]])+"",_,c,g=Vt(e[3][e[8]].props.label)+"",p,m,d,C=e[3][e[8]].props.name+"",T,y,b=e[0][e[2]][e[10]]!==void 0&&Ft(e);return{c(){t=w("div"),b&&b.c(),n=L(),r=w("span"),o=P(i),s=P(","),a=L(),f=w("span"),l=P("// represents "),_=P(u),c=P(` of
+ `),p=P(g),m=L(),d=w("span"),T=P(C),y=P(`
+ component`),E(r,"class","type svelte-fxtbel"),E(d,"class","name capitalize svelte-fxtbel"),E(f,"class","desc svelte-fxtbel"),E(t,"class","second-level svelte-fxtbel")},m(A,O){I(A,t,O),b&&b.m(t,null),h(t,n),h(t,r),h(r,o),h(r,s),h(t,a),h(t,f),h(f,l),h(f,_),h(f,c),h(f,p),h(f,m),h(f,d),h(d,T),h(f,y)},p(A,O){A[0][A[2]][A[10]]!==void 0?b?b.p(A,O):(b=Ft(A),b.c(),b.m(t,n)):b&&(b.d(1),b=null),O&10&&i!==(i=(A[3][A[8]].documentation?.type?.response_object||A[3][A[8]].documentation?.type?.payload)+"")&&B(o,i),O&15&&u!==(u=A[5](A[3][A[8]].documentation?.description?.response_object||A[3][A[8]].documentation?.description?.payload,A[0][A[2]][A[10]])+"")&&B(_,u),O&10&&g!==(g=Vt(A[3][A[8]].props.label)+"")&&B(p,g),O&10&&C!==(C=A[3][A[8]].props.name+"")&&B(T,C)},d(A){A&&S(t),b&&b.d()}}}function Ut(e){let t,n,r;return n=new bo({props:{margin:!1}}),{c(){t=w("div"),V(n.$$.fragment),E(t,"class","load-wrap svelte-fxtbel")},m(i,o){I(i,t,o),z(n,t,null),r=!0},i(i){r||(x(n.$$.fragment,i),r=!0)},o(i){D(n.$$.fragment,i),r=!1},d(i){i&&S(t),X(n)}}}function as(e){let t,n,r,i,o,s,a,f,l,u,_,c,g=e[1].outputs,p=[];for(let d=0;d// number of seconds to run function call`,u=P(`
+ }`),_=L(),m&&m.c(),E(i,"class","first-level svelte-fxtbel"),E(a,"class","first-level svelte-fxtbel"),E(l,"class","first-level svelte-fxtbel"),E(n,"class","svelte-fxtbel"),ht(n,"hide",e[4]),E(t,"class","response-wrap svelte-fxtbel")},m(d,C){I(d,t,C),h(t,n),h(n,r),h(n,i),h(n,o);for(let T=0;T{m=null}),ae())},i(d){c||(x(m),c=!0)},o(d){D(m),c=!1},d(d){d&&S(t),ye(p,d),m&&m.d()}}}function ls(e){let t,n,r,i;return r=new at({props:{$$slots:{default:[as]},$$scope:{ctx:e}}}),{c(){t=w("h4"),t.innerHTML=`
+ Response Object`,n=L(),V(r.$$.fragment),E(t,"class","svelte-fxtbel")},m(o,s){I(o,t,s),I(o,n,s),z(r,o,s),i=!0},p(o,[s]){const a={};s&2079&&(a.$$scope={dirty:s,ctx:o}),r.$set(a)},i(o){i||(x(r.$$.fragment,o),i=!0)},o(o){D(r.$$.fragment,o),i=!1},d(o){o&&S(t),o&&S(n),X(r,o)}}}const Vt=e=>e?"'"+e+"'":"the";function ss(e,t,n){let{dependency:r}=t,{dependency_index:i}=t,{instance_map:o}=t,{dependency_outputs:s}=t,{is_running:a}=t,{root:f}=t;const l=(_,c)=>_?.replace("{ROOT}",f)?.replace("{name}",c?JSON.parse(`${c}`)?.name:"{name}");function u(_){s[i][_]=this.value,n(0,s)}return e.$$set=_=>{"dependency"in _&&n(1,r=_.dependency),"dependency_index"in _&&n(2,i=_.dependency_index),"instance_map"in _&&n(3,o=_.instance_map),"dependency_outputs"in _&&n(0,s=_.dependency_outputs),"is_running"in _&&n(4,a=_.is_running),"root"in _&&n(6,f=_.root)},[s,r,i,o,a,l,f,u]}class us extends K{constructor(t){super(),$(this,t,ss,ls,ee,{dependency:1,dependency_index:2,instance_map:3,dependency_outputs:0,is_running:4,root:6})}}function fs(e){let t;return{c(){t=P(e[0])},m(n,r){I(n,t,r)},p(n,r){r&1&&B(t,n[0])},d(n){n&&S(t)}}}function cs(e){let t,n;return t=new ot({props:{size:"sm",$$slots:{default:[fs]},$$scope:{ctx:e}}}),t.$on("click",e[1]),{c(){V(t.$$.fragment)},m(r,i){z(t,r,i),n=!0},p(r,[i]){const o={};i&9&&(o.$$scope={dirty:i,ctx:r}),t.$set(o)},i(r){n||(x(t.$$.fragment,r),n=!0)},o(r){D(t.$$.fragment,r),n=!1},d(r){X(t,r)}}}function _s(e,t,n){let{code:r}=t,i="copy";function o(){navigator.clipboard.writeText(r),n(0,i="copied!"),setTimeout(()=>{n(0,i="copy")},1500)}return e.$$set=s=>{"code"in s&&n(2,r=s.code)},[i,o,r]}class eo extends K{constructor(t){super(),$(this,t,_s,cs,ee,{code:2})}}var ps="https://gradio.s3-us-west-2.amazonaws.com/3.23.0/assets/python.20e39c92.svg",ds="https://gradio.s3-us-west-2.amazonaws.com/3.23.0/assets/javascript.850cf94b.svg";function zt(e,t,n){const r=e.slice();return r[13]=t[n],r[15]=n,r}function Xt(e,t,n){const r=e.slice();return r[13]=t[n],r[15]=n,r}function Bt(e,t,n){const r=e.slice();return r[17]=t[n][0],r[18]=t[n][1],r}function qt(e){let t,n,r,i,o=e[17]+"",s,a,f,l,u;function _(){return e[10](e[17])}return{c(){t=w("li"),n=w("img"),i=L(),s=P(o),a=L(),Pe(n.src,r=e[18])||E(n,"src",r),E(n,"alt",""),E(n,"class","svelte-dks0o4"),E(t,"class",f="snippet "+(e[0]===e[17]?"current-lang":"inactive-lang")+" svelte-dks0o4")},m(c,g){I(c,t,g),h(t,n),h(t,i),h(t,s),h(t,a),l||(u=_e(t,"click",_),l=!0)},p(c,g){e=c,g&1&&f!==(f="snippet "+(e[0]===e[17]?"current-lang":"inactive-lang")+" svelte-dks0o4")&&E(t,"class",f)},d(c){c&&S(t),l=!1,u()}}}function ms(e){let t;return{c(){t=w("pre"),t.textContent="Hello World",E(t,"class","client svelte-dks0o4")},m(n,r){I(n,t,r)},p:re,i:re,o:re,d(n){n&&S(t)}}}function hs(e){let t,n,r,i,o,s,a,f,l=e[5]+"run/"+e[1].api_name,u,_,c,g,p,m,d;n=new eo({props:{code:e[8]?.innerText}});let C=e[6][e[3]],T=[];for(let y=0;y{s[u]=null}),ae()),~n?(r=s[n],r?r.p(f,l):(r=s[n]=o[n](f),r.c()),x(r,1),r.m(t,null)):r=null)},i(f){i||(x(r),i=!0)},o(f){D(r),i=!1},d(f){f&&S(t),~n&&s[n].d()}}}function bs(e){let t,n,r,i,o,s,a=e[9],f=[];for(let l=0;l
+ Code snippets`,n=L(),r=w("div");for(let l=0;ln(0,l=d);function p(d){we[d?"unshift":"push"](()=>{_=d,n(7,_)})}function m(d){we[d?"unshift":"push"](()=>{c=d,n(8,c)})}return e.$$set=d=>{"dependency"in d&&n(1,r=d.dependency),"dependencies"in d&&n(2,i=d.dependencies),"dependency_index"in d&&n(3,o=d.dependency_index),"instance_map"in d&&n(4,s=d.instance_map),"root"in d&&n(5,a=d.root),"dependency_inputs"in d&&n(6,f=d.dependency_inputs),"current_language"in d&&n(0,l=d.current_language)},[l,r,i,o,s,a,f,_,c,u,g,p,m]}class Es extends K{constructor(t){super(),$(this,t,ys,bs,ee,{dependency:1,dependencies:2,dependency_index:3,instance_map:4,root:5,dependency_inputs:6,current_language:0})}}function Zt(e,t,n){const r=e.slice();return r[11]=t[n],r[13]=n,r}function Ss(e){let t,n;return t=new Bl({props:{root:e[0]}}),t.$on("close",e[10]),{c(){V(t.$$.fragment)},m(r,i){z(t,r,i),n=!0},p(r,i){const o={};i&1&&(o.root=r[0]),t.$set(o)},i(r){n||(x(t.$$.fragment,r),n=!0)},o(r){D(t.$$.fragment,r),n=!1},d(r){X(t,r)}}}function Ts(e){let t,n,r,i,o;n=new Zl({props:{root:e[0],active_api_count:e[7]}}),n.$on("close",e[9]);let s=e[2],a=[];for(let l=0;lD(a[l],1,1,()=>{a[l]=null});return{c(){t=w("div"),V(n.$$.fragment),r=L(),i=w("div");for(let l=0;l{r=null}),ae())},i(i){n||(x(r),n=!0)},o(i){D(r),n=!1},d(i){r&&r.d(i),i&&S(t)}}}function ws(e){let t,n,r,i;const o=[Ts,Ss],s=[];function a(f,l){return f[7]?0:1}return t=a(e),n=s[t]=o[t](e),{c(){n.c(),r=ne()},m(f,l){s[t].m(f,l),I(f,r,l),i=!0},p(f,[l]){n.p(f,l)},i(f){i||(x(n),i=!0)},o(f){D(n),i=!1},d(f){s[t].d(f),f&&S(r)}}}let Is="python";function As(e,t,n){let{instance_map:r}=t,{dependencies:i}=t,{root:o}=t;o===""&&(o=location.protocol+"//"+location.host+location.pathname),o.endsWith("/")||(o+="/");let s=!1,a=i.map(p=>p.inputs.map(m=>{let d=r[m].documentation?.example_data;return d===void 0?d="":typeof d=="object"&&(d=JSON.stringify(d)),d})),f=i.map(p=>new Array(p.outputs.length)),l=i.map(p=>new Array(p.inputs.length).fill(!1)),u=i.filter(p=>p.api_name).length;const _=async p=>{n(3,s=!0);let m=i[p],d=0;try{var C=a[p].map((b,A)=>{d=A;let O=r[m.inputs[A]];return b=ve(b,O.documentation?.type?.input_payload||O.documentation?.type?.payload),n(5,l[p][d]=!1,l),b})}catch{n(5,l[p][d]=!0,l),n(3,s=!1);return}let[T,y]=await yo(`${o}/run/${m.api_name}`,{data:C});n(3,s=!1),y==200?n(4,f[p]=T.data.map((b,A)=>{let O=r[m.outputs[A]];return ve(b,O.documentation?.type?.response_object||O.documentation?.type?.payload,"js")}),f):n(5,l[p]=new Array(l[p].length).fill(!0),l)};on(()=>(document.body.style.overflow="hidden",()=>{document.body.style.overflow="auto"}));function c(p){je.call(this,e,p)}function g(p){je.call(this,e,p)}return e.$$set=p=>{"instance_map"in p&&n(1,r=p.instance_map),"dependencies"in p&&n(2,i=p.dependencies),"root"in p&&n(0,o=p.root)},[o,r,i,s,f,l,a,u,_,c,g]}class Ps extends K{constructor(t){super(),$(this,t,As,ws,ee,{instance_map:1,dependencies:2,root:0})}}var Cs="https://gradio.s3-us-west-2.amazonaws.com/3.23.0/assets/logo.0a070fcf.svg",Os="https://gradio.s3-us-west-2.amazonaws.com/3.23.0/static/img/api-logo.svg";function Qt(e){return document.title=e[3],{c:re,m:re,d:re}}function Kt(e){let t,n;return{c(){t=w("script"),t.async=!0,t.defer=!0,Pe(t.src,n="https://www.googletagmanager.com/gtag/js?id=UA-156449732-1")||E(t,"src",n)},m(r,i){I(r,t,i)},d(r){r&&S(t)}}}function $t(e){let t,n;return t=new Ki({props:{has_modes:e[11].has_modes,component:e[11].component,id:e[11].id,props:e[11].props,children:e[11].children,dynamic_ids:e[16],instance_map:e[13],root:e[1],target:e[5],theme:e[10]}}),t.$on("mount",e[17]),t.$on("destroy",e[24]),{c(){V(t.$$.fragment)},m(r,i){z(t,r,i),n=!0},p(r,i){const o={};i[0]&2048&&(o.has_modes=r[11].has_modes),i[0]&2048&&(o.component=r[11].component),i[0]&2048&&(o.id=r[11].id),i[0]&2048&&(o.props=r[11].props),i[0]&2048&&(o.children=r[11].children),i[0]&8192&&(o.instance_map=r[13]),i[0]&2&&(o.root=r[1]),i[0]&32&&(o.target=r[5]),i[0]&1024&&(o.theme=r[10]),t.$set(o)},i(r){n||(x(t.$$.fragment,r),n=!0)},o(r){D(t.$$.fragment,r),n=!1},d(r){X(t,r)}}}function en(e){let t,n,r,i,o,s,a=e[6]&&tn(e);return{c(){t=w("footer"),a&&a.c(),n=L(),r=w("a"),i=P(`Built with Gradio
+ `),o=w("img"),Pe(o.src,s=Cs)||E(o,"src",s),E(o,"alt","logo"),E(o,"class","svelte-1lyswbr"),E(r,"href","https://gradio.app"),E(r,"class","built-with svelte-1lyswbr"),E(r,"target","_blank"),E(r,"rel","noreferrer"),E(t,"class","svelte-1lyswbr")},m(f,l){I(f,t,l),a&&a.m(t,null),h(t,n),h(t,r),h(r,i),h(r,o)},p(f,l){f[6]?a?a.p(f,l):(a=tn(f),a.c(),a.m(t,n)):a&&(a.d(1),a=null)},d(f){f&&S(t),a&&a.d()}}}function tn(e){let t,n,r,i,o,s,a,f;return{c(){t=w("button"),n=P("Use via API "),r=w("img"),o=L(),s=w("div"),s.textContent="\xB7",Pe(r.src,i=Os)||E(r,"src",i),E(r,"alt",""),E(r,"class","svelte-1lyswbr"),E(t,"class","show-api svelte-1lyswbr"),E(s,"class","svelte-1lyswbr")},m(l,u){I(l,t,u),h(t,n),h(t,r),I(l,o,u),I(l,s,u),a||(f=_e(t,"click",e[25]),a=!0)},p:re,d(l){l&&S(t),l&&S(o),l&&S(s),a=!1,f()}}}function nn(e){let t,n,r,i,o,s,a,f;return o=new Ps({props:{instance_map:e[13],dependencies:e[2],root:e[1]}}),o.$on("close",e[27]),{c(){t=w("div"),n=w("div"),r=L(),i=w("div"),V(o.$$.fragment),E(n,"class","backdrop svelte-1lyswbr"),E(i,"class","api-docs-wrap svelte-1lyswbr"),E(t,"class","api-docs svelte-1lyswbr")},m(l,u){I(l,t,u),h(t,n),h(t,r),h(t,i),z(o,i,null),s=!0,a||(f=_e(n,"click",e[26]),a=!0)},p(l,u){const _={};u[0]&8192&&(_.instance_map=l[13]),u[0]&4&&(_.dependencies=l[2]),u[0]&2&&(_.root=l[1]),o.$set(_)},i(l){s||(x(o.$$.fragment,l),s=!0)},o(l){D(o.$$.fragment,l),s=!1},d(l){l&&S(t),X(o),a=!1,f()}}}function ks(e){let t,n,r,i,o,s,a,f,l,u=e[8]&&Qt(e),_=e[4]&&Kt(),c=e[0]&&$t(e),g=e[7]&&en(e),p=e[12]&&e[0]&&nn(e);return{c(){u&&u.c(),t=ne(),_&&_.c(),n=ne(),r=L(),i=w("div"),o=w("div"),c&&c.c(),s=L(),g&&g.c(),a=L(),p&&p.c(),f=ne(),E(o,"class","contain"),ie(o,"flex-grow",e[9]?"1":"auto",!1),E(i,"class","wrap svelte-1lyswbr"),ie(i,"min-height",e[9]?"100%":"auto",!1)},m(m,d){u&&u.m(document.head,null),h(document.head,t),_&&_.m(document.head,null),h(document.head,n),I(m,r,d),I(m,i,d),h(i,o),c&&c.m(o,null),h(i,s),g&&g.m(i,null),I(m,a,d),p&&p.m(m,d),I(m,f,d),l=!0},p(m,d){m[8]?u||(u=Qt(m),u.c(),u.m(t.parentNode,t)):u&&(u.d(1),u=null),m[4]?_||(_=Kt(),_.c(),_.m(n.parentNode,n)):_&&(_.d(1),_=null),m[0]?c?(c.p(m,d),d[0]&1&&x(c,1)):(c=$t(m),c.c(),x(c,1),c.m(o,null)):c&&(oe(),D(c,1,1,()=>{c=null}),ae()),d[0]&512&&ie(o,"flex-grow",m[9]?"1":"auto",!1),m[7]?g?g.p(m,d):(g=en(m),g.c(),g.m(i,null)):g&&(g.d(1),g=null),d[0]&512&&ie(i,"min-height",m[9]?"100%":"auto",!1),m[12]&&m[0]?p?(p.p(m,d),d[0]&4097&&x(p,1)):(p=nn(m),p.c(),x(p,1),p.m(f.parentNode,f)):p&&(oe(),D(p,1,1,()=>{p=null}),ae())},i(m){l||(x(c),x(p),l=!0)},o(m){D(c),D(p),l=!1},d(m){u&&u.d(m),S(t),_&&_.d(m),S(n),m&&S(r),m&&S(i),c&&c.d(),g&&g.d(),m&&S(a),p&&p.d(m),m&&S(f)}}}function rn(e,t,n){let r=0;for(;;){const i=n[r];if(i===void 0)break;let o=0;for(;;){const s=i[t][o];if(s===void 0)break;if(s===e)return!0;o++}r++}return!1}function xs(e){return Array.isArray(e)&&e.length===0||e===""||e===0||!e}function Ls(e,t,n){let r;Ml();let{root:i}=t,{components:o}=t,{layout:s}=t,{dependencies:a}=t,{title:f="Gradio"}=t,{analytics_enabled:l=!1}=t,{target:u}=t,{autoscroll:_}=t,{show_api:c=!0}=t,{show_footer:g=!0}=t,{control_page_title:p=!1}=t,{app_mode:m}=t,{theme:d}=t,{app:C}=t,T=Eo();So(e,T,v=>n(23,r=v));let y={id:s.id,type:"column",props:{},has_modes:!1,instance:{},component:{}};o.push(y);const b=Object.getPrototypeOf(async function(){}).constructor;a.forEach(v=>{if(v.js){const k=v.backend_fn?v.inputs.length===1:v.outputs.length===1;try{v.frontend_fn=new b("__fn_args",`let result = await (${v.js})(...__fn_args);
+ return ${k} ? [result] : result;`)}catch(R){console.error("Could not parse custom js method."),console.error(R)}}});let O=new URLSearchParams(window.location.search).get("view")==="api";const J=v=>{n(12,O=v);let k=new URLSearchParams(window.location.search);v?k.set("view","api"):k.delete("view"),history.replaceState(null,"","?"+k.toString())},ke=o.reduce((v,{id:k,props:R})=>{const N=rn(k,"inputs",a),H=rn(k,"outputs",a);return!N&&!H&&xs(R?.value)&&v.add(k),N&&v.add(k),v},new Set);let q=o.reduce((v,k)=>(v[k.id]=k,v),{});function W(v){return new Promise(async(k,R)=>{try{const N=await qa[v]();k({name:v,component:N})}catch(N){console.error("failed to load: "+v),console.error(N),R(N)}})}const le=new Set,te=new Map;async function ft(v){let k=q[v.id];const R=(await te.get(k.type)).component;k.component=R.Component,R.document&&(k.documentation=R.document(k.props)),R.modes&&R.modes.length>1&&(k.has_modes=!0),v.children&&(k.children=v.children.map(N=>q[N.id]),await Promise.all(v.children.map(N=>ft(N))))}o.forEach(async v=>{const k=W(v.type);le.add(k),te.set(v.type,k)});let{ready:Ve=!1}=t;Promise.all(Array.from(le)).then(()=>{ft(s).then(async()=>{n(0,Ve=!0)}).catch(v=>{console.error(v)})});function ct(v,k){const R=a[k].outputs;v.forEach((N,H)=>{if(typeof N=="object"&&N!==null&&N.__type__==="update"){for(const[ue,Y]of Object.entries(N))ue!=="__type__"&&n(13,q[R[H]].props[ue]=Y,q);n(11,y)}else n(13,q[R[H]].props.value=N,q)})}C.on("data",({data:v,fn_index:k})=>{ct(v,k);let R=T.get_status_for_fn(k);(R==="complete"||R==="error")&&a.forEach((N,H)=>{N.trigger_after===k&&(!N.trigger_only_on_success||R==="complete")&&ze(H,null)})}),C.on("status",({fn_index:v,...k})=>{T.update({...k,fn_index:v})});function _t(v,k,R){v?.props||(v.props={}),v.props[k]=R,n(11,y)}let se=[];const ze=(v,k)=>{let R=a[v];const N=T.get_status_for_fn(v);if(N==="pending"||N==="generating")return;R.cancels&&R.cancels.forEach(Y=>{C.cancel("/predict",Y)});let H={fn_index:v,data:R.inputs.map(Y=>q[Y].props.value),event_data:R.collects_event_data?k:null};R.frontend_fn?R.frontend_fn(H.data.concat(R.outputs.map(Y=>q[Y].props.value))).then(Y=>{R.backend_fn?(H.data=Y,ue()):ct(Y,v)}):R.backend_fn&&ue();function ue(){C.predict("/predict",H)}};async function to(){await wo();for(var v=u.getElementsByTagName("a"),k=0;k{let{targets:H,trigger:ue,inputs:Y,outputs:lo}=R;const so=H.map(Q=>[Q,q[Q]]);H.length===0&&!se[N]?.includes(-1)&&ue==="load"&&lo.every(Q=>q?.[Q].instance)&&Y.every(Q=>q?.[Q].instance)&&(ze(N,null),se[N]=[-1]),so.filter(Q=>!!Q&&!!Q[1]).forEach(([Q,{instance:dt}])=>{se[N]?.includes(Q)||!dt||(dt?.$on(ue,uo=>{ze(N,uo.detail)}),se[N]||(se[N]=[]),se[N].push(Q))})})}function pt(v){se=se.map(k=>k.filter(R=>R!==v))}a.forEach((v,k)=>{T.register(k,v.inputs,v.outputs)});function no(v){for(const R in v){let N=v[R],H=a[N.fn_index];N.scroll_to_output=H.scroll_to_output,N.visible=H.show_progress,_t(q[R],"loading_status",N)}const k=T.get_inputs_to_update();for(const[R,N]of k)_t(q[R],"pending",N==="pending")}const ro=({detail:v})=>pt(v),io=()=>{J(!O)},oo=()=>{J(!1)},ao=()=>{J(!1)};return e.$$set=v=>{"root"in v&&n(1,i=v.root),"components"in v&&n(19,o=v.components),"layout"in v&&n(20,s=v.layout),"dependencies"in v&&n(2,a=v.dependencies),"title"in v&&n(3,f=v.title),"analytics_enabled"in v&&n(4,l=v.analytics_enabled),"target"in v&&n(5,u=v.target),"autoscroll"in v&&n(21,_=v.autoscroll),"show_api"in v&&n(6,c=v.show_api),"show_footer"in v&&n(7,g=v.show_footer),"control_page_title"in v&&n(8,p=v.control_page_title),"app_mode"in v&&n(9,m=v.app_mode),"theme"in v&&n(10,d=v.theme),"app"in v&&n(22,C=v.app),"ready"in v&&n(0,Ve=v.ready)},e.$$.update=()=>{e.$$.dirty[0]&2097152&&To.update(v=>({...v,autoscroll:_})),e.$$.dirty[0]&8388608&&no(r)},[Ve,i,a,f,l,u,c,g,p,m,d,y,O,q,T,J,ke,to,pt,o,s,_,C,r,ro,io,oo,ao]}class Rs extends K{constructor(t){super(),$(this,t,Ls,ks,ee,{root:1,components:19,layout:20,dependencies:2,title:3,analytics_enabled:4,target:5,autoscroll:21,show_api:6,show_footer:7,control_page_title:8,app_mode:9,theme:10,app:22,ready:0},null,[-1,-1])}}var Ms=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:Rs});export{Ms as B,Ds as X};
diff --git a/gradio/templates/cdn/assets/Blocks.1c8a32b7.js.map b/gradio/templates/cdn/assets/Blocks.1c8a32b7.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..88a1eb9d138faed88526f40eea6a426c7d280f16
--- /dev/null
+++ b/gradio/templates/cdn/assets/Blocks.1c8a32b7.js.map
@@ -0,0 +1 @@
+{"version":3,"mappings":"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AAU,GAAK,OACrB,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACL,GAAK,OAAU,GAAK,OACpB,GAAK,OAAU,GAAK,OACrB,IAAM,OACN,IAAM,OACL,GAAK,OAAU,GAAK,OACrB,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACL,GAAK,OAAU,GAAK,OACpB,GAAK,OAAU,GAAK,OACpB,GAAK,OAAU,GAAK,OACrB,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACL,GAAK,OAAU,GAAK,OACrB,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACL,GAAK,OAAU,GAAK,OACrB,IAAM,OACN,IAAM,OACL,GAAK,OAAU,GAAK,OACpB,GAAK,OAAU,GAAK,OACpB,GAAK,OAAU,GAAK,OACpB,GAAK,OAAU,GAAK,OACpB,GAAK,OAAU,GAAK,OACpB,GAAK,OAAU,GAAK,OACpB,GAAK,OAAU,GAAK,OACpB,GAAK,OAAU,GAAK,OACrB,IAAM,OACL,GAAK,OAAU,GAAK,OACpB,GAAK,OAAU,GAAK,OACrB,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACL,GAAK,OAAU,GAAK,OACrB,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACL,GAAK,OAAU,GAAK,OACrB,IAAM,OACL,GAAK,OAAU,GAAK,OACrB,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAAM,OACL,GAAK,OAAU,GAAK,OACrB,IAAM,OACN,IAAM,OACN,IAAM,OACN,IAA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","names":["e","t","n","getLocaleFromNavigator","api_logo"],"sources":["../../../../ui/node_modules/.pnpm/deepmerge@4.2.2/node_modules/deepmerge/dist/cjs.js","../../../../ui/node_modules/.pnpm/tslib@2.3.1/node_modules/tslib/tslib.es6.js","../../../../ui/node_modules/.pnpm/@formatjs+icu-messageformat-parser@2.0.18/node_modules/@formatjs/icu-messageformat-parser/lib/error.js","../../../../ui/node_modules/.pnpm/@formatjs+icu-messageformat-parser@2.0.18/node_modules/@formatjs/icu-messageformat-parser/lib/types.js","../../../../ui/node_modules/.pnpm/@formatjs+icu-messageformat-parser@2.0.18/node_modules/@formatjs/icu-messageformat-parser/lib/regex.generated.js","../../../../ui/node_modules/.pnpm/@formatjs+icu-skeleton-parser@1.3.5/node_modules/@formatjs/icu-skeleton-parser/lib/date-time.js","../../../../ui/node_modules/.pnpm/@formatjs+icu-skeleton-parser@1.3.5/node_modules/@formatjs/icu-skeleton-parser/lib/regex.generated.js","../../../../ui/node_modules/.pnpm/@formatjs+icu-skeleton-parser@1.3.5/node_modules/@formatjs/icu-skeleton-parser/lib/number.js","../../../../ui/node_modules/.pnpm/@formatjs+icu-messageformat-parser@2.0.18/node_modules/@formatjs/icu-messageformat-parser/lib/parser.js","../../../../ui/node_modules/.pnpm/@formatjs+icu-messageformat-parser@2.0.18/node_modules/@formatjs/icu-messageformat-parser/lib/index.js","../../../../ui/node_modules/.pnpm/@formatjs+fast-memoize@1.2.1/node_modules/@formatjs/fast-memoize/lib/index.js","../../../../ui/node_modules/.pnpm/intl-messageformat@9.11.4/node_modules/intl-messageformat/lib/src/error.js","../../../../ui/node_modules/.pnpm/intl-messageformat@9.11.4/node_modules/intl-messageformat/lib/src/formatters.js","../../../../ui/node_modules/.pnpm/intl-messageformat@9.11.4/node_modules/intl-messageformat/lib/src/core.js","../../../../ui/node_modules/.pnpm/intl-messageformat@9.11.4/node_modules/intl-messageformat/lib/index.js","../../../../ui/node_modules/.pnpm/svelte-i18n@3.3.13_svelte@3.49.0/node_modules/svelte-i18n/dist/runtime.esm.js","../../../../ui/packages/app/src/components/directory.ts","../../../../ui/packages/app/src/i18n.ts","../../../../ui/packages/app/src/Render.svelte","../../../../ui/packages/app/src/api_docs/img/clear.svelte","../../../../ui/packages/app/src/api_docs/NoApi.svelte","../../../../ui/packages/app/src/api_docs/utils.ts","../../../../ui/packages/app/src/api_docs/img/api-logo.svg","../../../../ui/packages/app/src/api_docs/ApiBanner.svelte","../../../../ui/packages/app/src/api_docs/EndpointDetail.svelte","../../../../ui/packages/app/src/api_docs/InputPayload.svelte","../../../../ui/packages/app/src/api_docs/ResponseObject.svelte","../../../../ui/packages/app/src/api_docs/CopyButton.svelte","../../../../ui/packages/app/src/api_docs/img/python.svg","../../../../ui/packages/app/src/api_docs/img/javascript.svg","../../../../ui/packages/app/src/api_docs/CodeSnippets.svelte","../../../../ui/packages/app/src/api_docs/ApiDocs.svelte","../../../../ui/packages/app/src/images/logo.svg","../../../../../../../../../static/img/api-logo.svg","../../../../ui/packages/app/src/Blocks.svelte"],"sourcesContent":["'use strict';\n\nvar isMergeableObject = function isMergeableObject(value) {\n\treturn isNonNullObject(value)\n\t\t&& !isSpecial(value)\n};\n\nfunction isNonNullObject(value) {\n\treturn !!value && typeof value === 'object'\n}\n\nfunction isSpecial(value) {\n\tvar stringValue = Object.prototype.toString.call(value);\n\n\treturn stringValue === '[object RegExp]'\n\t\t|| stringValue === '[object Date]'\n\t\t|| isReactElement(value)\n}\n\n// see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25\nvar canUseSymbol = typeof Symbol === 'function' && Symbol.for;\nvar REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;\n\nfunction isReactElement(value) {\n\treturn value.$$typeof === REACT_ELEMENT_TYPE\n}\n\nfunction emptyTarget(val) {\n\treturn Array.isArray(val) ? [] : {}\n}\n\nfunction cloneUnlessOtherwiseSpecified(value, options) {\n\treturn (options.clone !== false && options.isMergeableObject(value))\n\t\t? deepmerge(emptyTarget(value), value, options)\n\t\t: value\n}\n\nfunction defaultArrayMerge(target, source, options) {\n\treturn target.concat(source).map(function(element) {\n\t\treturn cloneUnlessOtherwiseSpecified(element, options)\n\t})\n}\n\nfunction getMergeFunction(key, options) {\n\tif (!options.customMerge) {\n\t\treturn deepmerge\n\t}\n\tvar customMerge = options.customMerge(key);\n\treturn typeof customMerge === 'function' ? customMerge : deepmerge\n}\n\nfunction getEnumerableOwnPropertySymbols(target) {\n\treturn Object.getOwnPropertySymbols\n\t\t? Object.getOwnPropertySymbols(target).filter(function(symbol) {\n\t\t\treturn target.propertyIsEnumerable(symbol)\n\t\t})\n\t\t: []\n}\n\nfunction getKeys(target) {\n\treturn Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))\n}\n\nfunction propertyIsOnObject(object, property) {\n\ttry {\n\t\treturn property in object\n\t} catch(_) {\n\t\treturn false\n\t}\n}\n\n// Protects from prototype poisoning and unexpected merging up the prototype chain.\nfunction propertyIsUnsafe(target, key) {\n\treturn propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,\n\t\t&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,\n\t\t\t&& Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.\n}\n\nfunction mergeObject(target, source, options) {\n\tvar destination = {};\n\tif (options.isMergeableObject(target)) {\n\t\tgetKeys(target).forEach(function(key) {\n\t\t\tdestination[key] = cloneUnlessOtherwiseSpecified(target[key], options);\n\t\t});\n\t}\n\tgetKeys(source).forEach(function(key) {\n\t\tif (propertyIsUnsafe(target, key)) {\n\t\t\treturn\n\t\t}\n\n\t\tif (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {\n\t\t\tdestination[key] = getMergeFunction(key, options)(target[key], source[key], options);\n\t\t} else {\n\t\t\tdestination[key] = cloneUnlessOtherwiseSpecified(source[key], options);\n\t\t}\n\t});\n\treturn destination\n}\n\nfunction deepmerge(target, source, options) {\n\toptions = options || {};\n\toptions.arrayMerge = options.arrayMerge || defaultArrayMerge;\n\toptions.isMergeableObject = options.isMergeableObject || isMergeableObject;\n\t// cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()\n\t// implementations can use it. The caller may not replace it.\n\toptions.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;\n\n\tvar sourceIsArray = Array.isArray(source);\n\tvar targetIsArray = Array.isArray(target);\n\tvar sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;\n\n\tif (!sourceAndTargetTypesMatch) {\n\t\treturn cloneUnlessOtherwiseSpecified(source, options)\n\t} else if (sourceIsArray) {\n\t\treturn options.arrayMerge(target, source, options)\n\t} else {\n\t\treturn mergeObject(target, source, options)\n\t}\n}\n\ndeepmerge.all = function deepmergeAll(array, options) {\n\tif (!Array.isArray(array)) {\n\t\tthrow new Error('first argument should be an array')\n\t}\n\n\treturn array.reduce(function(prev, next) {\n\t\treturn deepmerge(prev, next, options)\n\t}, {})\n};\n\nvar deepmerge_1 = deepmerge;\n\nmodule.exports = deepmerge_1;\n","/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n","export var ErrorKind;\n(function (ErrorKind) {\n /** Argument is unclosed (e.g. `{0`) */\n ErrorKind[ErrorKind[\"EXPECT_ARGUMENT_CLOSING_BRACE\"] = 1] = \"EXPECT_ARGUMENT_CLOSING_BRACE\";\n /** Argument is empty (e.g. `{}`). */\n ErrorKind[ErrorKind[\"EMPTY_ARGUMENT\"] = 2] = \"EMPTY_ARGUMENT\";\n /** Argument is malformed (e.g. `{foo!}``) */\n ErrorKind[ErrorKind[\"MALFORMED_ARGUMENT\"] = 3] = \"MALFORMED_ARGUMENT\";\n /** Expect an argument type (e.g. `{foo,}`) */\n ErrorKind[ErrorKind[\"EXPECT_ARGUMENT_TYPE\"] = 4] = \"EXPECT_ARGUMENT_TYPE\";\n /** Unsupported argument type (e.g. `{foo,foo}`) */\n ErrorKind[ErrorKind[\"INVALID_ARGUMENT_TYPE\"] = 5] = \"INVALID_ARGUMENT_TYPE\";\n /** Expect an argument style (e.g. `{foo, number, }`) */\n ErrorKind[ErrorKind[\"EXPECT_ARGUMENT_STYLE\"] = 6] = \"EXPECT_ARGUMENT_STYLE\";\n /** The number skeleton is invalid. */\n ErrorKind[ErrorKind[\"INVALID_NUMBER_SKELETON\"] = 7] = \"INVALID_NUMBER_SKELETON\";\n /** The date time skeleton is invalid. */\n ErrorKind[ErrorKind[\"INVALID_DATE_TIME_SKELETON\"] = 8] = \"INVALID_DATE_TIME_SKELETON\";\n /** Exepct a number skeleton following the `::` (e.g. `{foo, number, ::}`) */\n ErrorKind[ErrorKind[\"EXPECT_NUMBER_SKELETON\"] = 9] = \"EXPECT_NUMBER_SKELETON\";\n /** Exepct a date time skeleton following the `::` (e.g. `{foo, date, ::}`) */\n ErrorKind[ErrorKind[\"EXPECT_DATE_TIME_SKELETON\"] = 10] = \"EXPECT_DATE_TIME_SKELETON\";\n /** Unmatched apostrophes in the argument style (e.g. `{foo, number, 'test`) */\n ErrorKind[ErrorKind[\"UNCLOSED_QUOTE_IN_ARGUMENT_STYLE\"] = 11] = \"UNCLOSED_QUOTE_IN_ARGUMENT_STYLE\";\n /** Missing select argument options (e.g. `{foo, select}`) */\n ErrorKind[ErrorKind[\"EXPECT_SELECT_ARGUMENT_OPTIONS\"] = 12] = \"EXPECT_SELECT_ARGUMENT_OPTIONS\";\n /** Expecting an offset value in `plural` or `selectordinal` argument (e.g `{foo, plural, offset}`) */\n ErrorKind[ErrorKind[\"EXPECT_PLURAL_ARGUMENT_OFFSET_VALUE\"] = 13] = \"EXPECT_PLURAL_ARGUMENT_OFFSET_VALUE\";\n /** Offset value in `plural` or `selectordinal` is invalid (e.g. `{foo, plural, offset: x}`) */\n ErrorKind[ErrorKind[\"INVALID_PLURAL_ARGUMENT_OFFSET_VALUE\"] = 14] = \"INVALID_PLURAL_ARGUMENT_OFFSET_VALUE\";\n /** Expecting a selector in `select` argument (e.g `{foo, select}`) */\n ErrorKind[ErrorKind[\"EXPECT_SELECT_ARGUMENT_SELECTOR\"] = 15] = \"EXPECT_SELECT_ARGUMENT_SELECTOR\";\n /** Expecting a selector in `plural` or `selectordinal` argument (e.g `{foo, plural}`) */\n ErrorKind[ErrorKind[\"EXPECT_PLURAL_ARGUMENT_SELECTOR\"] = 16] = \"EXPECT_PLURAL_ARGUMENT_SELECTOR\";\n /** Expecting a message fragment after the `select` selector (e.g. `{foo, select, apple}`) */\n ErrorKind[ErrorKind[\"EXPECT_SELECT_ARGUMENT_SELECTOR_FRAGMENT\"] = 17] = \"EXPECT_SELECT_ARGUMENT_SELECTOR_FRAGMENT\";\n /**\n * Expecting a message fragment after the `plural` or `selectordinal` selector\n * (e.g. `{foo, plural, one}`)\n */\n ErrorKind[ErrorKind[\"EXPECT_PLURAL_ARGUMENT_SELECTOR_FRAGMENT\"] = 18] = \"EXPECT_PLURAL_ARGUMENT_SELECTOR_FRAGMENT\";\n /** Selector in `plural` or `selectordinal` is malformed (e.g. `{foo, plural, =x {#}}`) */\n ErrorKind[ErrorKind[\"INVALID_PLURAL_ARGUMENT_SELECTOR\"] = 19] = \"INVALID_PLURAL_ARGUMENT_SELECTOR\";\n /**\n * Duplicate selectors in `plural` or `selectordinal` argument.\n * (e.g. {foo, plural, one {#} one {#}})\n */\n ErrorKind[ErrorKind[\"DUPLICATE_PLURAL_ARGUMENT_SELECTOR\"] = 20] = \"DUPLICATE_PLURAL_ARGUMENT_SELECTOR\";\n /** Duplicate selectors in `select` argument.\n * (e.g. {foo, select, apple {apple} apple {apple}})\n */\n ErrorKind[ErrorKind[\"DUPLICATE_SELECT_ARGUMENT_SELECTOR\"] = 21] = \"DUPLICATE_SELECT_ARGUMENT_SELECTOR\";\n /** Plural or select argument option must have `other` clause. */\n ErrorKind[ErrorKind[\"MISSING_OTHER_CLAUSE\"] = 22] = \"MISSING_OTHER_CLAUSE\";\n /** The tag is malformed. (e.g. `foo) */\n ErrorKind[ErrorKind[\"INVALID_TAG\"] = 23] = \"INVALID_TAG\";\n /** The tag name is invalid. (e.g. `<123>foo123>`) */\n ErrorKind[ErrorKind[\"INVALID_TAG_NAME\"] = 25] = \"INVALID_TAG_NAME\";\n /** The closing tag does not match the opening tag. (e.g. `foo`) */\n ErrorKind[ErrorKind[\"UNMATCHED_CLOSING_TAG\"] = 26] = \"UNMATCHED_CLOSING_TAG\";\n /** The opening tag has unmatched closing tag. (e.g. `foo`) */\n ErrorKind[ErrorKind[\"UNCLOSED_TAG\"] = 27] = \"UNCLOSED_TAG\";\n})(ErrorKind || (ErrorKind = {}));\n","export var TYPE;\n(function (TYPE) {\n /**\n * Raw text\n */\n TYPE[TYPE[\"literal\"] = 0] = \"literal\";\n /**\n * Variable w/o any format, e.g `var` in `this is a {var}`\n */\n TYPE[TYPE[\"argument\"] = 1] = \"argument\";\n /**\n * Variable w/ number format\n */\n TYPE[TYPE[\"number\"] = 2] = \"number\";\n /**\n * Variable w/ date format\n */\n TYPE[TYPE[\"date\"] = 3] = \"date\";\n /**\n * Variable w/ time format\n */\n TYPE[TYPE[\"time\"] = 4] = \"time\";\n /**\n * Variable w/ select format\n */\n TYPE[TYPE[\"select\"] = 5] = \"select\";\n /**\n * Variable w/ plural format\n */\n TYPE[TYPE[\"plural\"] = 6] = \"plural\";\n /**\n * Only possible within plural argument.\n * This is the `#` symbol that will be substituted with the count.\n */\n TYPE[TYPE[\"pound\"] = 7] = \"pound\";\n /**\n * XML-like tag\n */\n TYPE[TYPE[\"tag\"] = 8] = \"tag\";\n})(TYPE || (TYPE = {}));\nexport var SKELETON_TYPE;\n(function (SKELETON_TYPE) {\n SKELETON_TYPE[SKELETON_TYPE[\"number\"] = 0] = \"number\";\n SKELETON_TYPE[SKELETON_TYPE[\"dateTime\"] = 1] = \"dateTime\";\n})(SKELETON_TYPE || (SKELETON_TYPE = {}));\n/**\n * Type Guards\n */\nexport function isLiteralElement(el) {\n return el.type === TYPE.literal;\n}\nexport function isArgumentElement(el) {\n return el.type === TYPE.argument;\n}\nexport function isNumberElement(el) {\n return el.type === TYPE.number;\n}\nexport function isDateElement(el) {\n return el.type === TYPE.date;\n}\nexport function isTimeElement(el) {\n return el.type === TYPE.time;\n}\nexport function isSelectElement(el) {\n return el.type === TYPE.select;\n}\nexport function isPluralElement(el) {\n return el.type === TYPE.plural;\n}\nexport function isPoundElement(el) {\n return el.type === TYPE.pound;\n}\nexport function isTagElement(el) {\n return el.type === TYPE.tag;\n}\nexport function isNumberSkeleton(el) {\n return !!(el && typeof el === 'object' && el.type === SKELETON_TYPE.number);\n}\nexport function isDateTimeSkeleton(el) {\n return !!(el && typeof el === 'object' && el.type === SKELETON_TYPE.dateTime);\n}\nexport function createLiteralElement(value) {\n return {\n type: TYPE.literal,\n value: value,\n };\n}\nexport function createNumberElement(value, style) {\n return {\n type: TYPE.number,\n value: value,\n style: style,\n };\n}\n","// @generated from regex-gen.ts\nexport var SPACE_SEPARATOR_REGEX = /[ \\xA0\\u1680\\u2000-\\u200A\\u202F\\u205F\\u3000]/;\nexport var WHITE_SPACE_REGEX = /[\\t-\\r \\x85\\u200E\\u200F\\u2028\\u2029]/;\n","/**\n * https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table\n * Credit: https://github.com/caridy/intl-datetimeformat-pattern/blob/master/index.js\n * with some tweaks\n */\nvar DATE_TIME_REGEX = /(?:[Eec]{1,6}|G{1,5}|[Qq]{1,5}|(?:[yYur]+|U{1,5})|[ML]{1,5}|d{1,2}|D{1,3}|F{1}|[abB]{1,5}|[hkHK]{1,2}|w{1,2}|W{1}|m{1,2}|s{1,2}|[zZOvVxX]{1,4})(?=([^']*'[^']*')*[^']*$)/g;\n/**\n * Parse Date time skeleton into Intl.DateTimeFormatOptions\n * Ref: https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table\n * @public\n * @param skeleton skeleton string\n */\nexport function parseDateTimeSkeleton(skeleton) {\n var result = {};\n skeleton.replace(DATE_TIME_REGEX, function (match) {\n var len = match.length;\n switch (match[0]) {\n // Era\n case 'G':\n result.era = len === 4 ? 'long' : len === 5 ? 'narrow' : 'short';\n break;\n // Year\n case 'y':\n result.year = len === 2 ? '2-digit' : 'numeric';\n break;\n case 'Y':\n case 'u':\n case 'U':\n case 'r':\n throw new RangeError('`Y/u/U/r` (year) patterns are not supported, use `y` instead');\n // Quarter\n case 'q':\n case 'Q':\n throw new RangeError('`q/Q` (quarter) patterns are not supported');\n // Month\n case 'M':\n case 'L':\n result.month = ['numeric', '2-digit', 'short', 'long', 'narrow'][len - 1];\n break;\n // Week\n case 'w':\n case 'W':\n throw new RangeError('`w/W` (week) patterns are not supported');\n case 'd':\n result.day = ['numeric', '2-digit'][len - 1];\n break;\n case 'D':\n case 'F':\n case 'g':\n throw new RangeError('`D/F/g` (day) patterns are not supported, use `d` instead');\n // Weekday\n case 'E':\n result.weekday = len === 4 ? 'short' : len === 5 ? 'narrow' : 'short';\n break;\n case 'e':\n if (len < 4) {\n throw new RangeError('`e..eee` (weekday) patterns are not supported');\n }\n result.weekday = ['short', 'long', 'narrow', 'short'][len - 4];\n break;\n case 'c':\n if (len < 4) {\n throw new RangeError('`c..ccc` (weekday) patterns are not supported');\n }\n result.weekday = ['short', 'long', 'narrow', 'short'][len - 4];\n break;\n // Period\n case 'a': // AM, PM\n result.hour12 = true;\n break;\n case 'b': // am, pm, noon, midnight\n case 'B': // flexible day periods\n throw new RangeError('`b/B` (period) patterns are not supported, use `a` instead');\n // Hour\n case 'h':\n result.hourCycle = 'h12';\n result.hour = ['numeric', '2-digit'][len - 1];\n break;\n case 'H':\n result.hourCycle = 'h23';\n result.hour = ['numeric', '2-digit'][len - 1];\n break;\n case 'K':\n result.hourCycle = 'h11';\n result.hour = ['numeric', '2-digit'][len - 1];\n break;\n case 'k':\n result.hourCycle = 'h24';\n result.hour = ['numeric', '2-digit'][len - 1];\n break;\n case 'j':\n case 'J':\n case 'C':\n throw new RangeError('`j/J/C` (hour) patterns are not supported, use `h/H/K/k` instead');\n // Minute\n case 'm':\n result.minute = ['numeric', '2-digit'][len - 1];\n break;\n // Second\n case 's':\n result.second = ['numeric', '2-digit'][len - 1];\n break;\n case 'S':\n case 'A':\n throw new RangeError('`S/A` (second) patterns are not supported, use `s` instead');\n // Zone\n case 'z': // 1..3, 4: specific non-location format\n result.timeZoneName = len < 4 ? 'short' : 'long';\n break;\n case 'Z': // 1..3, 4, 5: The ISO8601 varios formats\n case 'O': // 1, 4: miliseconds in day short, long\n case 'v': // 1, 4: generic non-location format\n case 'V': // 1, 2, 3, 4: time zone ID or city\n case 'X': // 1, 2, 3, 4: The ISO8601 varios formats\n case 'x': // 1, 2, 3, 4: The ISO8601 varios formats\n throw new RangeError('`Z/O/v/V/X/x` (timeZone) patterns are not supported, use `z` instead');\n }\n return '';\n });\n return result;\n}\n","// @generated from regex-gen.ts\nexport var WHITE_SPACE_REGEX = /[\\t-\\r \\x85\\u200E\\u200F\\u2028\\u2029]/i;\n","import { __assign } from \"tslib\";\nimport { WHITE_SPACE_REGEX } from './regex.generated';\nexport function parseNumberSkeletonFromString(skeleton) {\n if (skeleton.length === 0) {\n throw new Error('Number skeleton cannot be empty');\n }\n // Parse the skeleton\n var stringTokens = skeleton\n .split(WHITE_SPACE_REGEX)\n .filter(function (x) { return x.length > 0; });\n var tokens = [];\n for (var _i = 0, stringTokens_1 = stringTokens; _i < stringTokens_1.length; _i++) {\n var stringToken = stringTokens_1[_i];\n var stemAndOptions = stringToken.split('/');\n if (stemAndOptions.length === 0) {\n throw new Error('Invalid number skeleton');\n }\n var stem = stemAndOptions[0], options = stemAndOptions.slice(1);\n for (var _a = 0, options_1 = options; _a < options_1.length; _a++) {\n var option = options_1[_a];\n if (option.length === 0) {\n throw new Error('Invalid number skeleton');\n }\n }\n tokens.push({ stem: stem, options: options });\n }\n return tokens;\n}\nfunction icuUnitToEcma(unit) {\n return unit.replace(/^(.*?)-/, '');\n}\nvar FRACTION_PRECISION_REGEX = /^\\.(?:(0+)(\\*)?|(#+)|(0+)(#+))$/g;\nvar SIGNIFICANT_PRECISION_REGEX = /^(@+)?(\\+|#+)?[rs]?$/g;\nvar INTEGER_WIDTH_REGEX = /(\\*)(0+)|(#+)(0+)|(0+)/g;\nvar CONCISE_INTEGER_WIDTH_REGEX = /^(0+)$/;\nfunction parseSignificantPrecision(str) {\n var result = {};\n if (str[str.length - 1] === 'r') {\n result.roundingPriority = 'morePrecision';\n }\n else if (str[str.length - 1] === 's') {\n result.roundingPriority = 'lessPrecision';\n }\n str.replace(SIGNIFICANT_PRECISION_REGEX, function (_, g1, g2) {\n // @@@ case\n if (typeof g2 !== 'string') {\n result.minimumSignificantDigits = g1.length;\n result.maximumSignificantDigits = g1.length;\n }\n // @@@+ case\n else if (g2 === '+') {\n result.minimumSignificantDigits = g1.length;\n }\n // .### case\n else if (g1[0] === '#') {\n result.maximumSignificantDigits = g1.length;\n }\n // .@@## or .@@@ case\n else {\n result.minimumSignificantDigits = g1.length;\n result.maximumSignificantDigits =\n g1.length + (typeof g2 === 'string' ? g2.length : 0);\n }\n return '';\n });\n return result;\n}\nfunction parseSign(str) {\n switch (str) {\n case 'sign-auto':\n return {\n signDisplay: 'auto',\n };\n case 'sign-accounting':\n case '()':\n return {\n currencySign: 'accounting',\n };\n case 'sign-always':\n case '+!':\n return {\n signDisplay: 'always',\n };\n case 'sign-accounting-always':\n case '()!':\n return {\n signDisplay: 'always',\n currencySign: 'accounting',\n };\n case 'sign-except-zero':\n case '+?':\n return {\n signDisplay: 'exceptZero',\n };\n case 'sign-accounting-except-zero':\n case '()?':\n return {\n signDisplay: 'exceptZero',\n currencySign: 'accounting',\n };\n case 'sign-never':\n case '+_':\n return {\n signDisplay: 'never',\n };\n }\n}\nfunction parseConciseScientificAndEngineeringStem(stem) {\n // Engineering\n var result;\n if (stem[0] === 'E' && stem[1] === 'E') {\n result = {\n notation: 'engineering',\n };\n stem = stem.slice(2);\n }\n else if (stem[0] === 'E') {\n result = {\n notation: 'scientific',\n };\n stem = stem.slice(1);\n }\n if (result) {\n var signDisplay = stem.slice(0, 2);\n if (signDisplay === '+!') {\n result.signDisplay = 'always';\n stem = stem.slice(2);\n }\n else if (signDisplay === '+?') {\n result.signDisplay = 'exceptZero';\n stem = stem.slice(2);\n }\n if (!CONCISE_INTEGER_WIDTH_REGEX.test(stem)) {\n throw new Error('Malformed concise eng/scientific notation');\n }\n result.minimumIntegerDigits = stem.length;\n }\n return result;\n}\nfunction parseNotationOptions(opt) {\n var result = {};\n var signOpts = parseSign(opt);\n if (signOpts) {\n return signOpts;\n }\n return result;\n}\n/**\n * https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#skeleton-stems-and-options\n */\nexport function parseNumberSkeleton(tokens) {\n var result = {};\n for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) {\n var token = tokens_1[_i];\n switch (token.stem) {\n case 'percent':\n case '%':\n result.style = 'percent';\n continue;\n case '%x100':\n result.style = 'percent';\n result.scale = 100;\n continue;\n case 'currency':\n result.style = 'currency';\n result.currency = token.options[0];\n continue;\n case 'group-off':\n case ',_':\n result.useGrouping = false;\n continue;\n case 'precision-integer':\n case '.':\n result.maximumFractionDigits = 0;\n continue;\n case 'measure-unit':\n case 'unit':\n result.style = 'unit';\n result.unit = icuUnitToEcma(token.options[0]);\n continue;\n case 'compact-short':\n case 'K':\n result.notation = 'compact';\n result.compactDisplay = 'short';\n continue;\n case 'compact-long':\n case 'KK':\n result.notation = 'compact';\n result.compactDisplay = 'long';\n continue;\n case 'scientific':\n result = __assign(__assign(__assign({}, result), { notation: 'scientific' }), token.options.reduce(function (all, opt) { return (__assign(__assign({}, all), parseNotationOptions(opt))); }, {}));\n continue;\n case 'engineering':\n result = __assign(__assign(__assign({}, result), { notation: 'engineering' }), token.options.reduce(function (all, opt) { return (__assign(__assign({}, all), parseNotationOptions(opt))); }, {}));\n continue;\n case 'notation-simple':\n result.notation = 'standard';\n continue;\n // https://github.com/unicode-org/icu/blob/master/icu4c/source/i18n/unicode/unumberformatter.h\n case 'unit-width-narrow':\n result.currencyDisplay = 'narrowSymbol';\n result.unitDisplay = 'narrow';\n continue;\n case 'unit-width-short':\n result.currencyDisplay = 'code';\n result.unitDisplay = 'short';\n continue;\n case 'unit-width-full-name':\n result.currencyDisplay = 'name';\n result.unitDisplay = 'long';\n continue;\n case 'unit-width-iso-code':\n result.currencyDisplay = 'symbol';\n continue;\n case 'scale':\n result.scale = parseFloat(token.options[0]);\n continue;\n // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#integer-width\n case 'integer-width':\n if (token.options.length > 1) {\n throw new RangeError('integer-width stems only accept a single optional option');\n }\n token.options[0].replace(INTEGER_WIDTH_REGEX, function (_, g1, g2, g3, g4, g5) {\n if (g1) {\n result.minimumIntegerDigits = g2.length;\n }\n else if (g3 && g4) {\n throw new Error('We currently do not support maximum integer digits');\n }\n else if (g5) {\n throw new Error('We currently do not support exact integer digits');\n }\n return '';\n });\n continue;\n }\n // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#integer-width\n if (CONCISE_INTEGER_WIDTH_REGEX.test(token.stem)) {\n result.minimumIntegerDigits = token.stem.length;\n continue;\n }\n if (FRACTION_PRECISION_REGEX.test(token.stem)) {\n // Precision\n // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#fraction-precision\n // precision-integer case\n if (token.options.length > 1) {\n throw new RangeError('Fraction-precision stems only accept a single optional option');\n }\n token.stem.replace(FRACTION_PRECISION_REGEX, function (_, g1, g2, g3, g4, g5) {\n // .000* case (before ICU67 it was .000+)\n if (g2 === '*') {\n result.minimumFractionDigits = g1.length;\n }\n // .### case\n else if (g3 && g3[0] === '#') {\n result.maximumFractionDigits = g3.length;\n }\n // .00## case\n else if (g4 && g5) {\n result.minimumFractionDigits = g4.length;\n result.maximumFractionDigits = g4.length + g5.length;\n }\n else {\n result.minimumFractionDigits = g1.length;\n result.maximumFractionDigits = g1.length;\n }\n return '';\n });\n var opt = token.options[0];\n // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#trailing-zero-display\n if (opt === 'w') {\n result = __assign(__assign({}, result), { trailingZeroDisplay: 'stripIfInteger' });\n }\n else if (opt) {\n result = __assign(__assign({}, result), parseSignificantPrecision(opt));\n }\n continue;\n }\n // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#significant-digits-precision\n if (SIGNIFICANT_PRECISION_REGEX.test(token.stem)) {\n result = __assign(__assign({}, result), parseSignificantPrecision(token.stem));\n continue;\n }\n var signOpts = parseSign(token.stem);\n if (signOpts) {\n result = __assign(__assign({}, result), signOpts);\n }\n var conciseScientificAndEngineeringOpts = parseConciseScientificAndEngineeringStem(token.stem);\n if (conciseScientificAndEngineeringOpts) {\n result = __assign(__assign({}, result), conciseScientificAndEngineeringOpts);\n }\n }\n return result;\n}\n","var _a;\nimport { __assign } from \"tslib\";\nimport { ErrorKind } from './error';\nimport { SKELETON_TYPE, TYPE, } from './types';\nimport { SPACE_SEPARATOR_REGEX } from './regex.generated';\nimport { parseNumberSkeleton, parseNumberSkeletonFromString, parseDateTimeSkeleton, } from '@formatjs/icu-skeleton-parser';\nvar SPACE_SEPARATOR_START_REGEX = new RegExp(\"^\".concat(SPACE_SEPARATOR_REGEX.source, \"*\"));\nvar SPACE_SEPARATOR_END_REGEX = new RegExp(\"\".concat(SPACE_SEPARATOR_REGEX.source, \"*$\"));\nfunction createLocation(start, end) {\n return { start: start, end: end };\n}\n// #region Ponyfills\n// Consolidate these variables up top for easier toggling during debugging\nvar hasNativeStartsWith = !!String.prototype.startsWith;\nvar hasNativeFromCodePoint = !!String.fromCodePoint;\nvar hasNativeFromEntries = !!Object.fromEntries;\nvar hasNativeCodePointAt = !!String.prototype.codePointAt;\nvar hasTrimStart = !!String.prototype.trimStart;\nvar hasTrimEnd = !!String.prototype.trimEnd;\nvar hasNativeIsSafeInteger = !!Number.isSafeInteger;\nvar isSafeInteger = hasNativeIsSafeInteger\n ? Number.isSafeInteger\n : function (n) {\n return (typeof n === 'number' &&\n isFinite(n) &&\n Math.floor(n) === n &&\n Math.abs(n) <= 0x1fffffffffffff);\n };\n// IE11 does not support y and u.\nvar REGEX_SUPPORTS_U_AND_Y = true;\ntry {\n var re = RE('([^\\\\p{White_Space}\\\\p{Pattern_Syntax}]*)', 'yu');\n /**\n * legacy Edge or Xbox One browser\n * Unicode flag support: supported\n * Pattern_Syntax support: not supported\n * See https://github.com/formatjs/formatjs/issues/2822\n */\n REGEX_SUPPORTS_U_AND_Y = ((_a = re.exec('a')) === null || _a === void 0 ? void 0 : _a[0]) === 'a';\n}\ncatch (_) {\n REGEX_SUPPORTS_U_AND_Y = false;\n}\nvar startsWith = hasNativeStartsWith\n ? // Native\n function startsWith(s, search, position) {\n return s.startsWith(search, position);\n }\n : // For IE11\n function startsWith(s, search, position) {\n return s.slice(position, position + search.length) === search;\n };\nvar fromCodePoint = hasNativeFromCodePoint\n ? String.fromCodePoint\n : // IE11\n function fromCodePoint() {\n var codePoints = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n codePoints[_i] = arguments[_i];\n }\n var elements = '';\n var length = codePoints.length;\n var i = 0;\n var code;\n while (length > i) {\n code = codePoints[i++];\n if (code > 0x10ffff)\n throw RangeError(code + ' is not a valid code point');\n elements +=\n code < 0x10000\n ? String.fromCharCode(code)\n : String.fromCharCode(((code -= 0x10000) >> 10) + 0xd800, (code % 0x400) + 0xdc00);\n }\n return elements;\n };\nvar fromEntries = \n// native\nhasNativeFromEntries\n ? Object.fromEntries\n : // Ponyfill\n function fromEntries(entries) {\n var obj = {};\n for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {\n var _a = entries_1[_i], k = _a[0], v = _a[1];\n obj[k] = v;\n }\n return obj;\n };\nvar codePointAt = hasNativeCodePointAt\n ? // Native\n function codePointAt(s, index) {\n return s.codePointAt(index);\n }\n : // IE 11\n function codePointAt(s, index) {\n var size = s.length;\n if (index < 0 || index >= size) {\n return undefined;\n }\n var first = s.charCodeAt(index);\n var second;\n return first < 0xd800 ||\n first > 0xdbff ||\n index + 1 === size ||\n (second = s.charCodeAt(index + 1)) < 0xdc00 ||\n second > 0xdfff\n ? first\n : ((first - 0xd800) << 10) + (second - 0xdc00) + 0x10000;\n };\nvar trimStart = hasTrimStart\n ? // Native\n function trimStart(s) {\n return s.trimStart();\n }\n : // Ponyfill\n function trimStart(s) {\n return s.replace(SPACE_SEPARATOR_START_REGEX, '');\n };\nvar trimEnd = hasTrimEnd\n ? // Native\n function trimEnd(s) {\n return s.trimEnd();\n }\n : // Ponyfill\n function trimEnd(s) {\n return s.replace(SPACE_SEPARATOR_END_REGEX, '');\n };\n// Prevent minifier to translate new RegExp to literal form that might cause syntax error on IE11.\nfunction RE(s, flag) {\n return new RegExp(s, flag);\n}\n// #endregion\nvar matchIdentifierAtIndex;\nif (REGEX_SUPPORTS_U_AND_Y) {\n // Native\n var IDENTIFIER_PREFIX_RE_1 = RE('([^\\\\p{White_Space}\\\\p{Pattern_Syntax}]*)', 'yu');\n matchIdentifierAtIndex = function matchIdentifierAtIndex(s, index) {\n var _a;\n IDENTIFIER_PREFIX_RE_1.lastIndex = index;\n var match = IDENTIFIER_PREFIX_RE_1.exec(s);\n return (_a = match[1]) !== null && _a !== void 0 ? _a : '';\n };\n}\nelse {\n // IE11\n matchIdentifierAtIndex = function matchIdentifierAtIndex(s, index) {\n var match = [];\n while (true) {\n var c = codePointAt(s, index);\n if (c === undefined || _isWhiteSpace(c) || _isPatternSyntax(c)) {\n break;\n }\n match.push(c);\n index += c >= 0x10000 ? 2 : 1;\n }\n return fromCodePoint.apply(void 0, match);\n };\n}\nvar Parser = /** @class */ (function () {\n function Parser(message, options) {\n if (options === void 0) { options = {}; }\n this.message = message;\n this.position = { offset: 0, line: 1, column: 1 };\n this.ignoreTag = !!options.ignoreTag;\n this.requiresOtherClause = !!options.requiresOtherClause;\n this.shouldParseSkeletons = !!options.shouldParseSkeletons;\n }\n Parser.prototype.parse = function () {\n if (this.offset() !== 0) {\n throw Error('parser can only be used once');\n }\n return this.parseMessage(0, '', false);\n };\n Parser.prototype.parseMessage = function (nestingLevel, parentArgType, expectingCloseTag) {\n var elements = [];\n while (!this.isEOF()) {\n var char = this.char();\n if (char === 123 /* `{` */) {\n var result = this.parseArgument(nestingLevel, expectingCloseTag);\n if (result.err) {\n return result;\n }\n elements.push(result.val);\n }\n else if (char === 125 /* `}` */ && nestingLevel > 0) {\n break;\n }\n else if (char === 35 /* `#` */ &&\n (parentArgType === 'plural' || parentArgType === 'selectordinal')) {\n var position = this.clonePosition();\n this.bump();\n elements.push({\n type: TYPE.pound,\n location: createLocation(position, this.clonePosition()),\n });\n }\n else if (char === 60 /* `<` */ &&\n !this.ignoreTag &&\n this.peek() === 47 // char code for '/'\n ) {\n if (expectingCloseTag) {\n break;\n }\n else {\n return this.error(ErrorKind.UNMATCHED_CLOSING_TAG, createLocation(this.clonePosition(), this.clonePosition()));\n }\n }\n else if (char === 60 /* `<` */ &&\n !this.ignoreTag &&\n _isAlpha(this.peek() || 0)) {\n var result = this.parseTag(nestingLevel, parentArgType);\n if (result.err) {\n return result;\n }\n elements.push(result.val);\n }\n else {\n var result = this.parseLiteral(nestingLevel, parentArgType);\n if (result.err) {\n return result;\n }\n elements.push(result.val);\n }\n }\n return { val: elements, err: null };\n };\n /**\n * A tag name must start with an ASCII lower/upper case letter. The grammar is based on the\n * [custom element name][] except that a dash is NOT always mandatory and uppercase letters\n * are accepted:\n *\n * ```\n * tag ::= \"<\" tagName (whitespace)* \"/>\" | \"<\" tagName (whitespace)* \">\" message \"\" tagName (whitespace)* \">\"\n * tagName ::= [a-z] (PENChar)*\n * PENChar ::=\n * \"-\" | \".\" | [0-9] | \"_\" | [a-z] | [A-Z] | #xB7 | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x37D] |\n * [#x37F-#x1FFF] | [#x200C-#x200D] | [#x203F-#x2040] | [#x2070-#x218F] | [#x2C00-#x2FEF] |\n * [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]\n * ```\n *\n * [custom element name]: https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name\n * NOTE: We're a bit more lax here since HTML technically does not allow uppercase HTML element but we do\n * since other tag-based engines like React allow it\n */\n Parser.prototype.parseTag = function (nestingLevel, parentArgType) {\n var startPosition = this.clonePosition();\n this.bump(); // `<`\n var tagName = this.parseTagName();\n this.bumpSpace();\n if (this.bumpIf('/>')) {\n // Self closing tag\n return {\n val: {\n type: TYPE.literal,\n value: \"<\".concat(tagName, \"/>\"),\n location: createLocation(startPosition, this.clonePosition()),\n },\n err: null,\n };\n }\n else if (this.bumpIf('>')) {\n var childrenResult = this.parseMessage(nestingLevel + 1, parentArgType, true);\n if (childrenResult.err) {\n return childrenResult;\n }\n var children = childrenResult.val;\n // Expecting a close tag\n var endTagStartPosition = this.clonePosition();\n if (this.bumpIf('')) {\n if (this.isEOF() || !_isAlpha(this.char())) {\n return this.error(ErrorKind.INVALID_TAG, createLocation(endTagStartPosition, this.clonePosition()));\n }\n var closingTagNameStartPosition = this.clonePosition();\n var closingTagName = this.parseTagName();\n if (tagName !== closingTagName) {\n return this.error(ErrorKind.UNMATCHED_CLOSING_TAG, createLocation(closingTagNameStartPosition, this.clonePosition()));\n }\n this.bumpSpace();\n if (!this.bumpIf('>')) {\n return this.error(ErrorKind.INVALID_TAG, createLocation(endTagStartPosition, this.clonePosition()));\n }\n return {\n val: {\n type: TYPE.tag,\n value: tagName,\n children: children,\n location: createLocation(startPosition, this.clonePosition()),\n },\n err: null,\n };\n }\n else {\n return this.error(ErrorKind.UNCLOSED_TAG, createLocation(startPosition, this.clonePosition()));\n }\n }\n else {\n return this.error(ErrorKind.INVALID_TAG, createLocation(startPosition, this.clonePosition()));\n }\n };\n /**\n * This method assumes that the caller has peeked ahead for the first tag character.\n */\n Parser.prototype.parseTagName = function () {\n var startOffset = this.offset();\n this.bump(); // the first tag name character\n while (!this.isEOF() && _isPotentialElementNameChar(this.char())) {\n this.bump();\n }\n return this.message.slice(startOffset, this.offset());\n };\n Parser.prototype.parseLiteral = function (nestingLevel, parentArgType) {\n var start = this.clonePosition();\n var value = '';\n while (true) {\n var parseQuoteResult = this.tryParseQuote(parentArgType);\n if (parseQuoteResult) {\n value += parseQuoteResult;\n continue;\n }\n var parseUnquotedResult = this.tryParseUnquoted(nestingLevel, parentArgType);\n if (parseUnquotedResult) {\n value += parseUnquotedResult;\n continue;\n }\n var parseLeftAngleResult = this.tryParseLeftAngleBracket();\n if (parseLeftAngleResult) {\n value += parseLeftAngleResult;\n continue;\n }\n break;\n }\n var location = createLocation(start, this.clonePosition());\n return {\n val: { type: TYPE.literal, value: value, location: location },\n err: null,\n };\n };\n Parser.prototype.tryParseLeftAngleBracket = function () {\n if (!this.isEOF() &&\n this.char() === 60 /* `<` */ &&\n (this.ignoreTag ||\n // If at the opening tag or closing tag position, bail.\n !_isAlphaOrSlash(this.peek() || 0))) {\n this.bump(); // `<`\n return '<';\n }\n return null;\n };\n /**\n * Starting with ICU 4.8, an ASCII apostrophe only starts quoted text if it immediately precedes\n * a character that requires quoting (that is, \"only where needed\"), and works the same in\n * nested messages as on the top level of the pattern. The new behavior is otherwise compatible.\n */\n Parser.prototype.tryParseQuote = function (parentArgType) {\n if (this.isEOF() || this.char() !== 39 /* `'` */) {\n return null;\n }\n // Parse escaped char following the apostrophe, or early return if there is no escaped char.\n // Check if is valid escaped character\n switch (this.peek()) {\n case 39 /* `'` */:\n // double quote, should return as a single quote.\n this.bump();\n this.bump();\n return \"'\";\n // '{', '<', '>', '}'\n case 123:\n case 60:\n case 62:\n case 125:\n break;\n case 35: // '#'\n if (parentArgType === 'plural' || parentArgType === 'selectordinal') {\n break;\n }\n return null;\n default:\n return null;\n }\n this.bump(); // apostrophe\n var codePoints = [this.char()]; // escaped char\n this.bump();\n // read chars until the optional closing apostrophe is found\n while (!this.isEOF()) {\n var ch = this.char();\n if (ch === 39 /* `'` */) {\n if (this.peek() === 39 /* `'` */) {\n codePoints.push(39);\n // Bump one more time because we need to skip 2 characters.\n this.bump();\n }\n else {\n // Optional closing apostrophe.\n this.bump();\n break;\n }\n }\n else {\n codePoints.push(ch);\n }\n this.bump();\n }\n return fromCodePoint.apply(void 0, codePoints);\n };\n Parser.prototype.tryParseUnquoted = function (nestingLevel, parentArgType) {\n if (this.isEOF()) {\n return null;\n }\n var ch = this.char();\n if (ch === 60 /* `<` */ ||\n ch === 123 /* `{` */ ||\n (ch === 35 /* `#` */ &&\n (parentArgType === 'plural' || parentArgType === 'selectordinal')) ||\n (ch === 125 /* `}` */ && nestingLevel > 0)) {\n return null;\n }\n else {\n this.bump();\n return fromCodePoint(ch);\n }\n };\n Parser.prototype.parseArgument = function (nestingLevel, expectingCloseTag) {\n var openingBracePosition = this.clonePosition();\n this.bump(); // `{`\n this.bumpSpace();\n if (this.isEOF()) {\n return this.error(ErrorKind.EXPECT_ARGUMENT_CLOSING_BRACE, createLocation(openingBracePosition, this.clonePosition()));\n }\n if (this.char() === 125 /* `}` */) {\n this.bump();\n return this.error(ErrorKind.EMPTY_ARGUMENT, createLocation(openingBracePosition, this.clonePosition()));\n }\n // argument name\n var value = this.parseIdentifierIfPossible().value;\n if (!value) {\n return this.error(ErrorKind.MALFORMED_ARGUMENT, createLocation(openingBracePosition, this.clonePosition()));\n }\n this.bumpSpace();\n if (this.isEOF()) {\n return this.error(ErrorKind.EXPECT_ARGUMENT_CLOSING_BRACE, createLocation(openingBracePosition, this.clonePosition()));\n }\n switch (this.char()) {\n // Simple argument: `{name}`\n case 125 /* `}` */: {\n this.bump(); // `}`\n return {\n val: {\n type: TYPE.argument,\n // value does not include the opening and closing braces.\n value: value,\n location: createLocation(openingBracePosition, this.clonePosition()),\n },\n err: null,\n };\n }\n // Argument with options: `{name, format, ...}`\n case 44 /* `,` */: {\n this.bump(); // `,`\n this.bumpSpace();\n if (this.isEOF()) {\n return this.error(ErrorKind.EXPECT_ARGUMENT_CLOSING_BRACE, createLocation(openingBracePosition, this.clonePosition()));\n }\n return this.parseArgumentOptions(nestingLevel, expectingCloseTag, value, openingBracePosition);\n }\n default:\n return this.error(ErrorKind.MALFORMED_ARGUMENT, createLocation(openingBracePosition, this.clonePosition()));\n }\n };\n /**\n * Advance the parser until the end of the identifier, if it is currently on\n * an identifier character. Return an empty string otherwise.\n */\n Parser.prototype.parseIdentifierIfPossible = function () {\n var startingPosition = this.clonePosition();\n var startOffset = this.offset();\n var value = matchIdentifierAtIndex(this.message, startOffset);\n var endOffset = startOffset + value.length;\n this.bumpTo(endOffset);\n var endPosition = this.clonePosition();\n var location = createLocation(startingPosition, endPosition);\n return { value: value, location: location };\n };\n Parser.prototype.parseArgumentOptions = function (nestingLevel, expectingCloseTag, value, openingBracePosition) {\n var _a;\n // Parse this range:\n // {name, type, style}\n // ^---^\n var typeStartPosition = this.clonePosition();\n var argType = this.parseIdentifierIfPossible().value;\n var typeEndPosition = this.clonePosition();\n switch (argType) {\n case '':\n // Expecting a style string number, date, time, plural, selectordinal, or select.\n return this.error(ErrorKind.EXPECT_ARGUMENT_TYPE, createLocation(typeStartPosition, typeEndPosition));\n case 'number':\n case 'date':\n case 'time': {\n // Parse this range:\n // {name, number, style}\n // ^-------^\n this.bumpSpace();\n var styleAndLocation = null;\n if (this.bumpIf(',')) {\n this.bumpSpace();\n var styleStartPosition = this.clonePosition();\n var result = this.parseSimpleArgStyleIfPossible();\n if (result.err) {\n return result;\n }\n var style = trimEnd(result.val);\n if (style.length === 0) {\n return this.error(ErrorKind.EXPECT_ARGUMENT_STYLE, createLocation(this.clonePosition(), this.clonePosition()));\n }\n var styleLocation = createLocation(styleStartPosition, this.clonePosition());\n styleAndLocation = { style: style, styleLocation: styleLocation };\n }\n var argCloseResult = this.tryParseArgumentClose(openingBracePosition);\n if (argCloseResult.err) {\n return argCloseResult;\n }\n var location_1 = createLocation(openingBracePosition, this.clonePosition());\n // Extract style or skeleton\n if (styleAndLocation && startsWith(styleAndLocation === null || styleAndLocation === void 0 ? void 0 : styleAndLocation.style, '::', 0)) {\n // Skeleton starts with `::`.\n var skeleton = trimStart(styleAndLocation.style.slice(2));\n if (argType === 'number') {\n var result = this.parseNumberSkeletonFromString(skeleton, styleAndLocation.styleLocation);\n if (result.err) {\n return result;\n }\n return {\n val: { type: TYPE.number, value: value, location: location_1, style: result.val },\n err: null,\n };\n }\n else {\n if (skeleton.length === 0) {\n return this.error(ErrorKind.EXPECT_DATE_TIME_SKELETON, location_1);\n }\n var style = {\n type: SKELETON_TYPE.dateTime,\n pattern: skeleton,\n location: styleAndLocation.styleLocation,\n parsedOptions: this.shouldParseSkeletons\n ? parseDateTimeSkeleton(skeleton)\n : {},\n };\n var type = argType === 'date' ? TYPE.date : TYPE.time;\n return {\n val: { type: type, value: value, location: location_1, style: style },\n err: null,\n };\n }\n }\n // Regular style or no style.\n return {\n val: {\n type: argType === 'number'\n ? TYPE.number\n : argType === 'date'\n ? TYPE.date\n : TYPE.time,\n value: value,\n location: location_1,\n style: (_a = styleAndLocation === null || styleAndLocation === void 0 ? void 0 : styleAndLocation.style) !== null && _a !== void 0 ? _a : null,\n },\n err: null,\n };\n }\n case 'plural':\n case 'selectordinal':\n case 'select': {\n // Parse this range:\n // {name, plural, options}\n // ^---------^\n var typeEndPosition_1 = this.clonePosition();\n this.bumpSpace();\n if (!this.bumpIf(',')) {\n return this.error(ErrorKind.EXPECT_SELECT_ARGUMENT_OPTIONS, createLocation(typeEndPosition_1, __assign({}, typeEndPosition_1)));\n }\n this.bumpSpace();\n // Parse offset:\n // {name, plural, offset:1, options}\n // ^-----^\n //\n // or the first option:\n //\n // {name, plural, one {...} other {...}}\n // ^--^\n var identifierAndLocation = this.parseIdentifierIfPossible();\n var pluralOffset = 0;\n if (argType !== 'select' && identifierAndLocation.value === 'offset') {\n if (!this.bumpIf(':')) {\n return this.error(ErrorKind.EXPECT_PLURAL_ARGUMENT_OFFSET_VALUE, createLocation(this.clonePosition(), this.clonePosition()));\n }\n this.bumpSpace();\n var result = this.tryParseDecimalInteger(ErrorKind.EXPECT_PLURAL_ARGUMENT_OFFSET_VALUE, ErrorKind.INVALID_PLURAL_ARGUMENT_OFFSET_VALUE);\n if (result.err) {\n return result;\n }\n // Parse another identifier for option parsing\n this.bumpSpace();\n identifierAndLocation = this.parseIdentifierIfPossible();\n pluralOffset = result.val;\n }\n var optionsResult = this.tryParsePluralOrSelectOptions(nestingLevel, argType, expectingCloseTag, identifierAndLocation);\n if (optionsResult.err) {\n return optionsResult;\n }\n var argCloseResult = this.tryParseArgumentClose(openingBracePosition);\n if (argCloseResult.err) {\n return argCloseResult;\n }\n var location_2 = createLocation(openingBracePosition, this.clonePosition());\n if (argType === 'select') {\n return {\n val: {\n type: TYPE.select,\n value: value,\n options: fromEntries(optionsResult.val),\n location: location_2,\n },\n err: null,\n };\n }\n else {\n return {\n val: {\n type: TYPE.plural,\n value: value,\n options: fromEntries(optionsResult.val),\n offset: pluralOffset,\n pluralType: argType === 'plural' ? 'cardinal' : 'ordinal',\n location: location_2,\n },\n err: null,\n };\n }\n }\n default:\n return this.error(ErrorKind.INVALID_ARGUMENT_TYPE, createLocation(typeStartPosition, typeEndPosition));\n }\n };\n Parser.prototype.tryParseArgumentClose = function (openingBracePosition) {\n // Parse: {value, number, ::currency/GBP }\n //\n if (this.isEOF() || this.char() !== 125 /* `}` */) {\n return this.error(ErrorKind.EXPECT_ARGUMENT_CLOSING_BRACE, createLocation(openingBracePosition, this.clonePosition()));\n }\n this.bump(); // `}`\n return { val: true, err: null };\n };\n /**\n * See: https://github.com/unicode-org/icu/blob/af7ed1f6d2298013dc303628438ec4abe1f16479/icu4c/source/common/messagepattern.cpp#L659\n */\n Parser.prototype.parseSimpleArgStyleIfPossible = function () {\n var nestedBraces = 0;\n var startPosition = this.clonePosition();\n while (!this.isEOF()) {\n var ch = this.char();\n switch (ch) {\n case 39 /* `'` */: {\n // Treat apostrophe as quoting but include it in the style part.\n // Find the end of the quoted literal text.\n this.bump();\n var apostrophePosition = this.clonePosition();\n if (!this.bumpUntil(\"'\")) {\n return this.error(ErrorKind.UNCLOSED_QUOTE_IN_ARGUMENT_STYLE, createLocation(apostrophePosition, this.clonePosition()));\n }\n this.bump();\n break;\n }\n case 123 /* `{` */: {\n nestedBraces += 1;\n this.bump();\n break;\n }\n case 125 /* `}` */: {\n if (nestedBraces > 0) {\n nestedBraces -= 1;\n }\n else {\n return {\n val: this.message.slice(startPosition.offset, this.offset()),\n err: null,\n };\n }\n break;\n }\n default:\n this.bump();\n break;\n }\n }\n return {\n val: this.message.slice(startPosition.offset, this.offset()),\n err: null,\n };\n };\n Parser.prototype.parseNumberSkeletonFromString = function (skeleton, location) {\n var tokens = [];\n try {\n tokens = parseNumberSkeletonFromString(skeleton);\n }\n catch (e) {\n return this.error(ErrorKind.INVALID_NUMBER_SKELETON, location);\n }\n return {\n val: {\n type: SKELETON_TYPE.number,\n tokens: tokens,\n location: location,\n parsedOptions: this.shouldParseSkeletons\n ? parseNumberSkeleton(tokens)\n : {},\n },\n err: null,\n };\n };\n /**\n * @param nesting_level The current nesting level of messages.\n * This can be positive when parsing message fragment in select or plural argument options.\n * @param parent_arg_type The parent argument's type.\n * @param parsed_first_identifier If provided, this is the first identifier-like selector of\n * the argument. It is a by-product of a previous parsing attempt.\n * @param expecting_close_tag If true, this message is directly or indirectly nested inside\n * between a pair of opening and closing tags. The nested message will not parse beyond\n * the closing tag boundary.\n */\n Parser.prototype.tryParsePluralOrSelectOptions = function (nestingLevel, parentArgType, expectCloseTag, parsedFirstIdentifier) {\n var _a;\n var hasOtherClause = false;\n var options = [];\n var parsedSelectors = new Set();\n var selector = parsedFirstIdentifier.value, selectorLocation = parsedFirstIdentifier.location;\n // Parse:\n // one {one apple}\n // ^--^\n while (true) {\n if (selector.length === 0) {\n var startPosition = this.clonePosition();\n if (parentArgType !== 'select' && this.bumpIf('=')) {\n // Try parse `={number}` selector\n var result = this.tryParseDecimalInteger(ErrorKind.EXPECT_PLURAL_ARGUMENT_SELECTOR, ErrorKind.INVALID_PLURAL_ARGUMENT_SELECTOR);\n if (result.err) {\n return result;\n }\n selectorLocation = createLocation(startPosition, this.clonePosition());\n selector = this.message.slice(startPosition.offset, this.offset());\n }\n else {\n break;\n }\n }\n // Duplicate selector clauses\n if (parsedSelectors.has(selector)) {\n return this.error(parentArgType === 'select'\n ? ErrorKind.DUPLICATE_SELECT_ARGUMENT_SELECTOR\n : ErrorKind.DUPLICATE_PLURAL_ARGUMENT_SELECTOR, selectorLocation);\n }\n if (selector === 'other') {\n hasOtherClause = true;\n }\n // Parse:\n // one {one apple}\n // ^----------^\n this.bumpSpace();\n var openingBracePosition = this.clonePosition();\n if (!this.bumpIf('{')) {\n return this.error(parentArgType === 'select'\n ? ErrorKind.EXPECT_SELECT_ARGUMENT_SELECTOR_FRAGMENT\n : ErrorKind.EXPECT_PLURAL_ARGUMENT_SELECTOR_FRAGMENT, createLocation(this.clonePosition(), this.clonePosition()));\n }\n var fragmentResult = this.parseMessage(nestingLevel + 1, parentArgType, expectCloseTag);\n if (fragmentResult.err) {\n return fragmentResult;\n }\n var argCloseResult = this.tryParseArgumentClose(openingBracePosition);\n if (argCloseResult.err) {\n return argCloseResult;\n }\n options.push([\n selector,\n {\n value: fragmentResult.val,\n location: createLocation(openingBracePosition, this.clonePosition()),\n },\n ]);\n // Keep track of the existing selectors\n parsedSelectors.add(selector);\n // Prep next selector clause.\n this.bumpSpace();\n (_a = this.parseIdentifierIfPossible(), selector = _a.value, selectorLocation = _a.location);\n }\n if (options.length === 0) {\n return this.error(parentArgType === 'select'\n ? ErrorKind.EXPECT_SELECT_ARGUMENT_SELECTOR\n : ErrorKind.EXPECT_PLURAL_ARGUMENT_SELECTOR, createLocation(this.clonePosition(), this.clonePosition()));\n }\n if (this.requiresOtherClause && !hasOtherClause) {\n return this.error(ErrorKind.MISSING_OTHER_CLAUSE, createLocation(this.clonePosition(), this.clonePosition()));\n }\n return { val: options, err: null };\n };\n Parser.prototype.tryParseDecimalInteger = function (expectNumberError, invalidNumberError) {\n var sign = 1;\n var startingPosition = this.clonePosition();\n if (this.bumpIf('+')) {\n }\n else if (this.bumpIf('-')) {\n sign = -1;\n }\n var hasDigits = false;\n var decimal = 0;\n while (!this.isEOF()) {\n var ch = this.char();\n if (ch >= 48 /* `0` */ && ch <= 57 /* `9` */) {\n hasDigits = true;\n decimal = decimal * 10 + (ch - 48);\n this.bump();\n }\n else {\n break;\n }\n }\n var location = createLocation(startingPosition, this.clonePosition());\n if (!hasDigits) {\n return this.error(expectNumberError, location);\n }\n decimal *= sign;\n if (!isSafeInteger(decimal)) {\n return this.error(invalidNumberError, location);\n }\n return { val: decimal, err: null };\n };\n Parser.prototype.offset = function () {\n return this.position.offset;\n };\n Parser.prototype.isEOF = function () {\n return this.offset() === this.message.length;\n };\n Parser.prototype.clonePosition = function () {\n // This is much faster than `Object.assign` or spread.\n return {\n offset: this.position.offset,\n line: this.position.line,\n column: this.position.column,\n };\n };\n /**\n * Return the code point at the current position of the parser.\n * Throws if the index is out of bound.\n */\n Parser.prototype.char = function () {\n var offset = this.position.offset;\n if (offset >= this.message.length) {\n throw Error('out of bound');\n }\n var code = codePointAt(this.message, offset);\n if (code === undefined) {\n throw Error(\"Offset \".concat(offset, \" is at invalid UTF-16 code unit boundary\"));\n }\n return code;\n };\n Parser.prototype.error = function (kind, location) {\n return {\n val: null,\n err: {\n kind: kind,\n message: this.message,\n location: location,\n },\n };\n };\n /** Bump the parser to the next UTF-16 code unit. */\n Parser.prototype.bump = function () {\n if (this.isEOF()) {\n return;\n }\n var code = this.char();\n if (code === 10 /* '\\n' */) {\n this.position.line += 1;\n this.position.column = 1;\n this.position.offset += 1;\n }\n else {\n this.position.column += 1;\n // 0 ~ 0x10000 -> unicode BMP, otherwise skip the surrogate pair.\n this.position.offset += code < 0x10000 ? 1 : 2;\n }\n };\n /**\n * If the substring starting at the current position of the parser has\n * the given prefix, then bump the parser to the character immediately\n * following the prefix and return true. Otherwise, don't bump the parser\n * and return false.\n */\n Parser.prototype.bumpIf = function (prefix) {\n if (startsWith(this.message, prefix, this.offset())) {\n for (var i = 0; i < prefix.length; i++) {\n this.bump();\n }\n return true;\n }\n return false;\n };\n /**\n * Bump the parser until the pattern character is found and return `true`.\n * Otherwise bump to the end of the file and return `false`.\n */\n Parser.prototype.bumpUntil = function (pattern) {\n var currentOffset = this.offset();\n var index = this.message.indexOf(pattern, currentOffset);\n if (index >= 0) {\n this.bumpTo(index);\n return true;\n }\n else {\n this.bumpTo(this.message.length);\n return false;\n }\n };\n /**\n * Bump the parser to the target offset.\n * If target offset is beyond the end of the input, bump the parser to the end of the input.\n */\n Parser.prototype.bumpTo = function (targetOffset) {\n if (this.offset() > targetOffset) {\n throw Error(\"targetOffset \".concat(targetOffset, \" must be greater than or equal to the current offset \").concat(this.offset()));\n }\n targetOffset = Math.min(targetOffset, this.message.length);\n while (true) {\n var offset = this.offset();\n if (offset === targetOffset) {\n break;\n }\n if (offset > targetOffset) {\n throw Error(\"targetOffset \".concat(targetOffset, \" is at invalid UTF-16 code unit boundary\"));\n }\n this.bump();\n if (this.isEOF()) {\n break;\n }\n }\n };\n /** advance the parser through all whitespace to the next non-whitespace code unit. */\n Parser.prototype.bumpSpace = function () {\n while (!this.isEOF() && _isWhiteSpace(this.char())) {\n this.bump();\n }\n };\n /**\n * Peek at the *next* Unicode codepoint in the input without advancing the parser.\n * If the input has been exhausted, then this returns null.\n */\n Parser.prototype.peek = function () {\n if (this.isEOF()) {\n return null;\n }\n var code = this.char();\n var offset = this.offset();\n var nextCode = this.message.charCodeAt(offset + (code >= 0x10000 ? 2 : 1));\n return nextCode !== null && nextCode !== void 0 ? nextCode : null;\n };\n return Parser;\n}());\nexport { Parser };\n/**\n * This check if codepoint is alphabet (lower & uppercase)\n * @param codepoint\n * @returns\n */\nfunction _isAlpha(codepoint) {\n return ((codepoint >= 97 && codepoint <= 122) ||\n (codepoint >= 65 && codepoint <= 90));\n}\nfunction _isAlphaOrSlash(codepoint) {\n return _isAlpha(codepoint) || codepoint === 47; /* '/' */\n}\n/** See `parseTag` function docs. */\nfunction _isPotentialElementNameChar(c) {\n return (c === 45 /* '-' */ ||\n c === 46 /* '.' */ ||\n (c >= 48 && c <= 57) /* 0..9 */ ||\n c === 95 /* '_' */ ||\n (c >= 97 && c <= 122) /** a..z */ ||\n (c >= 65 && c <= 90) /* A..Z */ ||\n c == 0xb7 ||\n (c >= 0xc0 && c <= 0xd6) ||\n (c >= 0xd8 && c <= 0xf6) ||\n (c >= 0xf8 && c <= 0x37d) ||\n (c >= 0x37f && c <= 0x1fff) ||\n (c >= 0x200c && c <= 0x200d) ||\n (c >= 0x203f && c <= 0x2040) ||\n (c >= 0x2070 && c <= 0x218f) ||\n (c >= 0x2c00 && c <= 0x2fef) ||\n (c >= 0x3001 && c <= 0xd7ff) ||\n (c >= 0xf900 && c <= 0xfdcf) ||\n (c >= 0xfdf0 && c <= 0xfffd) ||\n (c >= 0x10000 && c <= 0xeffff));\n}\n/**\n * Code point equivalent of regex `\\p{White_Space}`.\n * From: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt\n */\nfunction _isWhiteSpace(c) {\n return ((c >= 0x0009 && c <= 0x000d) ||\n c === 0x0020 ||\n c === 0x0085 ||\n (c >= 0x200e && c <= 0x200f) ||\n c === 0x2028 ||\n c === 0x2029);\n}\n/**\n * Code point equivalent of regex `\\p{Pattern_Syntax}`.\n * See https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt\n */\nfunction _isPatternSyntax(c) {\n return ((c >= 0x0021 && c <= 0x0023) ||\n c === 0x0024 ||\n (c >= 0x0025 && c <= 0x0027) ||\n c === 0x0028 ||\n c === 0x0029 ||\n c === 0x002a ||\n c === 0x002b ||\n c === 0x002c ||\n c === 0x002d ||\n (c >= 0x002e && c <= 0x002f) ||\n (c >= 0x003a && c <= 0x003b) ||\n (c >= 0x003c && c <= 0x003e) ||\n (c >= 0x003f && c <= 0x0040) ||\n c === 0x005b ||\n c === 0x005c ||\n c === 0x005d ||\n c === 0x005e ||\n c === 0x0060 ||\n c === 0x007b ||\n c === 0x007c ||\n c === 0x007d ||\n c === 0x007e ||\n c === 0x00a1 ||\n (c >= 0x00a2 && c <= 0x00a5) ||\n c === 0x00a6 ||\n c === 0x00a7 ||\n c === 0x00a9 ||\n c === 0x00ab ||\n c === 0x00ac ||\n c === 0x00ae ||\n c === 0x00b0 ||\n c === 0x00b1 ||\n c === 0x00b6 ||\n c === 0x00bb ||\n c === 0x00bf ||\n c === 0x00d7 ||\n c === 0x00f7 ||\n (c >= 0x2010 && c <= 0x2015) ||\n (c >= 0x2016 && c <= 0x2017) ||\n c === 0x2018 ||\n c === 0x2019 ||\n c === 0x201a ||\n (c >= 0x201b && c <= 0x201c) ||\n c === 0x201d ||\n c === 0x201e ||\n c === 0x201f ||\n (c >= 0x2020 && c <= 0x2027) ||\n (c >= 0x2030 && c <= 0x2038) ||\n c === 0x2039 ||\n c === 0x203a ||\n (c >= 0x203b && c <= 0x203e) ||\n (c >= 0x2041 && c <= 0x2043) ||\n c === 0x2044 ||\n c === 0x2045 ||\n c === 0x2046 ||\n (c >= 0x2047 && c <= 0x2051) ||\n c === 0x2052 ||\n c === 0x2053 ||\n (c >= 0x2055 && c <= 0x205e) ||\n (c >= 0x2190 && c <= 0x2194) ||\n (c >= 0x2195 && c <= 0x2199) ||\n (c >= 0x219a && c <= 0x219b) ||\n (c >= 0x219c && c <= 0x219f) ||\n c === 0x21a0 ||\n (c >= 0x21a1 && c <= 0x21a2) ||\n c === 0x21a3 ||\n (c >= 0x21a4 && c <= 0x21a5) ||\n c === 0x21a6 ||\n (c >= 0x21a7 && c <= 0x21ad) ||\n c === 0x21ae ||\n (c >= 0x21af && c <= 0x21cd) ||\n (c >= 0x21ce && c <= 0x21cf) ||\n (c >= 0x21d0 && c <= 0x21d1) ||\n c === 0x21d2 ||\n c === 0x21d3 ||\n c === 0x21d4 ||\n (c >= 0x21d5 && c <= 0x21f3) ||\n (c >= 0x21f4 && c <= 0x22ff) ||\n (c >= 0x2300 && c <= 0x2307) ||\n c === 0x2308 ||\n c === 0x2309 ||\n c === 0x230a ||\n c === 0x230b ||\n (c >= 0x230c && c <= 0x231f) ||\n (c >= 0x2320 && c <= 0x2321) ||\n (c >= 0x2322 && c <= 0x2328) ||\n c === 0x2329 ||\n c === 0x232a ||\n (c >= 0x232b && c <= 0x237b) ||\n c === 0x237c ||\n (c >= 0x237d && c <= 0x239a) ||\n (c >= 0x239b && c <= 0x23b3) ||\n (c >= 0x23b4 && c <= 0x23db) ||\n (c >= 0x23dc && c <= 0x23e1) ||\n (c >= 0x23e2 && c <= 0x2426) ||\n (c >= 0x2427 && c <= 0x243f) ||\n (c >= 0x2440 && c <= 0x244a) ||\n (c >= 0x244b && c <= 0x245f) ||\n (c >= 0x2500 && c <= 0x25b6) ||\n c === 0x25b7 ||\n (c >= 0x25b8 && c <= 0x25c0) ||\n c === 0x25c1 ||\n (c >= 0x25c2 && c <= 0x25f7) ||\n (c >= 0x25f8 && c <= 0x25ff) ||\n (c >= 0x2600 && c <= 0x266e) ||\n c === 0x266f ||\n (c >= 0x2670 && c <= 0x2767) ||\n c === 0x2768 ||\n c === 0x2769 ||\n c === 0x276a ||\n c === 0x276b ||\n c === 0x276c ||\n c === 0x276d ||\n c === 0x276e ||\n c === 0x276f ||\n c === 0x2770 ||\n c === 0x2771 ||\n c === 0x2772 ||\n c === 0x2773 ||\n c === 0x2774 ||\n c === 0x2775 ||\n (c >= 0x2794 && c <= 0x27bf) ||\n (c >= 0x27c0 && c <= 0x27c4) ||\n c === 0x27c5 ||\n c === 0x27c6 ||\n (c >= 0x27c7 && c <= 0x27e5) ||\n c === 0x27e6 ||\n c === 0x27e7 ||\n c === 0x27e8 ||\n c === 0x27e9 ||\n c === 0x27ea ||\n c === 0x27eb ||\n c === 0x27ec ||\n c === 0x27ed ||\n c === 0x27ee ||\n c === 0x27ef ||\n (c >= 0x27f0 && c <= 0x27ff) ||\n (c >= 0x2800 && c <= 0x28ff) ||\n (c >= 0x2900 && c <= 0x2982) ||\n c === 0x2983 ||\n c === 0x2984 ||\n c === 0x2985 ||\n c === 0x2986 ||\n c === 0x2987 ||\n c === 0x2988 ||\n c === 0x2989 ||\n c === 0x298a ||\n c === 0x298b ||\n c === 0x298c ||\n c === 0x298d ||\n c === 0x298e ||\n c === 0x298f ||\n c === 0x2990 ||\n c === 0x2991 ||\n c === 0x2992 ||\n c === 0x2993 ||\n c === 0x2994 ||\n c === 0x2995 ||\n c === 0x2996 ||\n c === 0x2997 ||\n c === 0x2998 ||\n (c >= 0x2999 && c <= 0x29d7) ||\n c === 0x29d8 ||\n c === 0x29d9 ||\n c === 0x29da ||\n c === 0x29db ||\n (c >= 0x29dc && c <= 0x29fb) ||\n c === 0x29fc ||\n c === 0x29fd ||\n (c >= 0x29fe && c <= 0x2aff) ||\n (c >= 0x2b00 && c <= 0x2b2f) ||\n (c >= 0x2b30 && c <= 0x2b44) ||\n (c >= 0x2b45 && c <= 0x2b46) ||\n (c >= 0x2b47 && c <= 0x2b4c) ||\n (c >= 0x2b4d && c <= 0x2b73) ||\n (c >= 0x2b74 && c <= 0x2b75) ||\n (c >= 0x2b76 && c <= 0x2b95) ||\n c === 0x2b96 ||\n (c >= 0x2b97 && c <= 0x2bff) ||\n (c >= 0x2e00 && c <= 0x2e01) ||\n c === 0x2e02 ||\n c === 0x2e03 ||\n c === 0x2e04 ||\n c === 0x2e05 ||\n (c >= 0x2e06 && c <= 0x2e08) ||\n c === 0x2e09 ||\n c === 0x2e0a ||\n c === 0x2e0b ||\n c === 0x2e0c ||\n c === 0x2e0d ||\n (c >= 0x2e0e && c <= 0x2e16) ||\n c === 0x2e17 ||\n (c >= 0x2e18 && c <= 0x2e19) ||\n c === 0x2e1a ||\n c === 0x2e1b ||\n c === 0x2e1c ||\n c === 0x2e1d ||\n (c >= 0x2e1e && c <= 0x2e1f) ||\n c === 0x2e20 ||\n c === 0x2e21 ||\n c === 0x2e22 ||\n c === 0x2e23 ||\n c === 0x2e24 ||\n c === 0x2e25 ||\n c === 0x2e26 ||\n c === 0x2e27 ||\n c === 0x2e28 ||\n c === 0x2e29 ||\n (c >= 0x2e2a && c <= 0x2e2e) ||\n c === 0x2e2f ||\n (c >= 0x2e30 && c <= 0x2e39) ||\n (c >= 0x2e3a && c <= 0x2e3b) ||\n (c >= 0x2e3c && c <= 0x2e3f) ||\n c === 0x2e40 ||\n c === 0x2e41 ||\n c === 0x2e42 ||\n (c >= 0x2e43 && c <= 0x2e4f) ||\n (c >= 0x2e50 && c <= 0x2e51) ||\n c === 0x2e52 ||\n (c >= 0x2e53 && c <= 0x2e7f) ||\n (c >= 0x3001 && c <= 0x3003) ||\n c === 0x3008 ||\n c === 0x3009 ||\n c === 0x300a ||\n c === 0x300b ||\n c === 0x300c ||\n c === 0x300d ||\n c === 0x300e ||\n c === 0x300f ||\n c === 0x3010 ||\n c === 0x3011 ||\n (c >= 0x3012 && c <= 0x3013) ||\n c === 0x3014 ||\n c === 0x3015 ||\n c === 0x3016 ||\n c === 0x3017 ||\n c === 0x3018 ||\n c === 0x3019 ||\n c === 0x301a ||\n c === 0x301b ||\n c === 0x301c ||\n c === 0x301d ||\n (c >= 0x301e && c <= 0x301f) ||\n c === 0x3020 ||\n c === 0x3030 ||\n c === 0xfd3e ||\n c === 0xfd3f ||\n (c >= 0xfe45 && c <= 0xfe46));\n}\n","import { __assign } from \"tslib\";\nimport { ErrorKind } from './error';\nimport { Parser } from './parser';\nimport { isDateElement, isDateTimeSkeleton, isNumberElement, isNumberSkeleton, isPluralElement, isSelectElement, isTagElement, isTimeElement, } from './types';\nfunction pruneLocation(els) {\n els.forEach(function (el) {\n delete el.location;\n if (isSelectElement(el) || isPluralElement(el)) {\n for (var k in el.options) {\n delete el.options[k].location;\n pruneLocation(el.options[k].value);\n }\n }\n else if (isNumberElement(el) && isNumberSkeleton(el.style)) {\n delete el.style.location;\n }\n else if ((isDateElement(el) || isTimeElement(el)) &&\n isDateTimeSkeleton(el.style)) {\n delete el.style.location;\n }\n else if (isTagElement(el)) {\n pruneLocation(el.children);\n }\n });\n}\nexport function parse(message, opts) {\n if (opts === void 0) { opts = {}; }\n opts = __assign({ shouldParseSkeletons: true, requiresOtherClause: true }, opts);\n var result = new Parser(message, opts).parse();\n if (result.err) {\n var error = SyntaxError(ErrorKind[result.err.kind]);\n // @ts-expect-error Assign to error object\n error.location = result.err.location;\n // @ts-expect-error Assign to error object\n error.originalMessage = result.err.message;\n throw error;\n }\n if (!(opts === null || opts === void 0 ? void 0 : opts.captureLocation)) {\n pruneLocation(result.val);\n }\n return result.val;\n}\nexport * from './types';\n","//\n// Main\n//\nexport default function memoize(fn, options) {\n var cache = options && options.cache ? options.cache : cacheDefault;\n var serializer = options && options.serializer ? options.serializer : serializerDefault;\n var strategy = options && options.strategy ? options.strategy : strategyDefault;\n return strategy(fn, {\n cache: cache,\n serializer: serializer,\n });\n}\n//\n// Strategy\n//\nfunction isPrimitive(value) {\n return (value == null || typeof value === 'number' || typeof value === 'boolean'); // || typeof value === \"string\" 'unsafe' primitive for our needs\n}\nfunction monadic(fn, cache, serializer, arg) {\n var cacheKey = isPrimitive(arg) ? arg : serializer(arg);\n var computedValue = cache.get(cacheKey);\n if (typeof computedValue === 'undefined') {\n computedValue = fn.call(this, arg);\n cache.set(cacheKey, computedValue);\n }\n return computedValue;\n}\nfunction variadic(fn, cache, serializer) {\n var args = Array.prototype.slice.call(arguments, 3);\n var cacheKey = serializer(args);\n var computedValue = cache.get(cacheKey);\n if (typeof computedValue === 'undefined') {\n computedValue = fn.apply(this, args);\n cache.set(cacheKey, computedValue);\n }\n return computedValue;\n}\nfunction assemble(fn, context, strategy, cache, serialize) {\n return strategy.bind(context, fn, cache, serialize);\n}\nfunction strategyDefault(fn, options) {\n var strategy = fn.length === 1 ? monadic : variadic;\n return assemble(fn, this, strategy, options.cache.create(), options.serializer);\n}\nfunction strategyVariadic(fn, options) {\n return assemble(fn, this, variadic, options.cache.create(), options.serializer);\n}\nfunction strategyMonadic(fn, options) {\n return assemble(fn, this, monadic, options.cache.create(), options.serializer);\n}\n//\n// Serializer\n//\nvar serializerDefault = function () {\n return JSON.stringify(arguments);\n};\n//\n// Cache\n//\nfunction ObjectWithoutPrototypeCache() {\n this.cache = Object.create(null);\n}\nObjectWithoutPrototypeCache.prototype.get = function (key) {\n return this.cache[key];\n};\nObjectWithoutPrototypeCache.prototype.set = function (key, value) {\n this.cache[key] = value;\n};\nvar cacheDefault = {\n create: function create() {\n // @ts-ignore\n return new ObjectWithoutPrototypeCache();\n },\n};\nexport var strategies = {\n variadic: strategyVariadic,\n monadic: strategyMonadic,\n};\n","import { __extends } from \"tslib\";\nexport var ErrorCode;\n(function (ErrorCode) {\n // When we have a placeholder but no value to format\n ErrorCode[\"MISSING_VALUE\"] = \"MISSING_VALUE\";\n // When value supplied is invalid\n ErrorCode[\"INVALID_VALUE\"] = \"INVALID_VALUE\";\n // When we need specific Intl API but it's not available\n ErrorCode[\"MISSING_INTL_API\"] = \"MISSING_INTL_API\";\n})(ErrorCode || (ErrorCode = {}));\nvar FormatError = /** @class */ (function (_super) {\n __extends(FormatError, _super);\n function FormatError(msg, code, originalMessage) {\n var _this = _super.call(this, msg) || this;\n _this.code = code;\n _this.originalMessage = originalMessage;\n return _this;\n }\n FormatError.prototype.toString = function () {\n return \"[formatjs Error: \".concat(this.code, \"] \").concat(this.message);\n };\n return FormatError;\n}(Error));\nexport { FormatError };\nvar InvalidValueError = /** @class */ (function (_super) {\n __extends(InvalidValueError, _super);\n function InvalidValueError(variableId, value, options, originalMessage) {\n return _super.call(this, \"Invalid values for \\\"\".concat(variableId, \"\\\": \\\"\").concat(value, \"\\\". Options are \\\"\").concat(Object.keys(options).join('\", \"'), \"\\\"\"), ErrorCode.INVALID_VALUE, originalMessage) || this;\n }\n return InvalidValueError;\n}(FormatError));\nexport { InvalidValueError };\nvar InvalidValueTypeError = /** @class */ (function (_super) {\n __extends(InvalidValueTypeError, _super);\n function InvalidValueTypeError(value, type, originalMessage) {\n return _super.call(this, \"Value for \\\"\".concat(value, \"\\\" must be of type \").concat(type), ErrorCode.INVALID_VALUE, originalMessage) || this;\n }\n return InvalidValueTypeError;\n}(FormatError));\nexport { InvalidValueTypeError };\nvar MissingValueError = /** @class */ (function (_super) {\n __extends(MissingValueError, _super);\n function MissingValueError(variableId, originalMessage) {\n return _super.call(this, \"The intl string context variable \\\"\".concat(variableId, \"\\\" was not provided to the string \\\"\").concat(originalMessage, \"\\\"\"), ErrorCode.MISSING_VALUE, originalMessage) || this;\n }\n return MissingValueError;\n}(FormatError));\nexport { MissingValueError };\n","import { isArgumentElement, isDateElement, isDateTimeSkeleton, isLiteralElement, isNumberElement, isNumberSkeleton, isPluralElement, isPoundElement, isSelectElement, isTimeElement, isTagElement, } from '@formatjs/icu-messageformat-parser';\nimport { MissingValueError, InvalidValueError, ErrorCode, FormatError, InvalidValueTypeError, } from './error';\nexport var PART_TYPE;\n(function (PART_TYPE) {\n PART_TYPE[PART_TYPE[\"literal\"] = 0] = \"literal\";\n PART_TYPE[PART_TYPE[\"object\"] = 1] = \"object\";\n})(PART_TYPE || (PART_TYPE = {}));\nfunction mergeLiteral(parts) {\n if (parts.length < 2) {\n return parts;\n }\n return parts.reduce(function (all, part) {\n var lastPart = all[all.length - 1];\n if (!lastPart ||\n lastPart.type !== PART_TYPE.literal ||\n part.type !== PART_TYPE.literal) {\n all.push(part);\n }\n else {\n lastPart.value += part.value;\n }\n return all;\n }, []);\n}\nexport function isFormatXMLElementFn(el) {\n return typeof el === 'function';\n}\n// TODO(skeleton): add skeleton support\nexport function formatToParts(els, locales, formatters, formats, values, currentPluralValue, \n// For debugging\noriginalMessage) {\n // Hot path for straight simple msg translations\n if (els.length === 1 && isLiteralElement(els[0])) {\n return [\n {\n type: PART_TYPE.literal,\n value: els[0].value,\n },\n ];\n }\n var result = [];\n for (var _i = 0, els_1 = els; _i < els_1.length; _i++) {\n var el = els_1[_i];\n // Exit early for string parts.\n if (isLiteralElement(el)) {\n result.push({\n type: PART_TYPE.literal,\n value: el.value,\n });\n continue;\n }\n // TODO: should this part be literal type?\n // Replace `#` in plural rules with the actual numeric value.\n if (isPoundElement(el)) {\n if (typeof currentPluralValue === 'number') {\n result.push({\n type: PART_TYPE.literal,\n value: formatters.getNumberFormat(locales).format(currentPluralValue),\n });\n }\n continue;\n }\n var varName = el.value;\n // Enforce that all required values are provided by the caller.\n if (!(values && varName in values)) {\n throw new MissingValueError(varName, originalMessage);\n }\n var value = values[varName];\n if (isArgumentElement(el)) {\n if (!value || typeof value === 'string' || typeof value === 'number') {\n value =\n typeof value === 'string' || typeof value === 'number'\n ? String(value)\n : '';\n }\n result.push({\n type: typeof value === 'string' ? PART_TYPE.literal : PART_TYPE.object,\n value: value,\n });\n continue;\n }\n // Recursively format plural and select parts' option — which can be a\n // nested pattern structure. The choosing of the option to use is\n // abstracted-by and delegated-to the part helper object.\n if (isDateElement(el)) {\n var style = typeof el.style === 'string'\n ? formats.date[el.style]\n : isDateTimeSkeleton(el.style)\n ? el.style.parsedOptions\n : undefined;\n result.push({\n type: PART_TYPE.literal,\n value: formatters\n .getDateTimeFormat(locales, style)\n .format(value),\n });\n continue;\n }\n if (isTimeElement(el)) {\n var style = typeof el.style === 'string'\n ? formats.time[el.style]\n : isDateTimeSkeleton(el.style)\n ? el.style.parsedOptions\n : undefined;\n result.push({\n type: PART_TYPE.literal,\n value: formatters\n .getDateTimeFormat(locales, style)\n .format(value),\n });\n continue;\n }\n if (isNumberElement(el)) {\n var style = typeof el.style === 'string'\n ? formats.number[el.style]\n : isNumberSkeleton(el.style)\n ? el.style.parsedOptions\n : undefined;\n if (style && style.scale) {\n value =\n value *\n (style.scale || 1);\n }\n result.push({\n type: PART_TYPE.literal,\n value: formatters\n .getNumberFormat(locales, style)\n .format(value),\n });\n continue;\n }\n if (isTagElement(el)) {\n var children = el.children, value_1 = el.value;\n var formatFn = values[value_1];\n if (!isFormatXMLElementFn(formatFn)) {\n throw new InvalidValueTypeError(value_1, 'function', originalMessage);\n }\n var parts = formatToParts(children, locales, formatters, formats, values, currentPluralValue);\n var chunks = formatFn(parts.map(function (p) { return p.value; }));\n if (!Array.isArray(chunks)) {\n chunks = [chunks];\n }\n result.push.apply(result, chunks.map(function (c) {\n return {\n type: typeof c === 'string' ? PART_TYPE.literal : PART_TYPE.object,\n value: c,\n };\n }));\n }\n if (isSelectElement(el)) {\n var opt = el.options[value] || el.options.other;\n if (!opt) {\n throw new InvalidValueError(el.value, value, Object.keys(el.options), originalMessage);\n }\n result.push.apply(result, formatToParts(opt.value, locales, formatters, formats, values));\n continue;\n }\n if (isPluralElement(el)) {\n var opt = el.options[\"=\".concat(value)];\n if (!opt) {\n if (!Intl.PluralRules) {\n throw new FormatError(\"Intl.PluralRules is not available in this environment.\\nTry polyfilling it using \\\"@formatjs/intl-pluralrules\\\"\\n\", ErrorCode.MISSING_INTL_API, originalMessage);\n }\n var rule = formatters\n .getPluralRules(locales, { type: el.pluralType })\n .select(value - (el.offset || 0));\n opt = el.options[rule] || el.options.other;\n }\n if (!opt) {\n throw new InvalidValueError(el.value, value, Object.keys(el.options), originalMessage);\n }\n result.push.apply(result, formatToParts(opt.value, locales, formatters, formats, values, value - (el.offset || 0)));\n continue;\n }\n }\n return mergeLiteral(result);\n}\n","/*\nCopyright (c) 2014, Yahoo! Inc. All rights reserved.\nCopyrights licensed under the New BSD License.\nSee the accompanying LICENSE file for terms.\n*/\nimport { __assign, __spreadArray } from \"tslib\";\nimport { parse } from '@formatjs/icu-messageformat-parser';\nimport memoize, { strategies } from '@formatjs/fast-memoize';\nimport { formatToParts, PART_TYPE, } from './formatters';\n// -- MessageFormat --------------------------------------------------------\nfunction mergeConfig(c1, c2) {\n if (!c2) {\n return c1;\n }\n return __assign(__assign(__assign({}, (c1 || {})), (c2 || {})), Object.keys(c1).reduce(function (all, k) {\n all[k] = __assign(__assign({}, c1[k]), (c2[k] || {}));\n return all;\n }, {}));\n}\nfunction mergeConfigs(defaultConfig, configs) {\n if (!configs) {\n return defaultConfig;\n }\n return Object.keys(defaultConfig).reduce(function (all, k) {\n all[k] = mergeConfig(defaultConfig[k], configs[k]);\n return all;\n }, __assign({}, defaultConfig));\n}\nfunction createFastMemoizeCache(store) {\n return {\n create: function () {\n return {\n get: function (key) {\n return store[key];\n },\n set: function (key, value) {\n store[key] = value;\n },\n };\n },\n };\n}\nfunction createDefaultFormatters(cache) {\n if (cache === void 0) { cache = {\n number: {},\n dateTime: {},\n pluralRules: {},\n }; }\n return {\n getNumberFormat: memoize(function () {\n var _a;\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n return new ((_a = Intl.NumberFormat).bind.apply(_a, __spreadArray([void 0], args, false)))();\n }, {\n cache: createFastMemoizeCache(cache.number),\n strategy: strategies.variadic,\n }),\n getDateTimeFormat: memoize(function () {\n var _a;\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n return new ((_a = Intl.DateTimeFormat).bind.apply(_a, __spreadArray([void 0], args, false)))();\n }, {\n cache: createFastMemoizeCache(cache.dateTime),\n strategy: strategies.variadic,\n }),\n getPluralRules: memoize(function () {\n var _a;\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n return new ((_a = Intl.PluralRules).bind.apply(_a, __spreadArray([void 0], args, false)))();\n }, {\n cache: createFastMemoizeCache(cache.pluralRules),\n strategy: strategies.variadic,\n }),\n };\n}\nvar IntlMessageFormat = /** @class */ (function () {\n function IntlMessageFormat(message, locales, overrideFormats, opts) {\n var _this = this;\n if (locales === void 0) { locales = IntlMessageFormat.defaultLocale; }\n this.formatterCache = {\n number: {},\n dateTime: {},\n pluralRules: {},\n };\n this.format = function (values) {\n var parts = _this.formatToParts(values);\n // Hot path for straight simple msg translations\n if (parts.length === 1) {\n return parts[0].value;\n }\n var result = parts.reduce(function (all, part) {\n if (!all.length ||\n part.type !== PART_TYPE.literal ||\n typeof all[all.length - 1] !== 'string') {\n all.push(part.value);\n }\n else {\n all[all.length - 1] += part.value;\n }\n return all;\n }, []);\n if (result.length <= 1) {\n return result[0] || '';\n }\n return result;\n };\n this.formatToParts = function (values) {\n return formatToParts(_this.ast, _this.locales, _this.formatters, _this.formats, values, undefined, _this.message);\n };\n this.resolvedOptions = function () { return ({\n locale: Intl.NumberFormat.supportedLocalesOf(_this.locales)[0],\n }); };\n this.getAst = function () { return _this.ast; };\n if (typeof message === 'string') {\n this.message = message;\n if (!IntlMessageFormat.__parse) {\n throw new TypeError('IntlMessageFormat.__parse must be set to process `message` of type `string`');\n }\n // Parse string messages into an AST.\n this.ast = IntlMessageFormat.__parse(message, {\n ignoreTag: opts === null || opts === void 0 ? void 0 : opts.ignoreTag,\n });\n }\n else {\n this.ast = message;\n }\n if (!Array.isArray(this.ast)) {\n throw new TypeError('A message must be provided as a String or AST.');\n }\n // Creates a new object with the specified `formats` merged with the default\n // formats.\n this.formats = mergeConfigs(IntlMessageFormat.formats, overrideFormats);\n // Defined first because it's used to build the format pattern.\n this.locales = locales;\n this.formatters =\n (opts && opts.formatters) || createDefaultFormatters(this.formatterCache);\n }\n Object.defineProperty(IntlMessageFormat, \"defaultLocale\", {\n get: function () {\n if (!IntlMessageFormat.memoizedDefaultLocale) {\n IntlMessageFormat.memoizedDefaultLocale =\n new Intl.NumberFormat().resolvedOptions().locale;\n }\n return IntlMessageFormat.memoizedDefaultLocale;\n },\n enumerable: false,\n configurable: true\n });\n IntlMessageFormat.memoizedDefaultLocale = null;\n IntlMessageFormat.__parse = parse;\n // Default format options used as the prototype of the `formats` provided to the\n // constructor. These are used when constructing the internal Intl.NumberFormat\n // and Intl.DateTimeFormat instances.\n IntlMessageFormat.formats = {\n number: {\n integer: {\n maximumFractionDigits: 0,\n },\n currency: {\n style: 'currency',\n },\n percent: {\n style: 'percent',\n },\n },\n date: {\n short: {\n month: 'numeric',\n day: 'numeric',\n year: '2-digit',\n },\n medium: {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n },\n long: {\n month: 'long',\n day: 'numeric',\n year: 'numeric',\n },\n full: {\n weekday: 'long',\n month: 'long',\n day: 'numeric',\n year: 'numeric',\n },\n },\n time: {\n short: {\n hour: 'numeric',\n minute: 'numeric',\n },\n medium: {\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n },\n long: {\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n timeZoneName: 'short',\n },\n full: {\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n timeZoneName: 'short',\n },\n },\n };\n return IntlMessageFormat;\n}());\nexport { IntlMessageFormat };\n","/*\nCopyright (c) 2014, Yahoo! Inc. All rights reserved.\nCopyrights licensed under the New BSD License.\nSee the accompanying LICENSE file for terms.\n*/\nimport { IntlMessageFormat } from './src/core';\nexport * from './src/formatters';\nexport * from './src/core';\nexport * from './src/error';\nexport default IntlMessageFormat;\n","import{writable as e,derived as n}from\"svelte/store\";import t from\"deepmerge\";import o from\"intl-messageformat\";const r={},i=(e,n,t)=>t?(n in r||(r[n]={}),e in r[n]||(r[n][e]=t),t):t,l=(e,n)=>{if(null==n)return;if(n in r&&e in r[n])return r[n][e];const t=E(n);for(let o=0;o0){const n=t.slice(e,t.length).join(\".\");if(n in o){o=o[n];break}}o=o[t[e]]}else o=void 0;return o}(function(e){return a[e]||null}(e),n)}function m(e,...n){delete r[e],s.update((o=>(o[e]=t.all([o[e]||{},...n]),o)))}const f=n([s],(([e])=>Object.keys(e)));s.subscribe((e=>a=e));const d={};function g(e){return d[e]}function w(e){return null!=e&&E(e).some((e=>{var n;return null===(n=g(e))||void 0===n?void 0:n.size}))}function h(e,n){return Promise.all(n.map((n=>(function(e,n){d[e].delete(n),0===d[e].size&&delete d[e]}(e,n),n().then((e=>e.default||e)))))).then((n=>m(e,...n)))}const p={};function b(e){if(!w(e))return e in p?p[e]:Promise.resolve();const n=function(e){return E(e).map((e=>{const n=g(e);return[e,n?[...n]:[]]})).filter((([,e])=>e.length>0))}(e);return p[e]=Promise.all(n.map((([e,n])=>h(e,n)))).then((()=>{if(w(e))return b(e);delete p[e]})),p[e]}function y(e,n){g(e)||function(e){d[e]=new Set}(e);const t=g(e);g(e).has(n)||(u(e)||s.update((n=>(n[e]={},n))),t.add(n))}\n/*! *****************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */function v(e,n){var t={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&n.indexOf(o)<0&&(t[o]=e[o]);if(null!=e&&\"function\"==typeof Object.getOwnPropertySymbols){var r=0;for(o=Object.getOwnPropertySymbols(e);rt.slice(0,n+1).join(\"-\"))).reverse()}function E(e,n=j().fallbackLocale){const t=x(e);return n?[...new Set([...t,...x(n)])]:t}function D(){return null!=L?L:void 0}T.subscribe((e=>{L=null!=e?e:void 0,\"undefined\"!=typeof window&&null!=e&&document.documentElement.setAttribute(\"lang\",e)}));const M=Object.assign(Object.assign({},T),{set:e=>{if(e&&function(e){if(null==e)return;const n=E(e);for(let e=0;ek.set(!0)),n):k.set(!0),b(e).then((()=>{T.set(e)})).finally((()=>{clearTimeout(t),k.set(!1)}))}return T.set(e)}}),P=(e,n)=>{const t=e.split(\"&\").find((e=>0===e.indexOf(`${n}=`)));return t?t.split(\"=\").pop():null},S=(e,n)=>{const t=n.exec(e);return t&&t[1]||null},N=e=>\"undefined\"==typeof window?null:S(window.location.hostname,e),A=e=>\"undefined\"==typeof window?null:S(window.location.pathname,e),I=()=>\"undefined\"==typeof window?null:window.navigator.language||window.navigator.languages[0],F=e=>\"undefined\"==typeof window?null:P(window.location.search.substr(1),e),z=e=>\"undefined\"==typeof window?null:P(window.location.hash.substr(1),e),Z=e=>{const n=Object.create(null);return t=>{const o=JSON.stringify(t);return o in n?n[o]:n[o]=e(t)}},C=(e,n)=>{const{formats:t}=j();if(e in t&&n in t[e])return t[e][n];throw new Error(`[svelte-i18n] Unknown \"${n}\" ${e} format.`)},G=Z((e=>{var{locale:n,format:t}=e,o=v(e,[\"locale\",\"format\"]);if(null==n)throw new Error('[svelte-i18n] A \"locale\" must be set to format numbers');return t&&(o=C(\"number\",t)),new Intl.NumberFormat(n,o)})),J=Z((e=>{var{locale:n,format:t}=e,o=v(e,[\"locale\",\"format\"]);if(null==n)throw new Error('[svelte-i18n] A \"locale\" must be set to format dates');return t?o=C(\"date\",t):0===Object.keys(o).length&&(o=C(\"date\",\"short\")),new Intl.DateTimeFormat(n,o)})),U=Z((e=>{var{locale:n,format:t}=e,o=v(e,[\"locale\",\"format\"]);if(null==n)throw new Error('[svelte-i18n] A \"locale\" must be set to format time values');return t?o=C(\"time\",t):0===Object.keys(o).length&&(o=C(\"time\",\"short\")),new Intl.DateTimeFormat(n,o)})),_=(e={})=>{var{locale:n=D()}=e,t=v(e,[\"locale\"]);return G(Object.assign({locale:n},t))},q=(e={})=>{var{locale:n=D()}=e,t=v(e,[\"locale\"]);return J(Object.assign({locale:n},t))},B=(e={})=>{var{locale:n=D()}=e,t=v(e,[\"locale\"]);return U(Object.assign({locale:n},t))},H=Z(((e,n=D())=>new o(e,n,j().formats,{ignoreTag:j().ignoreTag}))),K=(e,n={})=>{let t=n;\"object\"==typeof e&&(t=e,e=t.id);const{values:o,locale:r=D(),default:i}=t;if(null==r)throw new Error(\"[svelte-i18n] Cannot format a message without first setting the initial locale.\");let a=l(e,r);if(a){if(\"string\"!=typeof a)return console.warn(`[svelte-i18n] Message with id \"${e}\" must be of type \"string\", found: \"${typeof a}\". Gettin its value through the \"$format\" method is deprecated; use the \"json\" method instead.`),a}else j().warnOnMissingMessages&&console.warn(`[svelte-i18n] The message \"${e}\" was not found in \"${E(r).join('\", \"')}\".${w(D())?\"\\n\\nNote: there are at least one loader still registered to this locale that wasn't executed.\":\"\"}`),a=null!=i?i:e;if(!o)return a;let s=a;try{s=H(a,r).format(o)}catch(n){console.warn(`[svelte-i18n] Message \"${e}\" has syntax error:`,n.message)}return s},Q=(e,n)=>B(n).format(e),R=(e,n)=>q(n).format(e),V=(e,n)=>_(n).format(e),W=(e,n=D())=>l(e,n),X=n([M,s],(()=>K)),Y=n([M],(()=>Q)),ee=n([M],(()=>R)),ne=n([M],(()=>V)),te=n([M,s],(()=>W));function oe(e){return e}function re(e){return b(e||D()||j().initialLocale)}export{X as _,m as addMessages,ee as date,oe as defineMessages,s as dictionary,X as format,q as getDateFormatter,z as getLocaleFromHash,N as getLocaleFromHostname,I as getLocaleFromNavigator,A as getLocaleFromPathname,F as getLocaleFromQueryString,H as getMessageFormatter,_ as getNumberFormatter,B as getTimeFormatter,$ as init,k as isLoading,te as json,M as locale,f as locales,ne as number,y as register,X as t,Y as time,re as waitLocale};\n","export const component_map = {\n\taccordion: () => import(\"./Accordion\"),\n\taudio: () => import(\"./Audio\"),\n\tbox: () => import(\"./Box\"),\n\tbutton: () => import(\"./Button\"),\n\tchatbot: () => import(\"./Chatbot\"),\n\tcheckbox: () => import(\"./Checkbox\"),\n\tcheckboxgroup: () => import(\"./CheckboxGroup\"),\n\tcode: () => import(\"./Code\"),\n\tcolorpicker: () => import(\"./ColorPicker\"),\n\tcolumn: () => import(\"./Column\"),\n\tdataframe: () => import(\"./DataFrame\"),\n\tdataset: () => import(\"./Dataset\"),\n\tdropdown: () => import(\"./Dropdown\"),\n\tfile: () => import(\"./File\"),\n\tform: () => import(\"./Form\"),\n\tgallery: () => import(\"./Gallery\"),\n\tgroup: () => import(\"./Group\"),\n\thighlightedtext: () => import(\"./HighlightedText\"),\n\thtml: () => import(\"./HTML\"),\n\timage: () => import(\"./Image\"),\n\tinterpretation: () => import(\"./Interpretation\"),\n\tjson: () => import(\"./Json\"),\n\tlabel: () => import(\"./Label\"),\n\tmarkdown: () => import(\"./Markdown\"),\n\tmodel3d: () => import(\"./Model3D\"),\n\tnumber: () => import(\"./Number\"),\n\tplot: () => import(\"./Plot\"),\n\tradio: () => import(\"./Radio\"),\n\trow: () => import(\"./Row\"),\n\tslider: () => import(\"./Slider\"),\n\tstate: () => import(\"./State\"),\n\tstatustracker: () => import(\"./StatusTracker\"),\n\ttabs: () => import(\"./Tabs\"),\n\ttabitem: () => import(\"./TabItem\"),\n\ttextbox: () => import(\"./Textbox\"),\n\ttimeseries: () => import(\"./TimeSeries\"),\n\tuploadbutton: () => import(\"./UploadButton\"),\n\tvideo: () => import(\"./Video\")\n};\n","/// \n\nimport { addMessages, init, getLocaleFromNavigator } from \"svelte-i18n\";\n\nconst langs = import.meta.globEager(\"./lang/*.json\");\n\nexport function process_langs() {\n\tlet _langs: Record<\n\t\tstring,\n\t\t{\n\t\t\t[key: string]: any;\n\t\t}\n\t> = {};\n\n\tfor (const lang in langs) {\n\t\tconst code = (lang.split(\"/\").pop() as string).split(\".\").shift() as string;\n\t\t_langs[code] = langs[lang].default;\n\t}\n\n\treturn _langs;\n}\n\nconst processed_langs = process_langs();\n\nfor (const lang in processed_langs) {\n\taddMessages(lang, processed_langs[lang]);\n}\n\nexport function setupi18n() {\n\tinit({\n\t\tfallbackLocale: \"en\",\n\t\tinitialLocale: getLocaleFromNavigator()\n\t});\n}\n","\n\n\n\t{#if children && children.length}\n\t\t{#each children as { component, id: each_id, props, children: _children, has_modes } (each_id)}\n\t\t\t\n\t\t{/each}\n\t{/if}\n\n","\n","\n\n
\n\t
API Docs
\n\t
\n\t\tNo named API Routes found for\n\t\t\n\t\t\t{root}\n\t\t\n\t
\n\t
\n\t\tTo expose an API endpoint of your app in this page, set the \n\t\t\tapi_name\n\t\t\n\t\tparameter of the event listener.\n\t\t \n\t\tFor more information, visit the\n\t\t\n\t\t\tAPI Page guide\n\t\t\n\t\t. To hide the API documentation button and this page, set\n\t\tshow_api=False\n\t\tin the\n\t\tBlocks.launch()\n\t\tmethod.\n\t
\n
\n\n\n\n\n","export function represent_value(\n\tvalue: string,\n\ttype: string | undefined,\n\tlang: \"js\" | \"py\" | null = null\n) {\n\tif (type === undefined) {\n\t\treturn lang === \"py\" ? \"None\" : null;\n\t}\n\tif (type === \"string\") {\n\t\treturn lang === null ? value : '\"' + value + '\"';\n\t} else if (type === \"number\") {\n\t\treturn lang === null ? parseFloat(value) : value;\n\t} else if (type === \"boolean\") {\n\t\tif (lang === \"py\") {\n\t\t\treturn value === \"true\" ? \"True\" : \"False\";\n\t\t} else if (lang === \"js\") {\n\t\t\treturn value;\n\t\t} else {\n\t\t\treturn value === \"true\";\n\t\t}\n\t} else {\n\t\t// assume object type\n\t\tif (lang === null) {\n\t\t\treturn value === \"\" ? null : JSON.parse(value);\n\t\t} else if (typeof value === \"string\") {\n\t\t\tif (value === \"\") {\n\t\t\t\treturn lang === \"py\" ? \"None\" : \"null\";\n\t\t\t}\n\t\t\treturn value;\n\t\t} else {\n\t\t\treturn JSON.stringify(value);\n\t\t}\n\t}\n}\n","export default \"__VITE_ASSET__5346f193__\"","\n\n
\n\t\n\tAPI documentation for \n\t\n\t\t{root}\n\t\n
\n{#if active_api_count > 1}\n\t
\n\t\t{active_api_count} API endpoints:\n\t
\n{/if}\n\n\n\n\n","\n\n
\n\tPOST\n\t/run/{api_name}\n
\n
\n\t
\n\t\t{root}run/{api_name}\n\t\t\n\t
\n
\n\n\n","\n\n
\n\t
\n\t\t\n\t
\n\tInput Payload\n
\n\n\t
\n\t\t{\n\t\t
\"data\": [
\n\t\t{#each dependency.inputs as component_id, component_index}\n\t\t\t
\n{/if}\n\n\n"],"file":"assets/Blocks.1c8a32b7.js"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/ColorPicker.svelte_svelte_type_style_lang.adee3b52.css b/gradio/templates/cdn/assets/ColorPicker.svelte_svelte_type_style_lang.adee3b52.css
new file mode 100644
index 0000000000000000000000000000000000000000..e51e137574fa640199388db40f7111760b175f10
--- /dev/null
+++ b/gradio/templates/cdn/assets/ColorPicker.svelte_svelte_type_style_lang.adee3b52.css
@@ -0,0 +1 @@
+label.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70{display:flex;align-items:center;cursor:pointer;color:var(--body-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}label.svelte-1ojmf70>.svelte-1ojmf70+.svelte-1ojmf70{margin-left:var(--size-2)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70{--ring-color:transparent;position:relative;box-shadow:var(--input-shadow);border:1px solid var(--checkbox-border-color);border-radius:var(--checkbox-border-radius);background-color:var(--checkbox-background-color);line-height:var(--line-sm)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:checked,input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:checked:hover,input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:checked:focus{border-color:var(--checkbox-border-color-selected);background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:hover{border-color:var(--checkbox-border-color-hover);background-color:var(--checkbox-background-color-hover)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:focus{border-color:var(--checkbox-border-color-focus);background-color:var(--checkbox-background-color-focus)}input[disabled].svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70,.disabled.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70{cursor:not-allowed}.wrap.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{display:flex;flex-wrap:wrap;gap:var(--checkbox-label-gap)}label.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{display:flex;align-items:center;transition:var(--button-transition);cursor:pointer;box-shadow:var(--checkbox-label-shadow);border:var(--checkbox-label-border-width) solid var(--checkbox-label-border-color);border-radius:var(--button-small-radius);background:var(--checkbox-label-background-fill);padding:var(--checkbox-label-padding);color:var(--checkbox-label-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}label.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:hover{background:var(--checkbox-label-background-fill-hover)}label.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:focus{background:var(--checkbox-label-background-fill-focus)}label.selected.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{background:var(--checkbox-label-background-fill-selected);color:var(--checkbox-label-text-color-selected)}label.svelte-1qxcj04>.svelte-1qxcj04+.svelte-1qxcj04{margin-left:var(--size-2)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{--ring-color:transparent;position:relative;box-shadow:var(--checkbox-shadow);border:var(--checkbox-border-width) solid var(--checkbox-border-color);border-radius:var(--checkbox-border-radius);background-color:var(--checkbox-background-color);line-height:var(--line-sm)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:checked,input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:checked:hover,input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:checked:focus{border-color:var(--checkbox-border-color-selected);background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:hover{border-color:var(--checkbox-border-color-hover);background-color:var(--checkbox-background-color-hover)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:focus{border-color:var(--checkbox-border-color-focus);background-color:var(--checkbox-background-color-focus)}input[disabled].svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04,.disabled.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{cursor:not-allowed}.options.svelte-1oas11n{--window-padding:var(--size-8);position:absolute;z-index:var(--layer-5);margin-left:0;box-shadow:var(--shadow-drop-lg);border-radius:var(--container-radius);background:var(--background-fill-primary);width:var(--size-full);overflow:auto;color:var(--body-text-color);list-style:none}.item.svelte-1oas11n{display:flex;cursor:pointer;padding:var(--size-2)}.item.svelte-1oas11n:hover,.active.svelte-1oas11n{background:var(--background-fill-secondary)}.inner-item.svelte-1oas11n{padding-right:var(--size-1)}.hide.svelte-1oas11n{visibility:hidden}.wrap.svelte-a6vu2r.svelte-a6vu2r.svelte-a6vu2r{position:relative;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--border-color-primary);border-radius:var(--input-radius);background:var(--input-background-fill)}.wrap.svelte-a6vu2r.svelte-a6vu2r.svelte-a6vu2r:focus-within{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}.wrap-inner.svelte-a6vu2r.svelte-a6vu2r.svelte-a6vu2r{display:flex;position:relative;flex-wrap:wrap;align-items:center;gap:var(--checkbox-label-gap);padding:var(--checkbox-label-gap)}.token.svelte-a6vu2r.svelte-a6vu2r.svelte-a6vu2r{display:flex;align-items:center;transition:var(--button-transition);cursor:pointer;box-shadow:var(--checkbox-label-shadow);border:var(--checkbox-label-border-width) solid var(--checkbox-label-border-color);border-radius:var(--button-small-radius);background:var(--checkbox-label-background-fill);padding:var(--checkbox-label-padding);color:var(--checkbox-label-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}.token.svelte-a6vu2r>.svelte-a6vu2r+.svelte-a6vu2r{margin-left:var(--size-2)}.token-remove.svelte-a6vu2r.svelte-a6vu2r.svelte-a6vu2r{fill:var(--body-text-color);display:flex;justify-content:center;align-items:center;cursor:pointer;border:var(--checkbox-border-width) solid var(--border-color-primary);border-radius:var(--radius-full);background:var(--background-fill-primary);padding:var(--size-0-5);width:18px;height:18px}.single-select.svelte-a6vu2r.svelte-a6vu2r.svelte-a6vu2r{margin:var(--spacing-sm);color:var(--body-text-color)}.secondary-wrap.svelte-a6vu2r.svelte-a6vu2r.svelte-a6vu2r{display:flex;flex:1 1 0%;align-items:center;border:none;min-width:min-content}input.svelte-a6vu2r.svelte-a6vu2r.svelte-a6vu2r{margin:var(--spacing-sm);outline:none;border:none;background:inherit;width:var(--size-full);color:var(--body-text-color);font-size:var(--input-text-size)}input.svelte-a6vu2r.svelte-a6vu2r.svelte-a6vu2r:disabled{cursor:not-allowed}.remove-all.svelte-a6vu2r.svelte-a6vu2r.svelte-a6vu2r{margin-left:var(--size-1);width:20px;height:20px}input[type=number].svelte-1nnxs9b{display:block;position:relative;outline:none!important;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--input-radius);background:var(--input-background-fill);padding:var(--input-padding);width:100%;color:var(--body-text-color);font-size:var(--input-text-size);line-height:var(--line-sm)}input.svelte-1nnxs9b:focus{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}input.svelte-1nnxs9b::placeholder{color:var(--input-placeholder-color)}.wrap.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{display:flex;flex-wrap:wrap;gap:var(--checkbox-label-gap)}label.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{display:flex;align-items:center;transition:var(--button-transition);cursor:pointer;box-shadow:var(--checkbox-label-shadow);border:var(--checkbox-label-border-width) solid var(--checkbox-label-border-color);border-radius:var(--button-small-radius);background:var(--checkbox-label-background-fill);padding:var(--checkbox-label-padding);color:var(--checkbox-label-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}label.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:hover{background:var(--checkbox-label-background-fill-hover)}label.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:focus{background:var(--checkbox-label-background-fill-focus)}label.selected.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{background:var(--checkbox-label-background-fill-selected);color:var(--checkbox-label-text-color-selected)}label.svelte-1p9xokt>.svelte-1p9xokt+.svelte-1p9xokt{margin-left:var(--size-2)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{--ring-color:transparent;position:relative;box-shadow:var(--checkbox-shadow);border:var(--checkbox-border-width) solid var(--checkbox-border-color);border-radius:var(--radius-full);background-color:var(--checkbox-background-color);line-height:var(--line-sm)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:checked,input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:checked:hover,input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:checked:focus{border-color:var(--checkbox-border-color-selected);background-image:var(--radio-circle);background-color:var(--checkbox-background-color-selected)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:hover{border-color:var(--checkbox-border-color-hover);background-color:var(--checkbox-background-color-hover)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:focus{border-color:var(--checkbox-border-color-focus);background-color:var(--checkbox-background-color-focus)}input[disabled].svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt,.disabled.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{cursor:not-allowed}label.svelte-4xt1ch{display:block;width:100%}input[type=text].svelte-4xt1ch,input[type=password].svelte-4xt1ch,input[type=email].svelte-4xt1ch,textarea.svelte-4xt1ch{display:block;position:relative;outline:none!important;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--input-radius);background:var(--input-background-fill);padding:var(--input-padding);width:100%;color:var(--body-text-color);font-weight:var(--input-text-weight);font-size:var(--input-text-size);line-height:var(--line-sm)}input.svelte-4xt1ch:focus,textarea.svelte-4xt1ch:focus{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}input.svelte-4xt1ch::placeholder,textarea.svelte-4xt1ch::placeholder{color:var(--input-placeholder-color)}button.svelte-4xt1ch{display:flex;position:absolute;top:var(--block-label-margin);right:var(--block-label-margin);align-items:center;box-shadow:var(--shadow-drop);border:1px solid var(--color-border-primary);border-top:none;border-right:none;border-radius:var(--block-label-right-radius);background:var(--block-label-background-fill);padding:5px;width:22px;height:22px;overflow:hidden;color:var(--block-label-color);font:var(--font-sans);font-size:var(--button-small-text-size)}.wrap.svelte-jigama{display:flex;flex-direction:column;width:100%}.head.svelte-jigama{display:flex;justify-content:space-between}input[type=number].svelte-jigama{display:block;position:relative;outline:none!important;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--input-radius);background:var(--input-background-fill);padding:var(--size-2) var(--size-2);height:var(--size-6);color:var(--body-text-color);font-size:var(--input-text-size);line-height:var(--line-sm);text-align:center}input[type=number].svelte-jigama:focus{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}input.svelte-jigama::placeholder{color:var(--input-placeholder-color)}input[type=range].svelte-jigama{width:100%;accent-color:var(--slider-color)}input[disabled].svelte-jigama{cursor:not-allowed}input.svelte-56zyyb{display:block;position:relative;background:var(--background-fill-primary);line-height:var(--line-sm)}
diff --git a/gradio/templates/cdn/assets/Column.69198682.js b/gradio/templates/cdn/assets/Column.69198682.js
new file mode 100644
index 0000000000000000000000000000000000000000..02ad64f076f3d8f8597d7ca3dbf4c03002b127ca
--- /dev/null
+++ b/gradio/templates/cdn/assets/Column.69198682.js
@@ -0,0 +1,2 @@
+import{S as h,i as w,s as b,W as r,F as C,B as o,a8 as g,O as _,f as j,X as S,Y as q,Z as y,o as B,t as F,p as O}from"./index.7a68216a.js";/* empty css */function W(i){let e,n,m,f;const u=i[8].default,a=r(u,i,i[7],null);return{c(){e=C("div"),a&&a.c(),o(e,"id",i[2]),o(e,"class",n=g(i[3].join(" "))+" svelte-vt1mxs"),o(e,"style",m=`min-width: min(${i[1]}px, 100%); flex-grow: ${i[0]}`),_(e,"gap",i[6].gap!==!1),_(e,"compact",i[5]==="compact"),_(e,"panel",i[5]==="panel"),_(e,"hide",!i[4])},m(l,t){j(l,e,t),a&&a.m(e,null),f=!0},p(l,[t]){a&&a.p&&(!f||t&128)&&S(a,u,l,l[7],f?y(u,l[7],t,null):q(l[7]),null),(!f||t&4)&&o(e,"id",l[2]),(!f||t&8&&n!==(n=g(l[3].join(" "))+" svelte-vt1mxs"))&&o(e,"class",n),(!f||t&3&&m!==(m=`min-width: min(${l[1]}px, 100%); flex-grow: ${l[0]}`))&&o(e,"style",m),t&72&&_(e,"gap",l[6].gap!==!1),t&40&&_(e,"compact",l[5]==="compact"),t&40&&_(e,"panel",l[5]==="panel"),t&24&&_(e,"hide",!l[4])},i(l){f||(B(a,l),f=!0)},o(l){F(a,l),f=!1},d(l){l&&O(e),a&&a.d(l)}}}function X(i,e,n){let{$$slots:m={},$$scope:f}=e,{scale:u=1}=e,{min_width:a=0}=e,{elem_id:l=""}=e,{elem_classes:t=[]}=e,{visible:c=!0}=e,{variant:d="default"}=e,{style:v={}}=e;return i.$$set=s=>{"scale"in s&&n(0,u=s.scale),"min_width"in s&&n(1,a=s.min_width),"elem_id"in s&&n(2,l=s.elem_id),"elem_classes"in s&&n(3,t=s.elem_classes),"visible"in s&&n(4,c=s.visible),"variant"in s&&n(5,d=s.variant),"style"in s&&n(6,v=s.style),"$$scope"in s&&n(7,f=s.$$scope)},[u,a,l,t,c,d,v,f,m]}class k extends h{constructor(e){super(),w(this,e,X,W,b,{scale:0,min_width:1,elem_id:2,elem_classes:3,visible:4,variant:5,style:6})}}export{k as C};
+//# sourceMappingURL=Column.69198682.js.map
diff --git a/gradio/templates/cdn/assets/Column.69198682.js.map b/gradio/templates/cdn/assets/Column.69198682.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..9629364cf903bf81f57aa9b0f621e1f4d4b7781b
--- /dev/null
+++ b/gradio/templates/cdn/assets/Column.69198682.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"Column.69198682.js","sources":["../../../../ui/packages/app/src/components/Column/Column.svelte"],"sourcesContent":["\n\n
\n\t\n
\n\n\n"],"names":[],"mappings":"gTAcK,sBACG,KAAa,KAAK,GAAG,qDAKH,6BAAkC,kBAJhD,KAAM,MAAQ,EAAK,gBACf,OAAY,SAAS,cACvB,OAAY,OAAO,cACnB,cANd,8HACK,yBACG,KAAa,KAAK,GAAG,yEAKH,6BAAkC,yCAJhD,KAAM,MAAQ,EAAK,sBACf,OAAY,SAAS,oBACvB,OAAY,OAAO,oBACnB,0HAfF,QAAgB,MAChB,YAAoB,MACpB,UAAkB,OAClB,sBACA,UAAmB,OACnB,UAA2C,cAC3C"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/Column.svelte_svelte_type_style_lang.c4c23b6e.css b/gradio/templates/cdn/assets/Column.svelte_svelte_type_style_lang.c4c23b6e.css
new file mode 100644
index 0000000000000000000000000000000000000000..8657e4c7112cc9a8232f875b00f9cf9aaac5e9f6
--- /dev/null
+++ b/gradio/templates/cdn/assets/Column.svelte_svelte_type_style_lang.c4c23b6e.css
@@ -0,0 +1 @@
+div.svelte-vt1mxs{display:flex;position:relative;flex-direction:column}div.svelte-vt1mxs>*,div.svelte-vt1mxs>.form>*{width:var(--size-full)}.gap.svelte-vt1mxs{gap:var(--layout-gap)}.hide.svelte-vt1mxs{display:none}.compact.svelte-vt1mxs>*,.compact.svelte-vt1mxs .box{border-radius:0}.compact.svelte-vt1mxs,.panel.svelte-vt1mxs{border:solid var(--panel-border-width) var(--panel-border-color);border-radius:var(--container-radius);background:var(--panel-background-fill);padding:var(--spacing-lg)}
diff --git a/gradio/templates/cdn/assets/Copy.fa9f7398.js b/gradio/templates/cdn/assets/Copy.fa9f7398.js
new file mode 100644
index 0000000000000000000000000000000000000000..f376bcbf533e91bcc1fc2836266b1e7af740435a
--- /dev/null
+++ b/gradio/templates/cdn/assets/Copy.fa9f7398.js
@@ -0,0 +1,2 @@
+import{S as p,i as c,s as h,A as a,B as e,f as u,D as i,E as n,p as d}from"./index.7a68216a.js";function v(l){let t,s;return{c(){t=a("svg"),s=a("polyline"),e(s,"points","20 6 9 17 4 12"),e(t,"xmlns","http://www.w3.org/2000/svg"),e(t,"width","100%"),e(t,"height","100%"),e(t,"viewBox","0 0 24 24"),e(t,"fill","none"),e(t,"stroke","currentColor"),e(t,"stroke-width","3"),e(t,"stroke-linecap","round"),e(t,"stroke-linejoin","round")},m(o,r){u(o,t,r),i(t,s)},p:n,i:n,o:n,d(o){o&&d(t)}}}class m extends p{constructor(t){super(),c(this,t,null,v,h,{})}}function w(l){let t,s,o;return{c(){t=a("svg"),s=a("path"),o=a("path"),e(s,"fill","currentColor"),e(s,"d","M28 10v18H10V10h18m0-2H10a2 2 0 0 0-2 2v18a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2Z"),e(o,"fill","currentColor"),e(o,"d","M4 18H2V4a2 2 0 0 1 2-2h14v2H4Z"),e(t,"xmlns","http://www.w3.org/2000/svg"),e(t,"width","100%"),e(t,"height","100%"),e(t,"viewBox","0 0 32 32")},m(r,g){u(r,t,g),i(t,s),i(t,o)},p:n,i:n,o:n,d(r){r&&d(t)}}}class x extends p{constructor(t){super(),c(this,t,null,w,h,{})}}export{x as C,m as a};
+//# sourceMappingURL=Copy.fa9f7398.js.map
diff --git a/gradio/templates/cdn/assets/Copy.fa9f7398.js.map b/gradio/templates/cdn/assets/Copy.fa9f7398.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..256f189a178f23d3dbb275d5c9774674efe5634a
--- /dev/null
+++ b/gradio/templates/cdn/assets/Copy.fa9f7398.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"Copy.fa9f7398.js","sources":["../../../../ui/packages/icons/src/Check.svelte","../../../../ui/packages/icons/src/Copy.svelte"],"sourcesContent":["\n","\n"],"names":[],"mappings":"sbAAA,SASyB,ueCTzB,SAKE,OAGC"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/Download.e46fa6ff.js b/gradio/templates/cdn/assets/Download.e46fa6ff.js
new file mode 100644
index 0000000000000000000000000000000000000000..c45041597e2d27d80aa6303f3e0fa180280afd72
--- /dev/null
+++ b/gradio/templates/cdn/assets/Download.e46fa6ff.js
@@ -0,0 +1,2 @@
+import{S as i,i as p,s as v,A as o,B as e,f as h,D as c,E as n,p as m}from"./index.7a68216a.js";function d(l){let t,s;return{c(){t=o("svg"),s=o("path"),e(s,"fill","currentColor"),e(s,"d","M26 24v4H6v-4H4v4a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2v-4zm0-10l-1.41-1.41L17 20.17V2h-2v18.17l-7.59-7.58L6 14l10 10l10-10z"),e(t,"xmlns","http://www.w3.org/2000/svg"),e(t,"width","100%"),e(t,"height","100%"),e(t,"viewBox","0 0 32 32")},m(a,r){h(a,t,r),c(t,s)},p:n,i:n,o:n,d(a){a&&m(t)}}}class g extends i{constructor(t){super(),p(this,t,null,d,v,{})}}export{g as D};
+//# sourceMappingURL=Download.e46fa6ff.js.map
diff --git a/gradio/templates/cdn/assets/Download.e46fa6ff.js.map b/gradio/templates/cdn/assets/Download.e46fa6ff.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..60ba7e571681d747fc357ebee71194eacde16f00
--- /dev/null
+++ b/gradio/templates/cdn/assets/Download.e46fa6ff.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"Download.e46fa6ff.js","sources":["../../../../ui/packages/icons/src/Download.svelte"],"sourcesContent":["\n"],"names":[],"mappings":"0aAAA,SAKE"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css b/gradio/templates/cdn/assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css
new file mode 100644
index 0000000000000000000000000000000000000000..c47d6f6f010f0626b0036068fe41d683b37b2954
--- /dev/null
+++ b/gradio/templates/cdn/assets/DropdownArrow.svelte_svelte_type_style_lang.a71c0c1e.css
@@ -0,0 +1 @@
+.dropdown-arrow.svelte-p5edak{fill:var(--body-text-color);margin-right:var(--size-2);width:var(--size-5)}
diff --git a/gradio/templates/cdn/assets/Empty.092ff864.js b/gradio/templates/cdn/assets/Empty.092ff864.js
new file mode 100644
index 0000000000000000000000000000000000000000..5ee515709b38a4e5156fa3c590a900bce387fb94
--- /dev/null
+++ b/gradio/templates/cdn/assets/Empty.092ff864.js
@@ -0,0 +1,2 @@
+import{S as _,i as r,s as m,W as c,F as d,B as f,O as u,f as g,D as p,X as b,Y as v,Z as z,o as h,t as j,p as E}from"./index.7a68216a.js";import"./Empty.svelte_svelte_type_style_lang.d7a3af78.js";function S(t){let s,n,i;const o=t[3].default,a=c(o,t,t[2],null);return{c(){s=d("div"),n=d("div"),a&&a.c(),f(n,"class","icon svelte-1u5vjgs"),f(s,"class","empty svelte-1u5vjgs"),u(s,"small",t[0]==="small"),u(s,"large",t[0]==="large"),u(s,"unpadded_box",t[1])},m(e,l){g(e,s,l),p(s,n),a&&a.m(n,null),i=!0},p(e,[l]){a&&a.p&&(!i||l&4)&&b(a,o,e,e[2],i?z(o,e[2],l,null):v(e[2]),null),l&1&&u(s,"small",e[0]==="small"),l&1&&u(s,"large",e[0]==="large"),l&2&&u(s,"unpadded_box",e[1])},i(e){i||(h(a,e),i=!0)},o(e){j(a,e),i=!1},d(e){e&&E(s),a&&a.d(e)}}}function q(t,s,n){let{$$slots:i={},$$scope:o}=s,{size:a="small"}=s,{unpadded_box:e=!1}=s;return t.$$set=l=>{"size"in l&&n(0,a=l.size),"unpadded_box"in l&&n(1,e=l.unpadded_box),"$$scope"in l&&n(2,o=l.$$scope)},[a,e,o,i]}class D extends _{constructor(s){super(),r(this,s,q,S,m,{size:0,unpadded_box:1})}}export{D as E};
+//# sourceMappingURL=Empty.092ff864.js.map
diff --git a/gradio/templates/cdn/assets/Empty.092ff864.js.map b/gradio/templates/cdn/assets/Empty.092ff864.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..323384ca7fbcae30b3d721e019efa0e3892dbe9b
--- /dev/null
+++ b/gradio/templates/cdn/assets/Empty.092ff864.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"Empty.092ff864.js","sources":["../../../../ui/packages/atoms/src/Empty.svelte"],"sourcesContent":["\n\n
\n\t
\n\t\t\n\t
\n
\n\n\n"],"names":[],"mappings":"iYAOc,OAAS,OAAO,cAChB,OAAS,OAAO,mCAH9B,SAMC,uHAJa,OAAS,OAAO,mBAChB,OAAS,OAAO,oJAPlB,OAA0B,YAC1B,eAAe"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/Empty.svelte_svelte_type_style_lang.04656a45.css b/gradio/templates/cdn/assets/Empty.svelte_svelte_type_style_lang.04656a45.css
new file mode 100644
index 0000000000000000000000000000000000000000..7eccfe5b6ac9a0b65a64c4007b294d0f4df457cd
--- /dev/null
+++ b/gradio/templates/cdn/assets/Empty.svelte_svelte_type_style_lang.04656a45.css
@@ -0,0 +1 @@
+button.svelte-1ipelgc{display:inline-flex;justify-content:center;align-items:center;transition:var(--button-transition);box-shadow:var(--button-shadow);padding:var(--size-0-5) var(--size-2);text-align:center}button.svelte-1ipelgc:hover,button[disabled].svelte-1ipelgc{box-shadow:var(--button-shadow-hover)}button.svelte-1ipelgc:active{box-shadow:var(--button-shadow-active)}button[disabled].svelte-1ipelgc{opacity:.5;filter:grayscale(30%);cursor:not-allowed}.hide.svelte-1ipelgc{display:none}.primary.svelte-1ipelgc{border:var(--button-border-width) solid var(--button-primary-border-color);background:var(--button-primary-background-fill);color:var(--button-primary-text-color)}.primary.svelte-1ipelgc:hover,.primary[disabled].svelte-1ipelgc{border-color:var(--button-primary-border-color-hover);background:var(--button-primary-background-fill-hover);color:var(--button-primary-text-color-hover)}.secondary.svelte-1ipelgc{border:var(--button-border-width) solid var(--button-secondary-border-color);background:var(--button-secondary-background-fill);color:var(--button-secondary-text-color)}.secondary.svelte-1ipelgc:hover,.secondary[disabled].svelte-1ipelgc{border-color:var(--button-secondary-border-color-hover);background:var(--button-secondary-background-fill-hover);color:var(--button-secondary-text-color-hover)}.stop.svelte-1ipelgc{border:var(--button-border-width) solid var(--button-cancel-border-color);background:var(--button-cancel-background-fill);color:var(--button-cancel-text-color)}.stop.svelte-1ipelgc:hover,.stop[disabled].svelte-1ipelgc{border-color:var(--button-cancel-border-color-hover);background:var(--button-cancel-background-fill-hover);color:var(--button-cancel-text-color-hover)}.sm.svelte-1ipelgc{border-radius:var(--button-small-radius);padding:var(--button-small-padding);font-weight:var(--button-small-text-weight);font-size:var(--button-small-text-size)}.lg.svelte-1ipelgc{border-radius:var(--button-large-radius);padding:var(--button-large-padding);font-weight:var(--button-large-text-weight);font-size:var(--button-large-text-size)}.block.svelte-mppz8v{position:relative;margin:0;box-shadow:var(--block-shadow);border-width:var(--block-border-width);border-color:var(--block-border-color);border-radius:var(--block-radius);background:var(--block-background-fill);width:100%;line-height:var(--line-sm)}.block.border_focus.svelte-mppz8v{border-color:var(--color-accent)}.padded.svelte-mppz8v{padding:var(--block-padding)}.hidden.svelte-mppz8v{display:none}div.svelte-e8n7p6{margin-bottom:var(--spacing-lg);color:var(--block-info-text-color);font-weight:var(--block-info-text-weight);font-size:var(--block-info-text-size);line-height:var(--line-sm)}span.has-info.svelte-1gfkn6j{margin-bottom:var(--spacing-xs)}span.svelte-1gfkn6j:not(.has-info){margin-bottom:var(--spacing-lg)}span.svelte-1gfkn6j{display:inline-block;position:relative;z-index:var(--layer-4);border:solid var(--block-title-border-width) var(--block-title-border-color);border-radius:var(--block-title-radius);background:var(--block-title-background-fill);padding:var(--block-title-padding);color:var(--block-title-text-color);font-weight:var(--block-title-text-weight);font-size:var(--block-title-text-size);line-height:var(--line-sm)}.hide.svelte-1gfkn6j{margin:0;height:0}div.svelte-1frtwj3{display:inline-flex;align-items:center;z-index:var(--layer-2);box-shadow:var(--block-shadow);border:var(--block-label-border-width) solid var(--border-color-primary);border-top:none;border-left:none;border-radius:var(--block-label-radius);background:var(--block-label-background-fill);padding:var(--block-label-padding);pointer-events:none;color:var(--block-label-text-color);font-weight:var(--block-label-text-weight);font-size:var(--block-label-text-size);line-height:var(--line-sm)}div.float.svelte-1frtwj3{position:absolute;top:var(--block-label-margin);left:var(--block-label-margin)}div.svelte-1frtwj3:not(.float){position:static;margin-top:var(--block-label-margin);margin-left:var(--block-label-margin)}.hide.svelte-1frtwj3{height:0}span.svelte-1frtwj3{opacity:.8;margin-right:var(--size-2);width:calc(var(--block-label-text-size) - 1px);height:calc(var(--block-label-text-size) - 1px)}button.svelte-184m5ec{display:flex;justify-content:center;align-items:center;z-index:var(--layer-1);box-shadow:var(--shadow-drop);border:1px solid var(--button-secondary-border-color);border-radius:var(--radius-sm);background:var(--background-fill-primary);width:var(--size-5);height:var(--size-5);color:var(--block-label-text-color)}button.svelte-184m5ec:hover{border:1px solid var(--button-secondary-border-color-hover);color:var(--block-label-text-color)}div.svelte-184m5ec{width:60%;height:60%}.empty.svelte-1u5vjgs{display:flex;justify-content:center;align-items:center;height:var(--size-full)}.icon.svelte-1u5vjgs{opacity:.5;height:var(--size-5);color:var(--body-text-color)}.small.svelte-1u5vjgs{height:calc(var(--size-32) - 20px)}.large.svelte-1u5vjgs{height:calc(var(--size-64) - 20px)}.unpadded_box.small.svelte-1u5vjgs{min-height:var(--size-32)}.unpadded_box.large.svelte-1u5vjgs{min-height:var(--size-64)}
diff --git a/gradio/templates/cdn/assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js b/gradio/templates/cdn/assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js
new file mode 100644
index 0000000000000000000000000000000000000000..4cd0595caa5bffe822c536ea9627e01bcff0fe8e
--- /dev/null
+++ b/gradio/templates/cdn/assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js
@@ -0,0 +1,2 @@
+import{S as K,i as L,s as z,W as N,F as S,B as b,O as m,f as j,I as Z,X as Y,Y as F,Z as T,o as C,t as I,p as O,x as D,$ as E,C as y,g as G,e as H,a0 as J,v as M}from"./index.7a68216a.js";const P=(l,e)=>W[e](l[e]);function k(l,e){const t=e.reduce((n,s)=>(l[s]===void 0||!W[s]?n[s]=" ":n[s]=` ${P(l,s)} `,n),{});return t.styles=` ${Object.values(t).join(" ").replace(/\s+/g," ").trim()} `,t}const W={container(l){return l?"":"padding: 0; margin: 0; border-width: 0; box-shadow: none; overflow: visible; background: transparent;"},label_container(l){return l?"":"border-width: 0; box-shadow: none; overflow: visible; background: transparent;"},grid(l){let e=["","sm-","md-","lg-","xl-","2xl-"],t=Array.isArray(l)?l:[l];return[0,0,0,0,0,0].map((n,s)=>`--${e[s]}grid-cols: var(--grid-${t?.[s]||t?.[t?.length-1]});`).join(" ")},height(l){return l==="auto"?"height: auto;":""},full_width(l){return l?"width: var(--size-full); flex-grow: 1;":"flex-grow: 0; width: fit-content;"},equal_height(l){return l?"align-items: stretch;":"align-items: flex-start;"},visible(l){return l?"":"display:hidden;"},item_container(l){return l?"":"border-width:0;"}};function Q(l){let e,t,n,s,f;const _=l[9].default,d=N(_,l,l[8],null);return{c(){e=S("button"),d&&d.c(),b(e,"class",t=l[4]+" "+l[3]+" "+l[1].join(" ")+" svelte-1ipelgc"),b(e,"style",l[6]),b(e,"id",l[0]),e.disabled=l[5],m(e,"hide",!l[2])},m(a,i){j(a,e,i),d&&d.m(e,null),n=!0,s||(f=Z(e,"click",l[10]),s=!0)},p(a,[i]){d&&d.p&&(!n||i&256)&&Y(d,_,a,a[8],n?T(_,a[8],i,null):F(a[8]),null),(!n||i&26&&t!==(t=a[4]+" "+a[3]+" "+a[1].join(" ")+" svelte-1ipelgc"))&&b(e,"class",t),(!n||i&64)&&b(e,"style",a[6]),(!n||i&1)&&b(e,"id",a[0]),(!n||i&32)&&(e.disabled=a[5]),i&30&&m(e,"hide",!a[2])},i(a){n||(C(d,a),n=!0)},o(a){I(d,a),n=!1},d(a){a&&O(e),d&&d.d(a),s=!1,f()}}}function R(l,e,t){let n,{$$slots:s={},$$scope:f}=e,{style:_={}}=e,{elem_id:d=""}=e,{elem_classes:a=[]}=e,{visible:i=!0}=e,{variant:o="secondary"}=e,{size:v=_.size||"lg"}=e,{disabled:g=!1}=e;function c(r){D.call(this,l,r)}return l.$$set=r=>{"style"in r&&t(7,_=r.style),"elem_id"in r&&t(0,d=r.elem_id),"elem_classes"in r&&t(1,a=r.elem_classes),"visible"in r&&t(2,i=r.visible),"variant"in r&&t(3,o=r.variant),"size"in r&&t(4,v=r.size),"disabled"in r&&t(5,g=r.disabled),"$$scope"in r&&t(8,f=r.$$scope)},l.$$.update=()=>{l.$$.dirty&128&&t(6,{styles:n}=k(_,["full_width"]),n)},[d,a,i,o,v,g,n,_,f,s,c]}class p extends K{constructor(e){super(),L(this,e,R,Q,z,{style:7,elem_id:0,elem_classes:1,visible:2,variant:3,size:4,disabled:5})}}function B(l){let e,t,n,s;const f=l[16].default,_=N(f,l,l[15],null);let d=[{"data-testid":l[5]},{id:l[0]},{class:t="block "+l[1].join(" ")+" svelte-mppz8v"},{style:n=l[9]+" "+(l[8]||null)}],a={};for(let i=0;i{"style"in u&&t(11,d=u.style),"elem_id"in u&&t(0,a=u.elem_id),"elem_classes"in u&&t(1,i=u.elem_classes),"variant"in u&&t(2,o=u.variant),"border_mode"in u&&t(3,v=u.border_mode),"padding"in u&&t(4,g=u.padding),"type"in u&&t(12,c=u.type),"test_id"in u&&t(5,r=u.test_id),"disable"in u&&t(13,h=u.disable),"explicit_call"in u&&t(14,w=u.explicit_call),"visible"in u&&t(6,q=u.visible),"allow_overflow"in u&&t(7,A=u.allow_overflow),"$$scope"in u&&t(15,_=u.$$scope)},l.$$.update=()=>{l.$$.dirty&26624&&t(9,{styles:n}=w?k(d,[]):h?k({container:!1},["container"]):{styles:""},n),l.$$.dirty&2048&&t(8,s=(typeof d.height=="number"?`height: ${d.height}px; `:"")+(typeof d.width=="number"?`width: ${d.width}px;`:""))},[a,i,o,v,g,r,q,A,s,n,X,d,c,h,w,_,f]}class $ extends K{constructor(e){super(),L(this,e,V,U,z,{style:11,elem_id:0,elem_classes:1,variant:2,border_mode:3,padding:4,type:12,test_id:5,disable:13,explicit_call:14,visible:6,allow_overflow:7})}}export{p as B,$ as a,k as g};
+//# sourceMappingURL=Empty.svelte_svelte_type_style_lang.d7a3af78.js.map
diff --git a/gradio/templates/cdn/assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js.map b/gradio/templates/cdn/assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..678b4298389465d8fbcbf47c5b8c22fe0f995e6b
--- /dev/null
+++ b/gradio/templates/cdn/assets/Empty.svelte_svelte_type_style_lang.d7a3af78.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"Empty.svelte_svelte_type_style_lang.d7a3af78.js","sources":["../../../../ui/packages/utils/src/styles.ts","../../../../ui/packages/button/src/Button.svelte","../../../../ui/packages/atoms/src/Block.svelte"],"sourcesContent":["export interface Styles {\n\tcontainer?: boolean;\n\tgrid?: number | Array;\n\theight?: \"auto\" | string | number;\n\twidth?: \"auto\" | string | number;\n\tfull_width?: boolean;\n\tequal_height?: boolean;\n\tvisible?: boolean;\n\titem_container?: boolean;\n\tcolor_map?: Record;\n\tlabel_container?: boolean;\n\tgap?: boolean;\n\tsize?: \"sm\" | \"lg\";\n\tpreview?: boolean;\n\tshow_copy_button?: boolean;\n}\n\ntype PartialRecord = {\n\t[P in K]?: T;\n};\n\ntype ProcessedStyles = PartialRecord & {\n\tstyles: string;\n};\n\nconst get_style = (styles: Styles, key: T) => {\n\treturn style_handlers[key](styles[key]!);\n};\n\nexport function get_styles(\n\tstyles: Styles,\n\tallowed_styles: Array\n): ProcessedStyles {\n\tconst processed_styles = allowed_styles.reduce((acc, next) => {\n\t\tif (styles[next] === undefined || !style_handlers[next]) acc[next] = \" \";\n\t\telse {\n\t\t\tacc[next] = ` ${get_style(styles, next)} `;\n\t\t}\n\t\treturn acc;\n\t}, {} as ProcessedStyles);\n\n\tprocessed_styles.styles = ` ${Object.values(processed_styles)\n\t\t.join(\" \")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim()} `;\n\n\treturn processed_styles;\n}\n\ntype StyleHandlers = {\n\t[K in keyof Styles]: (style: Exclude) => string;\n};\n\nconst style_handlers: StyleHandlers = {\n\tcontainer(container_visible) {\n\t\treturn container_visible\n\t\t\t? \"\"\n\t\t\t: `padding: 0; margin: 0; border-width: 0; box-shadow: none; overflow: visible; background: transparent;`;\n\t},\n\tlabel_container(visible) {\n\t\treturn visible\n\t\t\t? \"\"\n\t\t\t: `border-width: 0; box-shadow: none; overflow: visible; background: transparent;`;\n\t},\n\tgrid(grid) {\n\t\tlet grid_map = [\"\", \"sm-\", \"md-\", \"lg-\", \"xl-\", \"2xl-\"];\n\t\tlet _grid = Array.isArray(grid) ? grid : [grid];\n\n\t\treturn [0, 0, 0, 0, 0, 0]\n\t\t\t.map(\n\t\t\t\t(_, i) =>\n\t\t\t\t\t`--${grid_map[i]}grid-cols: var(--grid-${\n\t\t\t\t\t\t_grid?.[i] || _grid?.[_grid?.length - 1]\n\t\t\t\t\t});`\n\t\t\t)\n\t\t\t.join(\" \");\n\t},\n\theight(height) {\n\t\treturn height === \"auto\" ? \"height: auto;\" : \"\";\n\t},\n\tfull_width(full_width) {\n\t\treturn full_width\n\t\t\t? \"width: var(--size-full); flex-grow: 1;\"\n\t\t\t: \"flex-grow: 0; width: fit-content;\";\n\t},\n\tequal_height(equal_height) {\n\t\treturn equal_height ? \"align-items: stretch;\" : \"align-items: flex-start;\";\n\t},\n\tvisible(visible) {\n\t\treturn visible ? \"\" : \"display:hidden;\";\n\t},\n\titem_container(visible) {\n\t\treturn visible ? \"\" : \"border-width:0;\";\n\t}\n} as const;\n\nexport const create_classes = (\n\tstyles: Record,\n\tprefix: string = \"\"\n): string => {\n\tlet classes: Array = [];\n\tlet target_styles: Record = {};\n\tif (prefix === \"\") {\n\t\ttarget_styles = styles;\n\t} else {\n\t\tfor (const prop in styles) {\n\t\t\tif (prop.startsWith(prefix + \"_\")) {\n\t\t\t\tconst propname = prop.substring(prop.indexOf(\"_\") + 1);\n\t\t\t\ttarget_styles[propname] = styles[prop];\n\t\t\t}\n\t\t}\n\t}\n\n\tif (target_styles.hasOwnProperty(\"margin\")) {\n\t\tif (!Array.isArray(target_styles.margin)) {\n\t\t\ttarget_styles.margin = !!target_styles.margin\n\t\t\t\t? [true, true, true, true]\n\t\t\t\t: [false, false, false, false];\n\t\t}\n\n\t\tlet margin_map = [\"t\", \"r\", \"b\", \"l\"];\n\n\t\t(target_styles.margin as boolean[]).forEach((margin, i) => {\n\t\t\tif (!margin) {\n\t\t\t\tclasses.push(`!m${margin_map[i]}-0`);\n\t\t\t}\n\t\t});\n\t}\n\n\tif (target_styles.hasOwnProperty(\"border\")) {\n\t\tif (!Array.isArray(target_styles.border)) {\n\t\t\ttarget_styles.border = !!target_styles.border\n\t\t\t\t? [true, true, true, true]\n\t\t\t\t: [false, false, false, false];\n\t\t}\n\n\t\tlet border_map = [\"t\", \"r\", \"b\", \"l\"];\n\n\t\t(target_styles.border as boolean[]).forEach((border, i) => {\n\t\t\tif (!border) {\n\t\t\t\tclasses.push(`!border-${border_map[i]}-0`);\n\t\t\t}\n\t\t});\n\t}\n\n\tswitch (target_styles.rounded) {\n\t\tcase true:\n\t\t\tclasses.push(\"!rounded-lg\");\n\t\t\tbreak;\n\t\tcase false:\n\t\t\tclasses.push(\"!rounded-none\");\n\t\t\tbreak;\n\t}\n\n\tswitch (target_styles.full_width) {\n\t\tcase true:\n\t\t\tclasses.push(\"w-full\");\n\t\t\tbreak;\n\t\tcase false:\n\t\t\tclasses.push(\"!grow-0\");\n\t\t\tbreak;\n\t}\n\n\tswitch (target_styles.text_color) {\n\t\tcase \"red\":\n\t\t\tclasses.push(\"!text-red-500\", \"dark:text-red-100\");\n\t\t\tbreak;\n\t\tcase \"yellow\":\n\t\t\tclasses.push(\"!text-yellow-500\", \"dark:text-yellow-100\");\n\t\t\tbreak;\n\t\tcase \"green\":\n\t\t\tclasses.push(\"!text-green-500\", \"dark:text-green-100\");\n\t\t\tbreak;\n\t\tcase \"blue\":\n\t\t\tclasses.push(\"!text-blue-500\", \"dark:text-blue-100\");\n\t\t\tbreak;\n\t\tcase \"purple\":\n\t\t\tclasses.push(\"!text-purple-500\", \"dark:text-purple-100\");\n\t\t\tbreak;\n\t\tcase \"black\":\n\t\t\tclasses.push(\"!text-gray-700\", \"dark:text-gray-50\");\n\t\t\tbreak;\n\t}\n\tswitch (target_styles.bg_color) {\n\t\tcase \"red\":\n\t\t\tclasses.push(\n\t\t\t\t\"!bg-red-100 !from-red-100 !to-red-200 !border-red-300\",\n\t\t\t\t\"dark:!bg-red-700 dark:!from-red-700 dark:!to-red-800 dark:!border-red-900\"\n\t\t\t);\n\t\t\tbreak;\n\t\tcase \"yellow\":\n\t\t\tclasses.push(\n\t\t\t\t\"!bg-yellow-100 !from-yellow-100 !to-yellow-200 !border-yellow-300\",\n\t\t\t\t\"dark:!bg-yellow-700 dark:!from-yellow-700 dark:!to-yellow-800 dark:!border-yellow-900\"\n\t\t\t);\n\t\t\tbreak;\n\t\tcase \"green\":\n\t\t\tclasses.push(\n\t\t\t\t\"!bg-green-100 !from-green-100 !to-green-200 !border-green-300\",\n\t\t\t\t\"dark:!bg-green-700 dark:!from-green-700 dark:!to-green-800 dark:!border-green-900 !text-gray-800\"\n\t\t\t);\n\t\t\tbreak;\n\t\tcase \"blue\":\n\t\t\tclasses.push(\n\t\t\t\t\"!bg-blue-100 !from-blue-100 !to-blue-200 !border-blue-300\",\n\t\t\t\t\"dark:!bg-blue-700 dark:!from-blue-700 dark:!to-blue-800 dark:!border-blue-900\"\n\t\t\t);\n\t\t\tbreak;\n\t\tcase \"purple\":\n\t\t\tclasses.push(\n\t\t\t\t\"!bg-purple-100 !from-purple-100 !to-purple-200 !border-purple-300\",\n\t\t\t\t\"dark:!bg-purple-700 dark:!from-purple-700 dark:!to-purple-800 dark:!border-purple-900\"\n\t\t\t);\n\t\t\tbreak;\n\t\tcase \"black\":\n\t\t\tclasses.push(\n\t\t\t\t\"!bg-gray-100 !from-gray-100 !to-gray-200 !border-gray-300\",\n\t\t\t\t\"dark:!bg-gray-700 dark:!from-gray-700 dark:!to-gray-800 dark:!border-gray-900\"\n\t\t\t);\n\t\tcase \"pink\":\n\t\t\tclasses.push(\n\t\t\t\t\"!bg-pink-100 !from-pink-100 !to-pink-200 !border-pink-300\",\n\t\t\t\t\"dark:!bg-pink-700 dark:!from-pink-700 dark:!to-pink-800 dark:!border-pink-900 !text-gray-800\"\n\t\t\t);\n\t\t\tbreak;\n\t}\n\treturn \" \" + classes.join(\" \");\n};\n","\n\n\n\n\n","\n\n\n\t\n\n\n\n"],"names":[],"mappings":"4LAyBA,KAAM,GAAY,CAAyB,EAAgB,IACnD,EAAe,GAAK,EAAO,EAAK,aAIvC,EACA,EACkB,MACZ,GAAmB,EAAe,OAAO,CAAC,EAAK,KAChD,EAAO,KAAU,QAAa,CAAC,EAAe,KAAW,GAAQ,MAEhE,GAAQ,IAAI,EAAU,EAAQ,CAAI,KAEhC,GACL,EAAqB,WAEP,OAAS,IAAI,OAAO,OAAO,CAAgB,EAC1D,KAAK,GAAG,EACR,QAAQ,OAAQ,GAAG,EACnB,UAEK,CACR,CAMA,KAAM,GAAgC,CACrC,UAAU,EAAmB,OACrB,GACJ,GACA,yGAEJ,gBAAgB,EAAS,OACjB,GACJ,GACA,kFAEJ,KAAK,EAAM,IACN,GAAW,CAAC,GAAI,MAAO,MAAO,MAAO,MAAO,MAAM,EAClD,EAAQ,MAAM,QAAQ,CAAI,EAAI,EAAO,CAAC,CAAI,QAEvC,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,CAAC,EACtB,IACA,CAAC,EAAG,IACH,KAAK,EAAS,2BACb,IAAQ,IAAM,IAAQ,GAAO,OAAS,MAEzC,EACC,KAAK,GAAG,GAEX,OAAO,EAAQ,OACP,KAAW,OAAS,gBAAkB,IAE9C,WAAW,EAAY,OACf,GACJ,yCACA,qCAEJ,aAAa,EAAc,OACnB,GAAe,wBAA0B,4BAEjD,QAAQ,EAAS,OACT,GAAU,GAAK,mBAEvB,eAAe,EAAS,OAChB,GAAU,GAAK,kBAExB,sHC5ES,SAAO,SAAU,KAAa,KAAK,GAAG,iCACvC,eACH,kCAHS,cAFd,2JAGS,SAAO,SAAU,KAAa,KAAK,GAAG,8DACvC,0BACH,sDAHS,sIAbF,eACA,UAAkB,OAClB,sBACA,UAAmB,OACnB,UAA4C,gBAC5C,OAAoB,EAAM,MAAQ,SAClC,WAAoB,iWAEzB,UAAW,EAAW,GAAQ,YAAY,4PC0BnC,UACT,wBAEU,KAAa,KAAK,GAAG,6BAG3B,SAAS,OAAc,oEAPzB,oCAGQ,OAAY,EAAK,eAEjB,yBACM,OAAgB,OAAO,qBAEvB,wBACJ,KAAiB,UAAY,qBAV9C,mJAEc,qBACT,gCAEU,KAAa,KAAK,GAAG,mDAG3B,SAAS,OAAc,mCAJjB,OAAY,EAAK,eAEjB,yBACM,OAAgB,OAAO,0BAEvB,+BACJ,KAAiB,UAAY,oGATvC,YAAA,kFAAA,YAAA,kHAAA,2HA/BK,eACA,UAAkB,OAClB,sBACA,UAAuC,YACvC,cAAgC,WAChC,UAAmB,OACnB,OAA8B,aAC9B,UAA8B,WAC9B,UAAmB,OACnB,gBAAyB,OACzB,UAAU,OACV,iBAAiB,MAExB,EAAM,IAAS,WAAa,WAAa,MAE9B,SAA0B,WAAW,8fAI9C,UAAW,EACd,EAAW,MACX,EACA,GAAa,UAAW,KAAU,WAAW,IAC3C,OAAQ,4BACV,EACF,OACQ,GAAM,QAAW,oBAAsB,EAAM,aAAe,WAC5D,GAAM,OAAU,mBAAqB,EAAM,WAAa"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/File.7698c472.js b/gradio/templates/cdn/assets/File.7698c472.js
new file mode 100644
index 0000000000000000000000000000000000000000..21f546f98c4524582dab186e32b8a2a7b07574b2
--- /dev/null
+++ b/gradio/templates/cdn/assets/File.7698c472.js
@@ -0,0 +1,2 @@
+import{S as h,i as c,s as f,A as o,B as t,f as d,D as i,E as r,p as u}from"./index.7a68216a.js";function g(l){let e,s,a;return{c(){e=o("svg"),s=o("path"),a=o("polyline"),t(s,"d","M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"),t(a,"points","13 2 13 9 20 9"),t(e,"xmlns","http://www.w3.org/2000/svg"),t(e,"width","100%"),t(e,"height","100%"),t(e,"viewBox","0 0 24 24"),t(e,"fill","none"),t(e,"stroke","currentColor"),t(e,"stroke-width","1.5"),t(e,"stroke-linecap","round"),t(e,"stroke-linejoin","round"),t(e,"class","feather feather-file")},m(n,p){d(n,e,p),i(e,s),i(e,a)},p:r,i:r,o:r,d(n){n&&u(e)}}}class v extends h{constructor(e){super(),c(this,e,null,g,f,{})}}export{v as F};
+//# sourceMappingURL=File.7698c472.js.map
diff --git a/gradio/templates/cdn/assets/File.7698c472.js.map b/gradio/templates/cdn/assets/File.7698c472.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..fcfd71cef5f77120d75cf186cfce2c00cc0d0b6f
--- /dev/null
+++ b/gradio/templates/cdn/assets/File.7698c472.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"File.7698c472.js","sources":["../../../../ui/packages/icons/src/File.svelte"],"sourcesContent":["\n"],"names":[],"mappings":"gjBAAA,SAYC,OACA"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/Form.0a7d9dad.css b/gradio/templates/cdn/assets/Form.0a7d9dad.css
new file mode 100644
index 0000000000000000000000000000000000000000..4f21cff8eebea060d05e431443a878eec064de57
--- /dev/null
+++ b/gradio/templates/cdn/assets/Form.0a7d9dad.css
@@ -0,0 +1 @@
+div.svelte-awbtu4{display:flex;flex-direction:inherit;flex-wrap:wrap;gap:var(--form-gap-width);box-shadow:var(--block-shadow);border:var(--block-border-width) solid var(--border-color-primary);border-radius:var(--radius-lg);background:var(--border-color-primary);overflow:hidden}div.svelte-awbtu4 .block{box-shadow:none!important;border-width:0px!important;border-radius:0!important}.hidden.svelte-awbtu4{display:none}
diff --git a/gradio/templates/cdn/assets/Form.c11fdf11.js b/gradio/templates/cdn/assets/Form.c11fdf11.js
new file mode 100644
index 0000000000000000000000000000000000000000..6b92c12cecb7f0775e47c6f35710ae7d88b01b4c
--- /dev/null
+++ b/gradio/templates/cdn/assets/Form.c11fdf11.js
@@ -0,0 +1,2 @@
+import{S as r,i as _,s as f,W as u,F as c,B as m,O as o,f as d,X as v,Y as b,Z as g,o as p,t as h,p as F}from"./index.7a68216a.js";function S(i){let t,a;const n=i[2].default,s=u(n,i,i[1],null);return{c(){t=c("div"),s&&s.c(),m(t,"class","form svelte-awbtu4"),o(t,"hidden",!i[0])},m(e,l){d(e,t,l),s&&s.m(t,null),a=!0},p(e,[l]){s&&s.p&&(!a||l&2)&&v(s,n,e,e[1],a?g(n,e[1],l,null):b(e[1]),null),l&1&&o(t,"hidden",!e[0])},i(e){a||(p(s,e),a=!0)},o(e){h(s,e),a=!1},d(e){e&&F(t),s&&s.d(e)}}}function q(i,t,a){let{$$slots:n={},$$scope:s}=t,{visible:e=!0}=t;return i.$$set=l=>{"visible"in l&&a(0,e=l.visible),"$$scope"in l&&a(1,s=l.$$scope)},[e,s,n]}class y extends r{constructor(t){super(),_(this,t,q,S,f,{visible:0})}}export{y as F};
+//# sourceMappingURL=Form.c11fdf11.js.map
diff --git a/gradio/templates/cdn/assets/Form.c11fdf11.js.map b/gradio/templates/cdn/assets/Form.c11fdf11.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..b2633c6c86c7a053193b4726ac7c6c1cfe573d16
--- /dev/null
+++ b/gradio/templates/cdn/assets/Form.c11fdf11.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"Form.c11fdf11.js","sources":["../../../../ui/packages/app/src/components/Form/Form.svelte"],"sourcesContent":["\n\n
\n\t\n
\n\n\n"],"names":[],"mappings":"gRAIiC,cAAjC,2HAAiC,0HAHrB,UAAU"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/Image.2e852803.js b/gradio/templates/cdn/assets/Image.2e852803.js
new file mode 100644
index 0000000000000000000000000000000000000000..77c6a6059b204962f66667198d03302aab102ca0
--- /dev/null
+++ b/gradio/templates/cdn/assets/Image.2e852803.js
@@ -0,0 +1,2 @@
+import{S as g,i as u,s as v,F as d,K as _,B as r,O as n,f as y,E as c,p as b}from"./index.7a68216a.js";function o(t){let e,a;return{c(){e=d("img"),_(e.src,a=t[1]+t[0])||r(e,"src",a),r(e,"class","svelte-gqt00k"),n(e,"table",t[2]==="table"),n(e,"gallery",t[2]==="gallery"),n(e,"selected",t[3])},m(l,s){y(l,e,s)},p(l,[s]){s&3&&!_(e.src,a=l[1]+l[0])&&r(e,"src",a),s&4&&n(e,"table",l[2]==="table"),s&4&&n(e,"gallery",l[2]==="gallery"),s&8&&n(e,"selected",l[3])},i:c,o:c,d(l){l&&b(e)}}}function q(t,e,a){let{value:l}=e,{samples_dir:s}=e,{type:f}=e,{selected:m=!1}=e;return t.$$set=i=>{"value"in i&&a(0,l=i.value),"samples_dir"in i&&a(1,s=i.samples_dir),"type"in i&&a(2,f=i.type),"selected"in i&&a(3,m=i.selected)},[l,s,f,m]}class E extends g{constructor(e){super(),u(this,e,q,o,v,{value:0,samples_dir:1,type:2,selected:3})}}var h=E;export{h as E};
+//# sourceMappingURL=Image.2e852803.js.map
diff --git a/gradio/templates/cdn/assets/Image.2e852803.js.map b/gradio/templates/cdn/assets/Image.2e852803.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..a271307cddce1b6966f4a091b3aa130a8eea712b
--- /dev/null
+++ b/gradio/templates/cdn/assets/Image.2e852803.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"Image.2e852803.js","sources":["../../../../ui/packages/app/src/components/Dataset/ExampleComponents/Image.svelte"],"sourcesContent":["\n\n\n\n\n\n"],"names":[],"mappings":"6JASM,KAAc,6DACN,OAAS,OAAO,gBACd,OAAS,SAAS,+BAHlC,mCACM,KAAc,qCACN,OAAS,OAAO,qBACd,OAAS,SAAS,0EAVtB,YACA,kBACA,WACA,WAAoB"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/Image.3a14ca24.css b/gradio/templates/cdn/assets/Image.3a14ca24.css
new file mode 100644
index 0000000000000000000000000000000000000000..60f45635043d082881d8d8a529c1142ee028a68b
--- /dev/null
+++ b/gradio/templates/cdn/assets/Image.3a14ca24.css
@@ -0,0 +1 @@
+img.svelte-gqt00k{border-radius:var(--radius-lg);max-width:none}img.selected.svelte-gqt00k{border-color:var(--border-color-accent)}.table.svelte-gqt00k{margin:0 auto;border:2px solid var(--border-color-primary);border-radius:var(--radius-lg);width:var(--size-20);height:var(--size-20);object-fit:cover}.gallery.svelte-gqt00k{border:2px solid var(--border-color-primary);max-height:var(--size-20);object-fit:cover}
diff --git a/gradio/templates/cdn/assets/Image.f3d382f6.js b/gradio/templates/cdn/assets/Image.f3d382f6.js
new file mode 100644
index 0000000000000000000000000000000000000000..fa702e32f0c5016aad53e1000fbd3802c3a4a075
--- /dev/null
+++ b/gradio/templates/cdn/assets/Image.f3d382f6.js
@@ -0,0 +1,2 @@
+import{S as h,i as g,s as d,A as n,B as e,f,D as a,E as l,p as m}from"./index.7a68216a.js";function u(c){let t,r,s,o;return{c(){t=n("svg"),r=n("rect"),s=n("circle"),o=n("polyline"),e(r,"x","3"),e(r,"y","3"),e(r,"width","18"),e(r,"height","18"),e(r,"rx","2"),e(r,"ry","2"),e(s,"cx","8.5"),e(s,"cy","8.5"),e(s,"r","1.5"),e(o,"points","21 15 16 10 5 21"),e(t,"xmlns","http://www.w3.org/2000/svg"),e(t,"width","100%"),e(t,"height","100%"),e(t,"viewBox","0 0 24 24"),e(t,"fill","none"),e(t,"stroke","currentColor"),e(t,"stroke-width","1.5"),e(t,"stroke-linecap","round"),e(t,"stroke-linejoin","round"),e(t,"class","feather feather-image")},m(i,p){f(i,t,p),a(t,r),a(t,s),a(t,o)},p:l,i:l,o:l,d(i){i&&m(t)}}}class x extends h{constructor(t){super(),g(this,t,null,u,d,{})}}export{x as I};
+//# sourceMappingURL=Image.f3d382f6.js.map
diff --git a/gradio/templates/cdn/assets/Image.f3d382f6.js.map b/gradio/templates/cdn/assets/Image.f3d382f6.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..9c436d536c3900c78642bfbbdad2f5998f0513c5
--- /dev/null
+++ b/gradio/templates/cdn/assets/Image.f3d382f6.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"Image.f3d382f6.js","sources":["../../../../ui/packages/icons/src/Image.svelte"],"sourcesContent":["\n"],"names":[],"mappings":"koBAAA,SAYC,OACA,OACA"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/api-logo.5346f193.svg b/gradio/templates/cdn/assets/api-logo.5346f193.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bce49a58f0e8a89980e96b8f3bb99f7da48e6254
--- /dev/null
+++ b/gradio/templates/cdn/assets/api-logo.5346f193.svg
@@ -0,0 +1,4 @@
+
diff --git a/gradio/templates/cdn/assets/color.f2fbe15a.js b/gradio/templates/cdn/assets/color.f2fbe15a.js
new file mode 100644
index 0000000000000000000000000000000000000000..47ee0425c6f0b3071fd2824fdd19feb5fe8a5d7b
--- /dev/null
+++ b/gradio/templates/cdn/assets/color.f2fbe15a.js
@@ -0,0 +1,2 @@
+import{am as o}from"./index.7a68216a.js";const t=r=>o[r%o.length];export{t as g};
+//# sourceMappingURL=color.f2fbe15a.js.map
diff --git a/gradio/templates/cdn/assets/color.f2fbe15a.js.map b/gradio/templates/cdn/assets/color.f2fbe15a.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..538fd1cad424c37e54268bcbd89b9b1c52f5285a
--- /dev/null
+++ b/gradio/templates/cdn/assets/color.f2fbe15a.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"color.f2fbe15a.js","sources":["../../../../ui/packages/utils/src/color.ts"],"sourcesContent":["import { colors, ordered_colors } from \"@gradio/theme\";\n\nexport const get_next_color = (index: number): keyof typeof colors => {\n\treturn ordered_colors[index % ordered_colors.length];\n};\n"],"names":[],"mappings":"8CAEa,GAAiB,AAAC,GACvB,EAAe,EAAQ,EAAe"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/csv.27f5436c.js b/gradio/templates/cdn/assets/csv.27f5436c.js
new file mode 100644
index 0000000000000000000000000000000000000000..7ee090c69a9158e1331c5630c3dff9699534ab58
--- /dev/null
+++ b/gradio/templates/cdn/assets/csv.27f5436c.js
@@ -0,0 +1,2 @@
+import{d as a}from"./dsv.7fe76a93.js";var s=a(","),v=s.parse,o=s.parseRows;export{v as a,o as c};
+//# sourceMappingURL=csv.27f5436c.js.map
diff --git a/gradio/templates/cdn/assets/csv.27f5436c.js.map b/gradio/templates/cdn/assets/csv.27f5436c.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..a2fc13e7d828302e2d638bb4c4ef261c7c9670ec
--- /dev/null
+++ b/gradio/templates/cdn/assets/csv.27f5436c.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"csv.27f5436c.js","sources":["../../../../ui/node_modules/.pnpm/d3-dsv@3.0.1/node_modules/d3-dsv/src/csv.js"],"sourcesContent":["import dsv from \"./dsv.js\";\n\nvar csv = dsv(\",\");\n\nexport var csvParse = csv.parse;\nexport var csvParseRows = csv.parseRows;\nexport var csvFormat = csv.format;\nexport var csvFormatBody = csv.formatBody;\nexport var csvFormatRows = csv.formatRows;\nexport var csvFormatRow = csv.formatRow;\nexport var csvFormatValue = csv.formatValue;\n"],"names":["dsv"],"mappings":"sCAEA,GAAI,GAAMA,EAAI,GAAG,EAEN,EAAW,EAAI,MACf,EAAe,EAAI"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/dockerfile.088eba71.js b/gradio/templates/cdn/assets/dockerfile.088eba71.js
new file mode 100644
index 0000000000000000000000000000000000000000..1c4466ab9a87e5fe8865875adf758592dbfa167c
--- /dev/null
+++ b/gradio/templates/cdn/assets/dockerfile.088eba71.js
@@ -0,0 +1,2 @@
+function c(n){a(n,"start");var t={},e=n.languageData||{},s=!1;for(var l in n)if(l!=e&&n.hasOwnProperty(l))for(var u=t[l]=[],o=n[l],r=0;r2&&o.token&&typeof o.token!="string"){e.pending=[];for(var g=2;g-1)return null;var l=e.indent.length-1,u=n[e.state];n:for(;;){for(var o=0;o 2 && rule.token && typeof rule.token != \"string\") {\n state.pending = [];\n for (var j = 2; j < matches.length; j++)\n if (matches[j])\n state.pending.push({text: matches[j], token: rule.token[j - 1]});\n stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));\n return token[0];\n } else if (token && token.join) {\n return token[0];\n } else {\n return token;\n }\n }\n }\n stream.next();\n return null;\n };\n}\n\nfunction indentFunction(states, meta) {\n return function(state, textAfter) {\n if (state.indent == null || meta.dontIndentStates && meta.doneIndentState.indexOf(state.state) > -1)\n return null\n\n var pos = state.indent.length - 1, rules = states[state.state];\n scan: for (;;) {\n for (var i = 0; i < rules.length; i++) {\n var rule = rules[i];\n if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {\n var m = rule.regex.exec(textAfter);\n if (m && m[0]) {\n pos--;\n if (rule.next || rule.push) rules = states[rule.next || rule.push];\n textAfter = textAfter.slice(m[0].length);\n continue scan;\n }\n }\n }\n break;\n }\n return pos < 0 ? 0 : state.indent[pos];\n };\n}\n","import {simpleMode} from \"./simple-mode.js\"\n\nvar from = \"from\";\nvar fromRegex = new RegExp(\"^(\\\\s*)\\\\b(\" + from + \")\\\\b\", \"i\");\n\nvar shells = [\"run\", \"cmd\", \"entrypoint\", \"shell\"];\nvar shellsAsArrayRegex = new RegExp(\"^(\\\\s*)(\" + shells.join('|') + \")(\\\\s+\\\\[)\", \"i\");\n\nvar expose = \"expose\";\nvar exposeRegex = new RegExp(\"^(\\\\s*)(\" + expose + \")(\\\\s+)\", \"i\");\n\nvar others = [\n \"arg\", \"from\", \"maintainer\", \"label\", \"env\",\n \"add\", \"copy\", \"volume\", \"user\",\n \"workdir\", \"onbuild\", \"stopsignal\", \"healthcheck\", \"shell\"\n];\n\n// Collect all Dockerfile directives\nvar instructions = [from, expose].concat(shells).concat(others),\n instructionRegex = \"(\" + instructions.join('|') + \")\",\n instructionOnlyLine = new RegExp(\"^(\\\\s*)\" + instructionRegex + \"(\\\\s*)(#.*)?$\", \"i\"),\n instructionWithArguments = new RegExp(\"^(\\\\s*)\" + instructionRegex + \"(\\\\s+)\", \"i\");\n\nexport const dockerFile = simpleMode({\n start: [\n // Block comment: This is a line starting with a comment\n {\n regex: /^\\s*#.*$/,\n sol: true,\n token: \"comment\"\n },\n {\n regex: fromRegex,\n token: [null, \"keyword\"],\n sol: true,\n next: \"from\"\n },\n // Highlight an instruction without any arguments (for convenience)\n {\n regex: instructionOnlyLine,\n token: [null, \"keyword\", null, \"error\"],\n sol: true\n },\n {\n regex: shellsAsArrayRegex,\n token: [null, \"keyword\", null],\n sol: true,\n next: \"array\"\n },\n {\n regex: exposeRegex,\n token: [null, \"keyword\", null],\n sol: true,\n next: \"expose\"\n },\n // Highlight an instruction followed by arguments\n {\n regex: instructionWithArguments,\n token: [null, \"keyword\", null],\n sol: true,\n next: \"arguments\"\n },\n {\n regex: /./,\n token: null\n }\n ],\n from: [\n {\n regex: /\\s*$/,\n token: null,\n next: \"start\"\n },\n {\n // Line comment without instruction arguments is an error\n regex: /(\\s*)(#.*)$/,\n token: [null, \"error\"],\n next: \"start\"\n },\n {\n regex: /(\\s*\\S+\\s+)(as)/i,\n token: [null, \"keyword\"],\n next: \"start\"\n },\n // Fail safe return to start\n {\n token: null,\n next: \"start\"\n }\n ],\n single: [\n {\n regex: /(?:[^\\\\']|\\\\.)/,\n token: \"string\"\n },\n {\n regex: /'/,\n token: \"string\",\n pop: true\n }\n ],\n double: [\n {\n regex: /(?:[^\\\\\"]|\\\\.)/,\n token: \"string\"\n },\n {\n regex: /\"/,\n token: \"string\",\n pop: true\n }\n ],\n array: [\n {\n regex: /\\]/,\n token: null,\n next: \"start\"\n },\n {\n regex: /\"(?:[^\\\\\"]|\\\\.)*\"?/,\n token: \"string\"\n }\n ],\n expose: [\n {\n regex: /\\d+$/,\n token: \"number\",\n next: \"start\"\n },\n {\n regex: /[^\\d]+$/,\n token: null,\n next: \"start\"\n },\n {\n regex: /\\d+/,\n token: \"number\"\n },\n {\n regex: /[^\\d]+/,\n token: null\n },\n // Fail safe return to start\n {\n token: null,\n next: \"start\"\n }\n ],\n arguments: [\n {\n regex: /^\\s*#.*$/,\n sol: true,\n token: \"comment\"\n },\n {\n regex: /\"(?:[^\\\\\"]|\\\\.)*\"?$/,\n token: \"string\",\n next: \"start\"\n },\n {\n regex: /\"/,\n token: \"string\",\n push: \"double\"\n },\n {\n regex: /'(?:[^\\\\']|\\\\.)*'?$/,\n token: \"string\",\n next: \"start\"\n },\n {\n regex: /'/,\n token: \"string\",\n push: \"single\"\n },\n {\n regex: /[^#\"']+[\\\\`]$/,\n token: null\n },\n {\n regex: /[^#\"']+$/,\n token: null,\n next: \"start\"\n },\n {\n regex: /[^#\"']+/,\n token: null\n },\n // Fail safe return to start\n {\n token: null,\n next: \"start\"\n }\n ],\n languageData: {\n commentTokens: {line: \"#\"}\n }\n});\n\n"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/dsv.7fe76a93.js b/gradio/templates/cdn/assets/dsv.7fe76a93.js
new file mode 100644
index 0000000000000000000000000000000000000000..fd7a34bfb56dda82dfbc84dbca32dfe81c5c5b4d
--- /dev/null
+++ b/gradio/templates/cdn/assets/dsv.7fe76a93.js
@@ -0,0 +1,6 @@
+var D={},A={},E=34,m=10,R=13;function I(r){return new Function("d","return {"+r.map(function(t,e){return JSON.stringify(t)+": d["+e+'] || ""'}).join(",")+"}")}function B(r,t){var e=I(r);return function(a,c){return t(e(a),c,r)}}function F(r){var t=Object.create(null),e=[];return r.forEach(function(a){for(var c in a)c in t||e.push(t[c]=c)}),e}function f(r,t){var e=r+"",a=e.length;return a9999?"+"+f(r,6):f(r,4)}function S(r){var t=r.getUTCHours(),e=r.getUTCMinutes(),a=r.getUTCSeconds(),c=r.getUTCMilliseconds();return isNaN(r)?"Invalid Date":L(r.getUTCFullYear())+"-"+f(r.getUTCMonth()+1,2)+"-"+f(r.getUTCDate(),2)+(c?"T"+f(t,2)+":"+f(e,2)+":"+f(a,2)+"."+f(c,3)+"Z":a?"T"+f(t,2)+":"+f(e,2)+":"+f(a,2)+"Z":e||t?"T"+f(t,2)+":"+f(e,2)+"Z":"")}function Z(r){var t=new RegExp('["'+r+`
+\r]`),e=r.charCodeAt(0);function a(n,o){var s,i,u=c(n,function(h,l){if(s)return s(h,l-1);i=h,s=o?B(h,o):I(h)});return u.columns=i||[],u}function c(n,o){var s=[],i=n.length,u=0,h=0,l,v=i<=0,C=!1;n.charCodeAt(i-1)===m&&--i,n.charCodeAt(i-1)===R&&--i;function w(){if(v)return A;if(C)return C=!1,D;var j,d=u,p;if(n.charCodeAt(d)===E){for(;u++=i?v=!0:(p=n.charCodeAt(u++))===m?C=!0:p===R&&(C=!0,n.charCodeAt(u)===m&&++u),n.slice(d+1,j-1).replace(/""/g,'"')}for(;u 9999 ? \"+\" + pad(year, 6)\n : pad(year, 4);\n}\n\nfunction formatDate(date) {\n var hours = date.getUTCHours(),\n minutes = date.getUTCMinutes(),\n seconds = date.getUTCSeconds(),\n milliseconds = date.getUTCMilliseconds();\n return isNaN(date) ? \"Invalid Date\"\n : formatYear(date.getUTCFullYear(), 4) + \"-\" + pad(date.getUTCMonth() + 1, 2) + \"-\" + pad(date.getUTCDate(), 2)\n + (milliseconds ? \"T\" + pad(hours, 2) + \":\" + pad(minutes, 2) + \":\" + pad(seconds, 2) + \".\" + pad(milliseconds, 3) + \"Z\"\n : seconds ? \"T\" + pad(hours, 2) + \":\" + pad(minutes, 2) + \":\" + pad(seconds, 2) + \"Z\"\n : minutes || hours ? \"T\" + pad(hours, 2) + \":\" + pad(minutes, 2) + \"Z\"\n : \"\");\n}\n\nexport default function(delimiter) {\n var reFormat = new RegExp(\"[\\\"\" + delimiter + \"\\n\\r]\"),\n DELIMITER = delimiter.charCodeAt(0);\n\n function parse(text, f) {\n var convert, columns, rows = parseRows(text, function(row, i) {\n if (convert) return convert(row, i - 1);\n columns = row, convert = f ? customConverter(row, f) : objectConverter(row);\n });\n rows.columns = columns || [];\n return rows;\n }\n\n function parseRows(text, f) {\n var rows = [], // output rows\n N = text.length,\n I = 0, // current character index\n n = 0, // current line number\n t, // current token\n eof = N <= 0, // current token followed by EOF?\n eol = false; // current token followed by EOL?\n\n // Strip the trailing newline.\n if (text.charCodeAt(N - 1) === NEWLINE) --N;\n if (text.charCodeAt(N - 1) === RETURN) --N;\n\n function token() {\n if (eof) return EOF;\n if (eol) return eol = false, EOL;\n\n // Unescape quotes.\n var i, j = I, c;\n if (text.charCodeAt(j) === QUOTE) {\n while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE);\n if ((i = I) >= N) eof = true;\n else if ((c = text.charCodeAt(I++)) === NEWLINE) eol = true;\n else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; }\n return text.slice(j + 1, i - 1).replace(/\"\"/g, \"\\\"\");\n }\n\n // Find next delimiter or newline.\n while (I < N) {\n if ((c = text.charCodeAt(i = I++)) === NEWLINE) eol = true;\n else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; }\n else if (c !== DELIMITER) continue;\n return text.slice(j, i);\n }\n\n // Return last token before EOF.\n return eof = true, text.slice(j, N);\n }\n\n while ((t = token()) !== EOF) {\n var row = [];\n while (t !== EOL && t !== EOF) row.push(t), t = token();\n if (f && (row = f(row, n++)) == null) continue;\n rows.push(row);\n }\n\n return rows;\n }\n\n function preformatBody(rows, columns) {\n return rows.map(function(row) {\n return columns.map(function(column) {\n return formatValue(row[column]);\n }).join(delimiter);\n });\n }\n\n function format(rows, columns) {\n if (columns == null) columns = inferColumns(rows);\n return [columns.map(formatValue).join(delimiter)].concat(preformatBody(rows, columns)).join(\"\\n\");\n }\n\n function formatBody(rows, columns) {\n if (columns == null) columns = inferColumns(rows);\n return preformatBody(rows, columns).join(\"\\n\");\n }\n\n function formatRows(rows) {\n return rows.map(formatRow).join(\"\\n\");\n }\n\n function formatRow(row) {\n return row.map(formatValue).join(delimiter);\n }\n\n function formatValue(value) {\n return value == null ? \"\"\n : value instanceof Date ? formatDate(value)\n : reFormat.test(value += \"\") ? \"\\\"\" + value.replace(/\"/g, \"\\\"\\\"\") + \"\\\"\"\n : value;\n }\n\n return {\n parse: parse,\n parseRows: parseRows,\n format: format,\n formatBody: formatBody,\n formatRows: formatRows,\n formatRow: formatRow,\n formatValue: formatValue\n };\n}\n"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/frontmatter.daeef12a.js b/gradio/templates/cdn/assets/frontmatter.daeef12a.js
new file mode 100644
index 0000000000000000000000000000000000000000..f12ceb2c49dd7949b278ebf355d2506a6c7cce37
--- /dev/null
+++ b/gradio/templates/cdn/assets/frontmatter.daeef12a.js
@@ -0,0 +1,2 @@
+import{s as m,t as a,f as s,a as i,p,S as l}from"./index.bb94c2e1.js";import{yaml as f}from"./yaml.44f733df.js";import"./index.7a68216a.js";import"./Blocks.1c8a32b7.js";import"./Empty.svelte_svelte_type_style_lang.d7a3af78.js";import"./BlockLabel.fd555cfa.js";import"./Empty.092ff864.js";/* empty css */import"./Copy.fa9f7398.js";import"./Download.e46fa6ff.js";const n=/^---\s*$/m,b={defineNodes:[{name:"Frontmatter",block:!0},"FrontmatterMark"],props:[m({Frontmatter:[a.documentMeta,a.monospace],FrontmatterMark:a.processingInstruction}),s.add({Frontmatter:i,FrontmatterMark:()=>null})],wrap:p(t=>{const{parser:e}=l.define(f);return t.type.name==="Frontmatter"?{parser:e,overlay:[{from:t.from+4,to:t.to-4}]}:null}),parseBlock:[{name:"Frontmatter",before:"HorizontalRule",parse:(t,e)=>{let r;const o=new Array;if(t.lineStart===0&&n.test(e.text)){for(o.push(t.elt("FrontmatterMark",0,4));t.nextLine();)if(n.test(e.text)){r=t.lineStart+4;break}return r!==void 0&&(o.push(t.elt("FrontmatterMark",r-4,r)),t.addElement(t.elt("Frontmatter",0,r,o))),!0}else return!1}}]};export{b as frontmatter};
+//# sourceMappingURL=frontmatter.daeef12a.js.map
diff --git a/gradio/templates/cdn/assets/frontmatter.daeef12a.js.map b/gradio/templates/cdn/assets/frontmatter.daeef12a.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..6023d4e0d58fbbd26c3feade85971054b8102373
--- /dev/null
+++ b/gradio/templates/cdn/assets/frontmatter.daeef12a.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"frontmatter.daeef12a.js","sources":["../../../../ui/packages/code/interactive/frontmatter.ts"],"sourcesContent":["import type {\n\tElement,\n\tMarkdownExtension,\n\tBlockContext,\n\tLine\n} from \"@lezer/markdown\";\nimport { parseMixed } from \"@lezer/common\";\nimport { yaml } from \"@codemirror/legacy-modes/mode/yaml\";\nimport { foldInside, foldNodeProp, StreamLanguage } from \"@codemirror/language\";\nimport { styleTags, tags } from \"@lezer/highlight\";\n\nconst frontMatterFence = /^---\\s*$/m;\n\nexport const frontmatter: MarkdownExtension = {\n\tdefineNodes: [{ name: \"Frontmatter\", block: true }, \"FrontmatterMark\"],\n\tprops: [\n\t\tstyleTags({\n\t\t\tFrontmatter: [tags.documentMeta, tags.monospace],\n\t\t\tFrontmatterMark: tags.processingInstruction\n\t\t}),\n\t\tfoldNodeProp.add({\n\t\t\tFrontmatter: foldInside,\n\t\t\tFrontmatterMark: () => null\n\t\t})\n\t],\n\twrap: parseMixed((node) => {\n\t\tconst { parser } = StreamLanguage.define(yaml);\n\t\tif (node.type.name === \"Frontmatter\") {\n\t\t\treturn {\n\t\t\t\tparser,\n\t\t\t\toverlay: [{ from: node.from + 4, to: node.to - 4 }]\n\t\t\t};\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}),\n\tparseBlock: [\n\t\t{\n\t\t\tname: \"Frontmatter\",\n\t\t\tbefore: \"HorizontalRule\",\n\t\t\tparse: (cx: BlockContext, line: Line): boolean => {\n\t\t\t\tlet end: number | undefined = undefined;\n\t\t\t\tconst children = new Array();\n\t\t\t\tif (cx.lineStart === 0 && frontMatterFence.test(line.text)) {\n\t\t\t\t\tchildren.push(cx.elt(\"FrontmatterMark\", 0, 4));\n\t\t\t\t\twhile (cx.nextLine()) {\n\t\t\t\t\t\tif (frontMatterFence.test(line.text)) {\n\t\t\t\t\t\t\tend = cx.lineStart + 4;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (end !== undefined) {\n\t\t\t\t\t\tchildren.push(cx.elt(\"FrontmatterMark\", end - 4, end));\n\t\t\t\t\t\tcx.addElement(cx.elt(\"Frontmatter\", 0, end, children));\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t]\n};\n"],"names":[],"mappings":"4ZAWA,KAAM,GAAmB,YAEZ,EAAiC,CAC7C,YAAa,CAAC,CAAE,KAAM,cAAe,MAAO,IAAQ,iBAAiB,EACrE,MAAO,CACN,EAAU,CACT,YAAa,CAAC,EAAK,aAAc,EAAK,SAAS,EAC/C,gBAAiB,EAAK,sBACtB,EACD,EAAa,IAAI,CAChB,YAAa,EACb,gBAAiB,IAAM,KACvB,GAEF,KAAM,EAAW,AAAC,GAAS,MACpB,CAAE,UAAW,EAAe,OAAO,CAAI,QACzC,GAAK,KAAK,OAAS,cACf,CACN,SACA,QAAS,CAAC,CAAE,KAAM,EAAK,KAAO,EAAG,GAAI,EAAK,GAAK,EAAG,GAG5C,KAER,EACD,WAAY,CACX,CACC,KAAM,cACN,OAAQ,iBACR,MAAO,CAAC,EAAkB,IAAwB,IAC7C,QACE,GAAW,GAAI,UACjB,EAAG,YAAc,GAAK,EAAiB,KAAK,EAAK,IAAI,EAAG,OAClD,KAAK,EAAG,IAAI,kBAAmB,EAAG,CAAC,CAAC,EACtC,EAAG,eACL,EAAiB,KAAK,EAAK,IAAI,EAAG,GAC/B,EAAG,UAAY,cAInB,KAAQ,WACF,KAAK,EAAG,IAAI,kBAAmB,EAAM,EAAG,CAAG,CAAC,IAClD,WAAW,EAAG,IAAI,cAAe,EAAG,EAAK,CAAQ,CAAC,GAE/C,cAEA,KAKZ"}
\ No newline at end of file
diff --git a/gradio/templates/cdn/assets/index.00ec9920.css b/gradio/templates/cdn/assets/index.00ec9920.css
new file mode 100644
index 0000000000000000000000000000000000000000..15c9d289c09b6f2581d92648fe1acdaebd8776fd
--- /dev/null
+++ b/gradio/templates/cdn/assets/index.00ec9920.css
@@ -0,0 +1 @@
+.model3D.svelte-14ct53h{display:flex;position:relative;width:var(--size-full);height:var(--size-full)}canvas.svelte-14ct53h{width:var(--size-full);height:var(--size-full);object-fit:contain}.download.svelte-14ct53h{position:absolute;top:6px;right:6px}.input-model.svelte-wn75i6{display:flex;position:relative;justify-content:center;align-items:center;width:var(--size-full);height:var(--size-64)}canvas.svelte-wn75i6{width:var(--size-full);height:var(--size-full);object-fit:contain}
diff --git a/gradio/templates/cdn/assets/index.06965fd8.js b/gradio/templates/cdn/assets/index.06965fd8.js
new file mode 100644
index 0000000000000000000000000000000000000000..a74a0efc91d9a7c011ff3e3b1afaaef3e41806e0
--- /dev/null
+++ b/gradio/templates/cdn/assets/index.06965fd8.js
@@ -0,0 +1,2 @@
+import{S as T,i as D,s as G,F as b,H as C,G as y,B as u,f as v,D as h,J as q,p as k,c as N,m as R,o as A,t as B,l as I,N as j,A as z,O as E,K as J,af as fe,b as K,e as re,g as ue,h as _e,k as ce,n as oe,v as ge}from"./index.7a68216a.js";import"./Empty.svelte_svelte_type_style_lang.d7a3af78.js";import{B as M}from"./BlockTitle.39fa370e.js";import"./Info.4b69e77f.js";const w=i=>{var e=null;return i<0?e=[52,152,219]:e=[231,76,60],me(he(Math.abs(i),[255,255,255],e))},he=(i,e,t)=>{i>1&&(i=1),i=Math.sqrt(i);var n=[0,0,0],o;for(o=0;o<3;o++)n[o]=Math.round(e[o]*(1-i)+t[o]*i);return n},me=i=>"rgb("+i[0]+", "+i[1]+", "+i[2]+")",U=(i,e,t,n,o)=>{var s=n/o,c=e/t,l=0,r=0,f=i?s>c:s{"interpretation"in s&&t(0,n=s.interpretation),"label"in s&&t(1,o=s.label)},[n,o]}class ke extends T{constructor(e){super(),D(this,e,ve,be,G,{interpretation:0,label:1})}}function Q(i,e,t){const n=i.slice();return n[3]=e[t],n[5]=t,n}function pe(i){let e;return{c(){e=C(i[2])},m(t,n){v(t,e,n)},p(t,n){n&4&&q(e,t[2])},d(t){t&&k(e)}}}function V(i){let e,t=i[3]+"",n,o,s;return{c(){e=b("li"),n=C(t),o=y(),u(e,"class","dropdown-item svelte-1cqwepf"),u(e,"style",s="background-color: "+w(i[0][i[5]]))},m(c,l){v(c,e,l),h(e,n),h(e,o)},p(c,l){l&2&&t!==(t=c[3]+"")&&q(n,t),l&1&&s!==(s="background-color: "+w(c[0][c[5]]))&&u(e,"style",s)},d(c){c&&k(e)}}}function we(i){let e,t,n,o,s;t=new M({props:{$$slots:{default:[pe]},$$scope:{ctx:i}}});let c=i[1],l=[];for(let r=0;r{"interpretation"in c&&t(0,n=c.interpretation),"choices"in c&&t(1,o=c.choices),"label"in c&&t(2,s=c.label)},[n,o,s]}class Se extends T{constructor(e){super(),D(this,e,ye,we,G,{interpretation:0,choices:1,label:2})}}function Ce(i){let e;return{c(){e=C(i[0])},m(t,n){v(t,e,n)},p(t,n){n&1&&q(e,t[0])},d(t){t&&k(e)}}}function qe(i){let e,t,n,o,s,c,l,r,f,a,_,g,m;return t=new M({props:{$$slots:{default:[Ce]},$$scope:{ctx:i}}}),{c(){e=b("div"),N(t.$$.fragment),n=y(),o=b("button"),s=b("div"),l=y(),r=b("div"),f=z("svg"),a=z("line"),_=z("line"),u(s,"class","checkbox svelte-1nw19ca"),u(s,"style",c="background-color: "+w(i[2][0])),u(a,"x1","-7.5"),u(a,"y1","0"),u(a,"x2","-2.5"),u(a,"y2","5"),u(a,"stroke","black"),u(a,"stroke-width","4"),u(a,"stroke-linecap","round"),u(_,"x1","-2.5"),u(_,"y1","5"),u(_,"x2","7.5"),u(_,"y2","-7.5"),u(_,"stroke","black"),u(_,"stroke-width","4"),u(_,"stroke-linecap","round"),u(f,"viewBox","-10 -10 20 20"),u(f,"class","svelte-1nw19ca"),u(r,"class","checkbox svelte-1nw19ca"),u(r,"style",g="background-color: "+w(i[2][1])),u(o,"class","checkbox-item svelte-1nw19ca"),E(o,"selected",i[1]),u(e,"class","input-checkbox svelte-1nw19ca")},m(d,p){v(d,e,p),R(t,e,null),h(e,n),h(e,o),h(o,s),h(o,l),h(o,r),h(r,f),h(f,a),h(f,_),m=!0},p(d,[p]){const S={};p&9&&(S.$$scope={dirty:p,ctx:d}),t.$set(S),(!m||p&4&&c!==(c="background-color: "+w(d[2][0])))&&u(s,"style",c),(!m||p&4&&g!==(g="background-color: "+w(d[2][1])))&&u(r,"style",g),p&2&&E(o,"selected",d[1])},i(d){m||(A(t.$$.fragment,d),m=!0)},o(d){B(t.$$.fragment,d),m=!1},d(d){d&&k(e),I(t)}}}function Ae(i,e,t){let{label:n=""}=e,{original:o}=e,{interpretation:s}=e;return i.$$set=c=>{"label"in c&&t(0,n=c.label),"original"in c&&t(1,o=c.original),"interpretation"in c&&t(2,s=c.interpretation)},[n,o,s]}class Be extends T{constructor(e){super(),D(this,e,Ae,qe,G,{label:0,original:1,interpretation:2})}}function W(i,e,t){const n=i.slice();return n[4]=e[t],n[6]=t,n}function Ne(i){let e;return{c(){e=C(i[3])},m(t,n){v(t,e,n)},p(t,n){n&8&&q(e,t[3])},d(t){t&&k(e)}}}function X(i){let e,t,n,o,s,c,l,r,f,a,_=i[4]+"",g,m;return{c(){e=b("button"),t=b("div"),o=y(),s=b("div"),c=z("svg"),l=z("line"),r=z("line"),a=y(),g=C(_),m=y(),u(t,"class","checkbox svelte-1cbhr6k"),u(t,"style",n="background-color: "+w(i[1][i[6]][0])),u(l,"x1","-7.5"),u(l,"y1","0"),u(l,"x2","-2.5"),u(l,"y2","5"),u(l,"stroke","black"),u(l,"stroke-width","4"),u(l,"stroke-linecap","round"),u(r,"x1","-2.5"),u(r,"y1","5"),u(r,"x2","7.5"),u(r,"y2","-7.5"),u(r,"stroke","black"),u(r,"stroke-width","4"),u(r,"stroke-linecap","round"),u(c,"viewBox","-10 -10 20 20"),u(c,"class","svelte-1cbhr6k"),u(s,"class","checkbox svelte-1cbhr6k"),u(s,"style",f="background-color: "+w(i[1][i[6]][1])),u(e,"class","checkbox-item svelte-1cbhr6k"),E(e,"selected",i[0].includes(i[4]))},m(d,p){v(d,e,p),h(e,t),h(e,o),h(e,s),h(s,c),h(c,l),h(c,r),h(e,a),h(e,g),h(e,m)},p(d,p){p&2&&n!==(n="background-color: "+w(d[1][d[6]][0]))&&u(t,"style",n),p&2&&f!==(f="background-color: "+w(d[1][d[6]][1]))&&u(s,"style",f),p&4&&_!==(_=d[4]+"")&&q(g,_),p&5&&E(e,"selected",d[0].includes(d[4]))},d(d){d&&k(e)}}}function Re(i){let e,t,n,o;t=new M({props:{$$slots:{default:[Ne]},$$scope:{ctx:i}}});let s=i[2],c=[];for(let l=0;l{"original"in l&&t(0,n=l.original),"interpretation"in l&&t(1,o=l.interpretation),"choices"in l&&t(2,s=l.choices),"label"in l&&t(3,c=l.label)},[n,o,s,c]}class Te extends T{constructor(e){super(),D(this,e,Ie,Re,G,{original:0,interpretation:1,choices:2,label:3})}}function Y(i,e,t){const n=i.slice();return n[6]=e[t],n}function De(i){let e;return{c(){e=C(i[5])},m(t,n){v(t,e,n)},p(t,n){n&32&&q(e,t[5])},d(t){t&&k(e)}}}function Z(i){let e,t;return{c(){e=b("div"),u(e,"style",t="background-color: "+w(i[6])),u(e,"class","svelte-1sxprr7")},m(n,o){v(n,e,o)},p(n,o){o&2&&t!==(t="background-color: "+w(n[6]))&&u(e,"style",t)},d(n){n&&k(e)}}}function Ge(i){let e,t,n,o,s,c,l,r,f,a;t=new M({props:{$$slots:{default:[De]},$$scope:{ctx:i}}});let _=i[1],g=[];for(let m=0;m<_.length;m+=1)g[m]=Z(Y(i,_,m));return{c(){e=b("div"),N(t.$$.fragment),n=y(),o=b("input"),s=y(),c=b("div");for(let m=0;m{"original"in f&&t(0,n=f.original),"interpretation"in f&&t(1,o=f.interpretation),"minimum"in f&&t(2,s=f.minimum),"maximum"in f&&t(3,c=f.maximum),"step"in f&&t(4,l=f.step),"label"in f&&t(5,r=f.label)},[n,o,s,c,l,r]}class je extends T{constructor(e){super(),D(this,e,Me,Ge,G,{original:0,interpretation:1,minimum:2,maximum:3,step:4,label:5})}}function x(i,e,t){const n=i.slice();return n[4]=e[t],n[6]=t,n}function ze(i){let e;return{c(){e=C(i[3])},m(t,n){v(t,e,n)},p(t,n){n&8&&q(e,t[3])},d(t){t&&k(e)}}}function $(i){let e,t,n,o,s=i[4]+"",c,l;return{c(){e=b("button"),t=b("div"),o=y(),c=C(s),l=y(),u(t,"class","radio-circle svelte-1nekfre"),u(t,"style",n="background-color: "+w(i[1][i[6]])),u(e,"class","radio-item svelte-1nekfre"),E(e,"selected",i[0]===i[4])},m(r,f){v(r,e,f),h(e,t),h(e,o),h(e,c),h(e,l)},p(r,f){f&2&&n!==(n="background-color: "+w(r[1][r[6]]))&&u(t,"style",n),f&4&&s!==(s=r[4]+"")&&q(c,s),f&5&&E(e,"selected",r[0]===r[4])},d(r){r&&k(e)}}}function Ee(i){let e,t,n,o;t=new M({props:{$$slots:{default:[ze]},$$scope:{ctx:i}}});let s=i[2],c=[];for(let l=0;l{"original"in l&&t(0,n=l.original),"interpretation"in l&&t(1,o=l.interpretation),"choices"in l&&t(2,s=l.choices),"label"in l&&t(3,c=l.label)},[n,o,s,c]}class Oe extends T{constructor(e){super(),D(this,e,Fe,Ee,G,{original:0,interpretation:1,choices:2,label:3})}}function He(i){let e;return{c(){e=C(i[1])},m(t,n){v(t,e,n)},p(t,n){n&2&&q(e,t[1])},d(t){t&&k(e)}}}function Je(i){let e,t,n,o,s,c,l,r,f,a;return t=new M({props:{$$slots:{default:[He]},$$scope:{ctx:i}}}),{c(){e=b("div"),N(t.$$.fragment),n=y(),o=b("div"),s=b("div"),c=b("canvas"),l=y(),r=b("img"),u(s,"class","interpretation svelte-h0dntu"),J(r.src,f=i[0])||u(r,"src",f),u(r,"class","svelte-h0dntu"),u(o,"class","image-preview svelte-h0dntu"),u(e,"class","input-image")},m(_,g){v(_,e,g),R(t,e,null),h(e,n),h(e,o),h(o,s),h(s,c),i[6](c),h(o,l),h(o,r),i[7](r),a=!0},p(_,[g]){const m={};g&514&&(m.$$scope={dirty:g,ctx:_}),t.$set(m),(!a||g&1&&!J(r.src,f=_[0]))&&u(r,"src",f)},i(_){a||(A(t.$$.fragment,_),a=!0)},o(_){B(t.$$.fragment,_),a=!1},d(_){_&&k(e),I(t),i[6](null),i[7](null)}}}function Ke(i,e,t){let{original:n}=e,{interpretation:o}=e,{shape:s}=e,{label:c=""}=e,l,r;const f=(g,m,d,p)=>{var S=d/g[0].length,F=p/g.length,O=0;g.forEach(function(se){var H=0;se.forEach(function(ae){m.fillStyle=w(ae),m.fillRect(H*S,O*F,S,F),H++}),O++})};fe(()=>{let g=U(!0,r.width,r.height,r.naturalWidth,r.naturalHeight);s&&(g=U(!0,g.width,g.height,s[0],s[1]));let m=g.width,d=g.height;l.setAttribute("height",`${d}`),l.setAttribute("width",`${m}`),f(o,l.getContext("2d"),m,d)});function a(g){K[g?"unshift":"push"](()=>{l=g,t(2,l)})}function _(g){K[g?"unshift":"push"](()=>{r=g,t(3,r)})}return i.$$set=g=>{"original"in g&&t(0,n=g.original),"interpretation"in g&&t(4,o=g.interpretation),"shape"in g&&t(5,s=g.shape),"label"in g&&t(1,c=g.label)},[n,c,l,r,o,s,a,_]}class Ue extends T{constructor(e){super(),D(this,e,Ke,Je,G,{original:0,interpretation:4,shape:5,label:1})}}function ee(i,e,t){const n=i.slice();return n[2]=e[t],n}function Le(i){let e;return{c(){e=C(i[1])},m(t,n){v(t,e,n)},p(t,n){n&2&&q(e,t[1])},d(t){t&&k(e)}}}function te(i){let e,t;return{c(){e=b("div"),u(e,"class","item svelte-13lmfcp"),u(e,"style",t="background-color: "+w(i[2]))},m(n,o){v(n,e,o)},p(n,o){o&1&&t!==(t="background-color: "+w(n[2]))&&u(e,"style",t)},d(n){n&&k(e)}}}function Pe(i){let e,t,n,o,s;t=new M({props:{$$slots:{default:[Le]},$$scope:{ctx:i}}});let c=i[0],l=[];for(let r=0;r{"interpretation"in s&&t(0,n=s.interpretation),"label"in s&&t(1,o=s.label)},[n,o]}class Ve extends T{constructor(e){super(),D(this,e,Qe,Pe,G,{interpretation:0,label:1})}}function le(i,e,t){const n=i.slice();return n[2]=e[t][0],n[3]=e[t][1],n}function We(i){let e;return{c(){e=C(i[0])},m(t,n){v(t,e,n)},p(t,n){n&1&&q(e,t[0])},d(t){t&&k(e)}}}function ne(i){let e,t=i[2]+"",n,o,s;return{c(){e=b("span"),n=C(t),o=y(),u(e,"class","text-span svelte-15c0u2m"),u(e,"style",s="background-color: "+w(i[3]))},m(c,l){v(c,e,l),h(e,n),h(e,o)},p(c,l){l&2&&t!==(t=c[2]+"")&&q(n,t),l&2&&s!==(s="background-color: "+w(c[3]))&&u(e,"style",s)},d(c){c&&k(e)}}}function Xe(i){let e,t,n,o;t=new M({props:{$$slots:{default:[We]},$$scope:{ctx:i}}});let s=i[1],c=[];for(let l=0;l{"label"in s&&t(0,n=s.label),"interpretation"in s&&t(1,o=s.interpretation)},[n,o]}class Ze extends T{constructor(e){super(),D(this,e,Ye,Xe,G,{label:0,interpretation:1})}}const xe={audio:Ve,dropdown:Se,checkbox:Be,checkboxgroup:Te,number:ke,slider:je,radio:Oe,image:Ue,textbox:Ze};function ie(i){let e,t,n;const o=[i[0],{original:i[1].original},{interpretation:i[1].interpretation}];var s=i[2];function c(l){let r={};for(let f=0;f{I(a,1)}),oe()}s?(e=new s(c()),N(e.$$.fragment),A(e.$$.fragment,1),R(e,t.parentNode,t)):e=null}else s&&e.$set(f)},i(l){n||(e&&A(e.$$.fragment,l),n=!0)},o(l){e&&B(e.$$.fragment,l),n=!1},d(l){l&&k(t),e&&I(e,l)}}}function $e(i){let e,t,n=i[1]&&ie(i);return{c(){n&&n.c(),e=re()},m(o,s){n&&n.m(o,s),v(o,e,s),t=!0},p(o,[s]){o[1]?n?(n.p(o,s),s&2&&A(n,1)):(n=ie(o),n.c(),A(n,1),n.m(e.parentNode,e)):n&&(ce(),B(n,1,1,()=>{n=null}),oe())},i(o){t||(A(n),t=!0)},o(o){B(n),t=!1},d(o){n&&n.d(o),o&&k(e)}}}function et(i,e,t){let n,{component:o}=e,{component_props:s}=e,{value:c}=e;return i.$$set=l=>{"component"in l&&t(3,o=l.component),"component_props"in l&&t(0,s=l.component_props),"value"in l&&t(1,c=l.value)},i.$$.update=()=>{i.$$.dirty&8&&t(2,n=xe[o])},[s,c,n,o]}class tt extends T{constructor(e){super(),D(this,e,et,$e,G,{component:3,component_props:0,value:1})}}var ct=tt;const ot=["dynamic"];export{ct as Component,ot as modes};
+//# sourceMappingURL=index.06965fd8.js.map
diff --git a/gradio/templates/cdn/assets/index.06965fd8.js.map b/gradio/templates/cdn/assets/index.06965fd8.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..f5ba57f33fc26c96a373160cfad8cc70925015c4
--- /dev/null
+++ b/gradio/templates/cdn/assets/index.06965fd8.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.06965fd8.js","sources":["../../../../ui/packages/app/src/components/Interpretation/utils.ts","../../../../ui/packages/app/src/components/Interpretation/InterpretationComponents/Number.svelte","../../../../ui/packages/app/src/components/Interpretation/InterpretationComponents/Dropdown.svelte","../../../../ui/packages/app/src/components/Interpretation/InterpretationComponents/Checkbox.svelte","../../../../ui/packages/app/src/components/Interpretation/InterpretationComponents/CheckboxGroup.svelte","../../../../ui/packages/app/src/components/Interpretation/InterpretationComponents/Slider.svelte","../../../../ui/packages/app/src/components/Interpretation/InterpretationComponents/Radio.svelte","../../../../ui/packages/app/src/components/Interpretation/InterpretationComponents/Image.svelte","../../../../ui/packages/app/src/components/Interpretation/InterpretationComponents/Audio.svelte","../../../../ui/packages/app/src/components/Interpretation/InterpretationComponents/Textbox.svelte","../../../../ui/packages/app/src/components/Interpretation/directory.ts","../../../../ui/packages/app/src/components/Interpretation/Interpretation.svelte","../../../../ui/packages/app/src/components/Interpretation/index.ts"],"sourcesContent":["export const getSaliencyColor = (value: number): string => {\n\tvar color: [number, number, number] | null = null;\n\tif (value < 0) {\n\t\tcolor = [52, 152, 219];\n\t} else {\n\t\tcolor = [231, 76, 60];\n\t}\n\treturn colorToString(interpolate(Math.abs(value), [255, 255, 255], color));\n};\n\nconst interpolate = (\n\tval: number,\n\trgb1: [number, number, number],\n\trgb2: [number, number, number]\n): [number, number, number] => {\n\tif (val > 1) {\n\t\tval = 1;\n\t}\n\tval = Math.sqrt(val);\n\tvar rgb: [number, number, number] = [0, 0, 0];\n\tvar i;\n\tfor (i = 0; i < 3; i++) {\n\t\trgb[i] = Math.round(rgb1[i] * (1.0 - val) + rgb2[i] * val);\n\t}\n\treturn rgb;\n};\n\nconst colorToString = (rgb: [number, number, number]): string => {\n\treturn \"rgb(\" + rgb[0] + \", \" + rgb[1] + \", \" + rgb[2] + \")\";\n};\n\nexport const getObjectFitSize = (\n\tcontains: boolean /* true = contain, false = cover */,\n\tcontainerWidth: number,\n\tcontainerHeight: number,\n\twidth: number,\n\theight: number\n) => {\n\tvar doRatio = width / height;\n\tvar cRatio = containerWidth / containerHeight;\n\tvar targetWidth = 0;\n\tvar targetHeight = 0;\n\tvar test = contains ? doRatio > cRatio : doRatio < cRatio;\n\n\tif (test) {\n\t\ttargetWidth = containerWidth;\n\t\ttargetHeight = targetWidth / doRatio;\n\t} else {\n\t\ttargetHeight = containerHeight;\n\t\ttargetWidth = targetHeight * doRatio;\n\t}\n\n\treturn {\n\t\twidth: targetWidth,\n\t\theight: targetHeight,\n\t\tx: (containerWidth - targetWidth) / 2,\n\t\ty: (containerHeight - targetHeight) / 2\n\t};\n};\n","\n\n
\n\t{label}\n\t
\n\t\t{#each interpretation as interpret_value}\n\t\t\t
\n\t\t\t\t{interpret_value[0]}\n\t\t\t
\n\t\t{/each}\n\t
\n
\n\n\n","\n\n
\n\t{label}\n\t
\n\t\t{#each choices as choice, i}\n\t\t\t
\n\t\t\t\t{choice}\n\t\t\t
\n\t\t{/each}\n\t
\n
\n\n\n","\n\n
\n\t{label}\n\t\n
\n\n\n","\n\n
\n\t{label}\n\t{#each choices as choice, i}\n\t\t\n\t{/each}\n
\n\n\n","\n\n
\n\t{label}\n\t\n\t
\n\t\t{#each interpretation as interpret_value}\n\t\t\t\n\t\t{/each}\n\t
\n\t
\n\t\t{original}\n\t
\n
\n\n\n","\n\n
\n\t{label}\n\t{#each choices as choice, i}\n\t\t\n\t{/each}\n
\n\n\n","\n\n
\n\t{label}\n\t
\n\t\t\n\t\t
\n\t\t\t\n\t\t
\n\t\t\n\t\t\n\t
\n
\n\n\n","\n\n
\n\t{label}\n\t
\n\t\t{#each interpretation as interpret_value}\n\t\t\t\n\t\t{/each}\n\t
\n
\n\n\n","\n\n
\n\t{label}\n\t{#each interpretation as [text, saliency]}\n\t\t\n\t\t\t{text}\n\t\t\n\t{/each}\n