mirror of
https://github.com/gradio-app/gradio.git
synced 2025-04-18 12:50:30 +08:00
Refactor component directories (#5074)
* asd * changes * fix everything * cleanup * add changeset * fix casing * lockfile * fix casing * fix ci, enable linting * fix test * add changeset * add changeset * delete changeset * fix dirs * fix casing * fix notebooks * fix casing * fix casing * fix casing * fix casing * fix casing * fix casing * fix casing * fix casing --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
parent
d7f83823fb
commit
1419538ea7
@ -2,4 +2,4 @@
|
||||
"website": patch
|
||||
---
|
||||
|
||||
fix:Correct gradio version on website
|
||||
fix:Correct gradio version on website
|
||||
|
@ -15,7 +15,6 @@
|
||||
**/.github/**
|
||||
**/guides/**
|
||||
**/.mypy_cache/**
|
||||
**/*.md
|
||||
!test-strategy.md
|
||||
**/js/_space-test/**
|
||||
../js/app/src/lite/theme.css
|
||||
|
@ -3,5 +3,5 @@
|
||||
"singleQuote": false,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 80,
|
||||
"plugins": ["prettier-plugin-svelte", "prettier-plugin-css-order"]
|
||||
"plugins": ["prettier-plugin-svelte"]
|
||||
}
|
||||
|
@ -16,10 +16,9 @@ const js_rules_disabled = Object.fromEntries(
|
||||
Object.keys(js_plugin.configs.all.rules).map((rule) => [rule, "off"])
|
||||
);
|
||||
|
||||
const rules = {
|
||||
...ts_rules_disabled,
|
||||
const js_rules = {
|
||||
...js_rules_disabled,
|
||||
"no-console": ["error", { allow: ["warn", "error"] }],
|
||||
"no-console": ["error", { allow: ["warn", "error", "debug"] }],
|
||||
"no-constant-condition": "error",
|
||||
"no-dupe-args": "error",
|
||||
"no-extra-boolean-cast": "error",
|
||||
@ -30,10 +29,16 @@ const rules = {
|
||||
complexity: "error",
|
||||
"no-else-return": "error",
|
||||
"no-useless-return": "error",
|
||||
"no-shadow": "error",
|
||||
"no-undef": "error",
|
||||
"no-undef": "error"
|
||||
};
|
||||
|
||||
const ts_rules = {
|
||||
...ts_rules_disabled,
|
||||
"@typescript-eslint/adjacent-overload-signatures": "error",
|
||||
"@typescript-eslint/explicit-function-return-type": "error",
|
||||
"@typescript-eslint/explicit-function-return-type": [
|
||||
"error",
|
||||
{ allowExpressions: true }
|
||||
],
|
||||
"@typescript-eslint/consistent-type-exports": "error",
|
||||
"@typescript-eslint/ban-types": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
@ -52,7 +57,10 @@ export default [
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.ts",
|
||||
"**/*.node-test.ts",
|
||||
"js/app/test/**/*"
|
||||
"js/app/test/**/*",
|
||||
"**/*vite.config.ts",
|
||||
"**/_website/**/*",
|
||||
"**/_spaces-test/**/*"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -68,7 +76,7 @@ export default [
|
||||
plugins: {
|
||||
"eslint:recommended": js_plugin
|
||||
},
|
||||
rules
|
||||
rules: js_rules
|
||||
},
|
||||
|
||||
{
|
||||
@ -90,10 +98,14 @@ export default [
|
||||
"@typescript-eslint": ts_plugin,
|
||||
"eslint:recommended": js_plugin
|
||||
},
|
||||
rules
|
||||
rules: {
|
||||
...ts_rules,
|
||||
...js_rules,
|
||||
"no-undef": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ["./client/js/**"],
|
||||
files: ["**/client/js/**"],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
project: "./client/js/tsconfig.json"
|
||||
@ -120,8 +132,11 @@ export default [
|
||||
"eslint:recommended": js_plugin
|
||||
},
|
||||
rules: {
|
||||
...rules,
|
||||
...sveltePlugin.configs.recommended.rules
|
||||
...ts_rules,
|
||||
...js_rules,
|
||||
...sveltePlugin.configs.recommended.rules,
|
||||
"svelte/no-at-html-tags": "off",
|
||||
"no-undef": "off"
|
||||
}
|
||||
}
|
||||
];
|
||||
|
1
.github/workflows/deploy-chromatic.yml
vendored
1
.github/workflows/deploy-chromatic.yml
vendored
@ -53,6 +53,7 @@ jobs:
|
||||
with:
|
||||
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
exitOnceUploaded: true
|
||||
- name: post deployment link to PR
|
||||
if: ${{ needs.get-current-pr.outputs.pr_found }} == 'true'
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
|
1
.github/workflows/ui.yml
vendored
1
.github/workflows/ui.yml
vendored
@ -31,7 +31,6 @@ jobs:
|
||||
run: pnpm --filter @gradio/wasm build
|
||||
- name: lint
|
||||
run: pnpm lint
|
||||
continue-on-error: true
|
||||
- name: typecheck
|
||||
run: pnpm ts:check
|
||||
- name: unit tests
|
||||
|
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -12,7 +12,6 @@
|
||||
"python.testing.pytestArgs": ["."],
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"eslint.packageManager": "pnpm",
|
||||
"eslint.validate": ["javascript", "typescript", "html", "markdown", "svelte"],
|
||||
"eslint.experimental.useFlatConfig": true,
|
||||
"eslint.options": {
|
||||
|
60
CHANGELOG.md
60
CHANGELOG.md
@ -6,11 +6,12 @@
|
||||
|
||||
#### Create Discord Bots from Gradio Apps 🤖 ([#4960](https://github.com/gradio-app/gradio/pull/4960) [`46e4ef67`](https://github.com/gradio-app/gradio/commit/46e4ef67d287dd68a91473b73172b29cbad064bc))
|
||||
|
||||
We're excited to announce that Gradio can now automatically create a discord bot from any `gr.ChatInterface` app.
|
||||
We're excited to announce that Gradio can now automatically create a discord bot from any `gr.ChatInterface` app.
|
||||
|
||||
It's as easy as importing `gradio_client`, connecting to the app, and calling `deploy_discord`!
|
||||
|
||||
*🦙 Turning Llama 2 70b into a discord bot 🦙*
|
||||
_🦙 Turning Llama 2 70b into a discord bot 🦙_
|
||||
|
||||
```python
|
||||
import gradio_client as grc
|
||||
grc.Client("ysharma/Explore_llamav2_with_TGI").deploy_discord(to_id="llama2-70b-discord-bot")
|
||||
@ -24,17 +25,17 @@ To help get you started, we have created an organization on Hugging Face called
|
||||
|
||||
Currently we have template spaces for:
|
||||
|
||||
* [Llama-2-70b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) powered by a FREE Hugging Face Inference Endpoint!
|
||||
* [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.
|
||||
* [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.
|
||||
* [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.
|
||||
* [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Requires an OpenAI key.
|
||||
- [Llama-2-70b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) powered by a FREE Hugging Face Inference Endpoint!
|
||||
- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.
|
||||
- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.
|
||||
- [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.
|
||||
- [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Requires an OpenAI key.
|
||||
|
||||
But once again, you can deploy ANY `gr.ChatInterface` app exposed on the internet! So don't hesitate to try it on your own Chatbots.
|
||||
|
||||
❗️ Additional Note ❗️: Technically, any gradio app that exposes an api route that takes in a single string and outputs a single string can be deployed to discord. But `gr.ChatInterface` apps naturally lend themselves to discord's chat functionality so we suggest you start with those.
|
||||
|
||||
Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
|
||||
Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
|
||||
|
||||
### Features
|
||||
|
||||
@ -53,7 +54,7 @@ But once again, you can deploy ANY `gr.ChatInterface` app exposed on the interne
|
||||
|
||||
- Provide a parameter `animate` (`False` by default) in `gr.make_waveform()` which animates the overlayed waveform by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4918](https://github.com/gradio-app/gradio/pull/4918)
|
||||
- Add `show_download_button` param to allow the download button in static Image components to be hidden by [@hannahblair](https://github.com/hannahblair) in [PR 4959](https://github.com/gradio-app/gradio/pull/4959)
|
||||
- Added autofocus argument to Textbox by [@aliabid94](https://github.com/aliabid94) in [PR 4978](https://github.com/gradio-app/gradio/pull/4978)
|
||||
- Added autofocus argument to Textbox by [@aliabid94](https://github.com/aliabid94) in [PR 4978](https://github.com/gradio-app/gradio/pull/4978)
|
||||
- The `gr.ChatInterface` UI now converts the "Submit" button to a "Stop" button in ChatInterface while streaming, which can be used to pause generation. By [@abidlabs](https://github.com/abidlabs) in [PR 4971](https://github.com/gradio-app/gradio/pull/4971).
|
||||
- Add a `border_color_accent_subdued` theme variable to add a subdued border color to accented items. This is used by chatbot user messages. Set the value of this variable in `Default` theme to `*primary_200`. By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4989](https://github.com/gradio-app/gradio/pull/4989)
|
||||
- Add default sketch color argument `brush_color`. Also, masks drawn on images are now slightly translucent (and mask color can also be set via brush_color). By [@aliabid94](https://github.com/aliabid94) in [PR 4979](https://github.com/gradio-app/gradio/pull/4979)
|
||||
@ -71,7 +72,7 @@ No changes to highlight.
|
||||
### Other Changes:
|
||||
|
||||
- Apply pyright to the `components` directory by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4948](https://github.com/gradio-app/gradio/pull/4948)
|
||||
- Improved look of ChatInterface by [@aliabid94](https://github.com/aliabid94) in [PR 4978](https://github.com/gradio-app/gradio/pull/4978)
|
||||
- Improved look of ChatInterface by [@aliabid94](https://github.com/aliabid94) in [PR 4978](https://github.com/gradio-app/gradio/pull/4978)
|
||||
|
||||
## 3.37
|
||||
|
||||
@ -97,7 +98,6 @@ And a corresponding easy-to-use API at `/chat`:
|
||||
|
||||
<img width="1164" alt="image" src="https://github.com/gradio-app/gradio/assets/1778297/7b10d6db-6476-4e2e-bebd-ecda802c3b8f">
|
||||
|
||||
|
||||
The `gr.ChatInterface` abstraction works nicely with various LLM libraries, such as `langchain`. See the [dedicated guide](https://gradio.app/guides/creating-a-chatbot-fast) for more examples using `gr.ChatInterface`. Collective team effort in [PR 4869](https://github.com/gradio-app/gradio/pull/4869)
|
||||
|
||||
- Chatbot messages now show hyperlinks to download files uploaded to `gr.Chatbot()` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4848](https://github.com/gradio-app/gradio/pull/4848)
|
||||
@ -107,29 +107,31 @@ The `gr.ChatInterface` abstraction works nicely with various LLM libraries, such
|
||||
Examples of usage:
|
||||
|
||||
```py
|
||||
with gr.Blocks() as demo:
|
||||
with gr.Blocks() as demo:
|
||||
gr.Textbox(interactive=True, text_align="right")
|
||||
demo.launch()
|
||||
```
|
||||
|
||||
```py
|
||||
with gr.Blocks() as demo:
|
||||
with gr.Blocks() as demo:
|
||||
gr.Markdown("سلام", rtl=True)
|
||||
demo.launch()
|
||||
```
|
||||
|
||||
- The `get_api_info` method of `Blocks` now supports layout output components [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4871](https://github.com/gradio-app/gradio/pull/4871)
|
||||
|
||||
- Added the support for the new command `gradio environment`to make it easier for people to file bug reports if we shipped an easy command to list the OS, gradio version, and versions of gradio/gradio-client dependencies. bu [@varshneydevansh](https://github.com/varshneydevansh) in [PR 4915](https://github.com/gradio-app/gradio/pull/4915).
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* The `.change()` event is fixed in `Video` and `Image` so that it only fires once by [@abidlabs](https://github.com/abidlabs) in [PR 4793](https://github.com/gradio-app/gradio/pull/4793)
|
||||
* The `.change()` event is fixed in `Audio` so that fires when the component value is programmatically updated by [@abidlabs](https://github.com/abidlabs) in [PR 4793](https://github.com/gradio-app/gradio/pull/4793)
|
||||
- Add missing `display: flex` property to `Row` so that flex styling is applied to children by [@hannahblair] in [PR 4896](https://github.com/gradio-app/gradio/pull/4896)
|
||||
- Fixed bug where `gr.Video` could not preprocess urls by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4904](https://github.com/gradio-app/gradio/pull/4904)
|
||||
- Fixed copy button rendering in API page on Safari by [@aliabid94](https://github.com/aliabid94) in [PR 4924](https://github.com/gradio-app/gradio/pull/4924)
|
||||
- Fixed `gr.Group` and `container=False`. `container` parameter only available for `Textbox`, `Number`, and `Dropdown`, the only elements where it makes sense. By [@aliabid94](https://github.com/aliabid94) in [PR 4916](https://github.com/gradio-app/gradio/pull/4916)
|
||||
- Fixed broken image link in auto-generated `app.py` from `ThemeClass.push_to_hub` by [@deepkyu](https://github.com/deepkyu) in [PR 4944](https://github.com/gradio-app/gradio/pull/4944)
|
||||
- The `.change()` event is fixed in `Video` and `Image` so that it only fires once by [@abidlabs](https://github.com/abidlabs) in [PR 4793](https://github.com/gradio-app/gradio/pull/4793)
|
||||
- The `.change()` event is fixed in `Audio` so that fires when the component value is programmatically updated by [@abidlabs](https://github.com/abidlabs) in [PR 4793](https://github.com/gradio-app/gradio/pull/4793)
|
||||
|
||||
* Add missing `display: flex` property to `Row` so that flex styling is applied to children by [@hannahblair] in [PR 4896](https://github.com/gradio-app/gradio/pull/4896)
|
||||
* Fixed bug where `gr.Video` could not preprocess urls by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4904](https://github.com/gradio-app/gradio/pull/4904)
|
||||
* Fixed copy button rendering in API page on Safari by [@aliabid94](https://github.com/aliabid94) in [PR 4924](https://github.com/gradio-app/gradio/pull/4924)
|
||||
* Fixed `gr.Group` and `container=False`. `container` parameter only available for `Textbox`, `Number`, and `Dropdown`, the only elements where it makes sense. By [@aliabid94](https://github.com/aliabid94) in [PR 4916](https://github.com/gradio-app/gradio/pull/4916)
|
||||
* Fixed broken image link in auto-generated `app.py` from `ThemeClass.push_to_hub` by [@deepkyu](https://github.com/deepkyu) in [PR 4944](https://github.com/gradio-app/gradio/pull/4944)
|
||||
|
||||
### Other Changes:
|
||||
|
||||
@ -172,7 +174,7 @@ No changes to highlight.
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
- Updated components with `info` attribute to update when `update()` is called on them. by [@jebarpg](https://github.com/jebarpg) in [PR 4715](https://github.com/gradio-app/gradio/pull/4715).
|
||||
- Updated components with `info` attribute to update when `update()` is called on them. by [@jebarpg](https://github.com/jebarpg) in [PR 4715](https://github.com/gradio-app/gradio/pull/4715).
|
||||
- Ensure the `Image` components undo button works mode is `mask` or `color-sketch` by [@amyorz](https://github.com/AmyOrz) in [PR 4692](https://github.com/gradio-app/gradio/pull/4692)
|
||||
- Load the iframe resizer external asset asynchronously, by [@akx](https://github.com/akx) in [PR 4336](https://github.com/gradio-app/gradio/pull/4336)
|
||||
- Restored missing imports in `gr.components` by [@abidlabs](https://github.com/abidlabs) in [PR 4566](https://github.com/gradio-app/gradio/pull/4566)
|
||||
@ -182,13 +184,13 @@ No changes to highlight.
|
||||
- Send captured data in `stop_recording` event for `gr.Audio` and `gr.Video` components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4554](https://github.com/gradio-app/gradio/pull/4554)
|
||||
- Fix bug in `gr.Gallery` where `height` and `object_fit` parameters where being ignored by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4576](https://github.com/gradio-app/gradio/pull/4576)
|
||||
- Fixes an HTML sanitization issue in DOMPurify where links in markdown were not opening in a new window by [@hannahblair] in [PR 4577](https://github.com/gradio-app/gradio/pull/4577)
|
||||
- Fixed Dropdown height rendering in Columns by [@aliabid94](https://github.com/aliabid94) in [PR 4584](https://github.com/gradio-app/gradio/pull/4584)
|
||||
- Fixed bug where `AnnotatedImage` css styling was causing the annotation masks to not be displayed correctly by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4628](https://github.com/gradio-app/gradio/pull/4628)
|
||||
- Fixed Dropdown height rendering in Columns by [@aliabid94](https://github.com/aliabid94) in [PR 4584](https://github.com/gradio-app/gradio/pull/4584)
|
||||
- Fixed bug where `AnnotatedImage` css styling was causing the annotation masks to not be displayed correctly by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4628](https://github.com/gradio-app/gradio/pull/4628)
|
||||
- Ensure that Gradio does not silently fail when running on a port that is occupied by [@abidlabs](https://github.com/abidlabs) in [PR 4624](https://github.com/gradio-app/gradio/pull/4624).
|
||||
- Fix double upload bug that caused lag in file uploads by [@aliabid94](https://github.com/aliabid94) in [PR 4661](https://github.com/gradio-app/gradio/pull/4661)
|
||||
- `Progress` component now appears even when no `iterable` is specified in `tqdm` constructor by [@itrushkin](https://github.com/itrushkin) in [PR 4475](https://github.com/gradio-app/gradio/pull/4475)
|
||||
- Deprecation warnings now point at the user code using those deprecated features, instead of Gradio internals, by (https://github.com/akx) in [PR 4694](https://github.com/gradio-app/gradio/pull/4694)
|
||||
- Adapt column widths in gr.Examples based on content by [@pngwn](https://github.com/pngwn) & [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4700](https://github.com/gradio-app/gradio/pull/4700)
|
||||
- Adapt column widths in gr.Examples based on content by [@pngwn](https://github.com/pngwn) & [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4700](https://github.com/gradio-app/gradio/pull/4700)
|
||||
- The `plot` parameter deprecation warnings should now only be emitted for `Image` components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4709](https://github.com/gradio-app/gradio/pull/4709)
|
||||
- Removed uncessessary `type` deprecation warning by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4709](https://github.com/gradio-app/gradio/pull/4709)
|
||||
- Ensure Audio autoplays works when `autoplay=True` and the video source is dynamically updated [@pngwn](https://github.com/pngwn) in [PR 4705](https://github.com/gradio-app/gradio/pull/4705)
|
||||
@ -282,11 +284,12 @@ demo.launch()
|
||||
- Allow any function to generate an error message and allow multiple messages to appear at a time. Other error modal improvements such as auto dismiss after a time limit and a new layout on mobile [@pngwn](https://github.com/pngwn) in [PR 4459](https://github.com/gradio-app/gradio/pull/4459).
|
||||
- Add `autoplay` kwarg to `Video` and `Audio` components by [@pngwn](https://github.com/pngwn) in [PR 4453](https://github.com/gradio-app/gradio/pull/4453)
|
||||
- Add `allow_preview` parameter to `Gallery` to control whether a detailed preview is displayed on click by
|
||||
[@freddyaboulton](https://github.com/freddyaboulton) in [PR 4470](https://github.com/gradio-app/gradio/pull/4470)
|
||||
[@freddyaboulton](https://github.com/freddyaboulton) in [PR 4470](https://github.com/gradio-app/gradio/pull/4470)
|
||||
- Add `latex_delimiters` parameter to `Chatbot` to control the delimiters used for LaTeX and to disable LaTeX in the `Chatbot` by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 4516](https://github.com/gradio-app/gradio/pull/4516)
|
||||
- Can now issue `gr.Warning` and `gr.Info` modals. Simply put the code `gr.Warning("Your warning message")` or `gr.Info("Your info message")` as a standalone line in your function. By [@aliabid94](https://github.com/aliabid94) in [PR 4518](https://github.com/gradio-app/gradio/pull/4518).
|
||||
- Can now issue `gr.Warning` and `gr.Info` modals. Simply put the code `gr.Warning("Your warning message")` or `gr.Info("Your info message")` as a standalone line in your function. By [@aliabid94](https://github.com/aliabid94) in [PR 4518](https://github.com/gradio-app/gradio/pull/4518).
|
||||
|
||||
Example:
|
||||
|
||||
```python
|
||||
def start_process(name):
|
||||
gr.Info("Starting process")
|
||||
@ -297,7 +300,6 @@ def start_process(name):
|
||||
raise gr.Error("Process failed")
|
||||
```
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
- Add support for PAUSED state in the JS client by [@abidlabs](https://github.com/abidlabs) in [PR 4438](https://github.com/gradio-app/gradio/pull/4438)
|
||||
@ -318,7 +320,7 @@ def start_process(name):
|
||||
|
||||
- Change styling of status and toast error components by [@hannahblair](https://github.com/hannahblair) in [PR 4454](https://github.com/gradio-app/gradio/pull/4454).
|
||||
- Clean up unnecessary `new Promise()`s by [@akx](https://github.com/akx) in [PR 4442](https://github.com/gradio-app/gradio/pull/4442).
|
||||
- Minor UI cleanup for Examples and Dataframe components [@aliabid94](https://github.com/aliabid94) in [PR 4455](https://github.com/gradio-app/gradio/pull/4455).
|
||||
- Minor UI cleanup for Examples and Dataframe components [@aliabid94](https://github.com/aliabid94) in [PR 4455](https://github.com/gradio-app/gradio/pull/4455).
|
||||
- Minor UI cleanup for Examples and Dataframe components [@aliabid94](https://github.com/aliabid94) in [PR 4455](https://github.com/gradio-app/gradio/pull/4455).
|
||||
- Add Catalan translation [@jordimas](https://github.com/jordimas) in [PR 4483](https://github.com/gradio-app/gradio/pull/4483).
|
||||
- The API endpoint that loads examples upon click has been given an explicit name ("/load_examples") by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456).
|
||||
@ -3624,4 +3626,4 @@ We've introduced a lot of new components in `3.0`, including `Model3D`, `Dataset
|
||||
- [@ronvoluted](https://github.com/ronvoluted) made their first contribution in [PR 1050](https://github.com/gradio-app/gradio/pull/1050)
|
||||
- [@radames](https://github.com/radames) made their first contribution in [PR 1074](https://github.com/gradio-app/gradio/pull/1074)
|
||||
- [@freddyaboulton](https://github.com/freddyaboulton) made their first contribution in [PR 1085](https://github.com/gradio-app/gradio/pull/1085)
|
||||
- [@liteli1987gmail](https://github.com/liteli1987gmail) & [@chenglu](https://github.com/chenglu) made their first contribution in [PR 4767](https://github.com/gradio-app/gradio/pull/4767)
|
||||
- [@liteli1987gmail](https://github.com/liteli1987gmail) & [@chenglu](https://github.com/chenglu) made their first contribution in [PR 4767](https://github.com/gradio-app/gradio/pull/4767)
|
||||
|
47
README.md
47
README.md
@ -2,22 +2,23 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="readme_files/gradio.svg" alt="gradio" width=300>](https://gradio.app)<br>
|
||||
<em>Build & share delightful machine learning apps easily</em>
|
||||
[<img src="readme_files/gradio.svg" alt="gradio" width=300>](https://gradio.app)<br>
|
||||
<em>Build & share delightful machine learning apps easily</em>
|
||||
|
||||
[](https://github.com/gradio-app/gradio/actions/workflows/backend.yml)
|
||||
[](https://github.com/gradio-app/gradio/actions/workflows/ui.yml)
|
||||
[](https://pypi.org/project/gradio/)
|
||||
[](https://pypi.org/project/gradio/)
|
||||

|
||||
[](https://twitter.com/gradio)
|
||||
[](https://github.com/gradio-app/gradio/actions/workflows/backend.yml)
|
||||
[](https://github.com/gradio-app/gradio/actions/workflows/ui.yml)
|
||||
[](https://pypi.org/project/gradio/)
|
||||
[](https://pypi.org/project/gradio/)
|
||||

|
||||
[](https://twitter.com/gradio)
|
||||
|
||||
[Website](https://gradio.app)
|
||||
| [Documentation](https://gradio.app/docs/)
|
||||
| [Guides](https://gradio.app/guides/)
|
||||
| [Getting Started](https://gradio.app/getting_started/)
|
||||
| [Examples](demo/)
|
||||
| [中文](readme_files/zh-cn#readme)
|
||||
|
||||
[Website](https://gradio.app)
|
||||
| [Documentation](https://gradio.app/docs/)
|
||||
| [Guides](https://gradio.app/guides/)
|
||||
| [Getting Started](https://gradio.app/getting_started/)
|
||||
| [Examples](demo/)
|
||||
| [中文](readme_files/zh-cn#readme)
|
||||
</div>
|
||||
|
||||
# Gradio: Build Machine Learning Web Apps — in Python
|
||||
@ -43,7 +44,7 @@ Gradio is useful for:
|
||||
|
||||
### What Does Gradio Do?
|
||||
|
||||
One of the *best ways to share* your machine learning model, API, or data science workflow with others is to create an **interactive app** that allows your users or colleagues to try out the demo in their browsers.
|
||||
One of the _best ways to share_ your machine learning model, API, or data science workflow with others is to create an **interactive app** that allows your users or colleagues to try out the demo in their browsers.
|
||||
|
||||
Gradio allows you to **build demos and share them, all in Python.** And usually in just a few lines of code! So let's get started.
|
||||
|
||||
@ -66,11 +67,10 @@ def greet(name):
|
||||
return "Hello " + name + "!"
|
||||
|
||||
demo = gr.Interface(fn=greet, inputs="text", outputs="text")
|
||||
|
||||
|
||||
demo.launch()
|
||||
```
|
||||
|
||||
|
||||
We shorten the imported name to `gr` for better readability of code using Gradio. This is a widely adopted convention that you should follow so that anyone working with your code can easily understand it.
|
||||
|
||||
3\. The demo below will appear automatically within the Jupyter Notebook, or pop in a browser on [http://localhost:7860](http://localhost:7860) if running from a script:
|
||||
@ -154,8 +154,8 @@ import gradio as gr
|
||||
|
||||
def sepia(input_img):
|
||||
sepia_filter = np.array([
|
||||
[0.393, 0.769, 0.189],
|
||||
[0.349, 0.686, 0.168],
|
||||
[0.393, 0.769, 0.189],
|
||||
[0.349, 0.686, 0.168],
|
||||
[0.272, 0.534, 0.131]
|
||||
])
|
||||
sepia_img = input_img.dot(sepia_filter.T)
|
||||
@ -184,8 +184,8 @@ You can read more about the many components and how to use them in the [Gradio d
|
||||
|
||||
Gradio includes a high-level class, `gr.ChatInterface`, which is similar to `gr.Interface`, but is specifically designed for chatbot UIs. The `gr.ChatInterface` class also wraps a function but this function must have a specific signature. The function should take two arguments: `message` and then `history` (the arguments can be named anything, but must be in this order)
|
||||
|
||||
* `message`: a `str` representing the user's input
|
||||
* `history`: a `list` of `list` representing the conversations up until that point. Each inner list consists of two `str` representing a pair: `[user input, bot response]`.
|
||||
- `message`: a `str` representing the user's input
|
||||
- `history`: a `list` of `list` representing the conversations up until that point. Each inner list consists of two `str` representing a pair: `[user input, bot response]`.
|
||||
|
||||
Your function should return a single string response, which is the bot's response to the particular user input `message`.
|
||||
|
||||
@ -232,7 +232,7 @@ with gr.Blocks() as demo:
|
||||
output = gr.Textbox(label="Output Box")
|
||||
greet_btn = gr.Button("Greet")
|
||||
greet_btn.click(fn=greet, inputs=name, outputs=output, api_name="greet")
|
||||
|
||||
|
||||
|
||||
demo.launch()
|
||||
```
|
||||
@ -289,7 +289,6 @@ A lot more going on here! We'll cover how to create complex `Blocks` apps like t
|
||||
|
||||
Congrats, you're now familiar with the basics of Gradio! 🥳 Go to our [next guide](https://gradio.app/key_features) to learn more about the key features of Gradio.
|
||||
|
||||
|
||||
## Open Source Stack
|
||||
|
||||
Gradio is built with many wonderful open-source libraries, please support them as well!
|
||||
@ -311,7 +310,7 @@ Gradio is licensed under the Apache License 2.0 found in the [LICENSE](LICENSE)
|
||||
|
||||
## Citation
|
||||
|
||||
Also check out the paper *[Gradio: Hassle-Free Sharing and Testing of ML Models in the Wild](https://arxiv.org/abs/1906.02569), ICML HILL 2019*, and please cite it if you use Gradio in your work.
|
||||
Also check out the paper _[Gradio: Hassle-Free Sharing and Testing of ML Models in the Wild](https://arxiv.org/abs/1906.02569), ICML HILL 2019_, and please cite it if you use Gradio in your work.
|
||||
|
||||
```
|
||||
@article{abid2019gradio,
|
||||
|
@ -65,8 +65,8 @@ Applications hosted on Hugging Face spaces can be in a number of different state
|
||||
import { client, type SpaceStatus } from "@gradio/client";
|
||||
|
||||
const app = await client("user/space-name", {
|
||||
// The space_status parameter does not need to be manually annotated, this is just for illustration.
|
||||
space_status: (space_status: SpaceStatus) => console.log(space_status),
|
||||
// The space_status parameter does not need to be manually annotated, this is just for illustration.
|
||||
space_status: (space_status: SpaceStatus) => console.log(space_status)
|
||||
});
|
||||
```
|
||||
|
||||
@ -157,22 +157,22 @@ The status payload look like this:
|
||||
|
||||
```ts
|
||||
interface Status {
|
||||
queue: boolean;
|
||||
code?: string;
|
||||
success?: boolean;
|
||||
stage: "pending" | "error" | "complete" | "generating";
|
||||
size?: number;
|
||||
position?: number;
|
||||
eta?: number;
|
||||
message?: string;
|
||||
progress_data?: Array<{
|
||||
progress: number | null;
|
||||
index: number | null;
|
||||
length: number | null;
|
||||
unit: string | null;
|
||||
desc: string | null;
|
||||
}>;
|
||||
time?: Date;
|
||||
queue: boolean;
|
||||
code?: string;
|
||||
success?: boolean;
|
||||
stage: "pending" | "error" | "complete" | "generating";
|
||||
size?: number;
|
||||
position?: number;
|
||||
eta?: number;
|
||||
message?: string;
|
||||
progress_data?: Array<{
|
||||
progress: number | null;
|
||||
index: number | null;
|
||||
length: number | null;
|
||||
unit: string | null;
|
||||
desc: string | null;
|
||||
}>;
|
||||
time?: Date;
|
||||
}
|
||||
```
|
||||
|
||||
@ -183,9 +183,9 @@ import { client } from "@gradio/client";
|
||||
|
||||
const app = await client("user/space-name");
|
||||
const submission = app
|
||||
.submit("/predict", payload)
|
||||
.on("data", (data) => console.log(data))
|
||||
.on("status", (status: Status) => console.log(status));
|
||||
.submit("/predict", payload)
|
||||
.on("data", (data) => console.log(data))
|
||||
.on("status", (status: Status) => console.log(status));
|
||||
```
|
||||
|
||||
##### `off`
|
||||
@ -229,8 +229,8 @@ import { client } from "@gradio/client";
|
||||
|
||||
const app = await client("user/space-name");
|
||||
const submission = app
|
||||
.submit("/predict", payload)
|
||||
.on("data", (data) => console.log(data));
|
||||
.submit("/predict", payload)
|
||||
.on("data", (data) => console.log(data));
|
||||
|
||||
// later
|
||||
|
||||
@ -271,7 +271,7 @@ The duplicate function will attempt to duplicate the space that is referenced an
|
||||
import { duplicate } from "@gradio/client";
|
||||
|
||||
const app = await duplicate("user/space-name", {
|
||||
hf_token: "hf_...",
|
||||
hf_token: "hf_..."
|
||||
});
|
||||
```
|
||||
|
||||
@ -295,8 +295,8 @@ This is an optional property specific to `duplicate`'s options object and will d
|
||||
import { duplicate } from "@gradio/client";
|
||||
|
||||
const app = await duplicate("user/space-name", {
|
||||
hf_token: "hf_...",
|
||||
private: true,
|
||||
hf_token: "hf_...",
|
||||
private: true
|
||||
});
|
||||
```
|
||||
|
||||
@ -308,9 +308,9 @@ This is an optional property specific to `duplicate`'s options object and will s
|
||||
import { duplicate } from "@gradio/client";
|
||||
|
||||
const app = await duplicate("user/space-name", {
|
||||
hf_token: "hf_...",
|
||||
private: true,
|
||||
timeout: 5,
|
||||
hf_token: "hf_...",
|
||||
private: true,
|
||||
timeout: 5
|
||||
});
|
||||
```
|
||||
|
||||
@ -332,8 +332,8 @@ Possible hardware options are:
|
||||
import { duplicate } from "@gradio/client";
|
||||
|
||||
const app = await duplicate("user/space-name", {
|
||||
hf_token: "hf_...",
|
||||
private: true,
|
||||
hardware: "a10g-small",
|
||||
hf_token: "hf_...",
|
||||
private: true,
|
||||
hardware: "a10g-small"
|
||||
});
|
||||
```
|
||||
|
@ -69,7 +69,7 @@ export async function duplicate(
|
||||
hardware?: (typeof hardware_types)[number];
|
||||
timeout?: number;
|
||||
}
|
||||
) {
|
||||
): Promise<client_return> {
|
||||
const { hf_token, private: _private, hardware, timeout } = options;
|
||||
|
||||
if (hardware && !hardware_types.includes(hardware)) {
|
||||
@ -115,38 +115,57 @@ export async function duplicate(
|
||||
|
||||
if (response.status === 409) {
|
||||
return client(`${user}/${space_name}`, options);
|
||||
} else {
|
||||
const duplicated_space = await response.json();
|
||||
|
||||
let original_hardware;
|
||||
|
||||
if (!hardware) {
|
||||
original_hardware = await get_space_hardware(app_reference, hf_token);
|
||||
}
|
||||
|
||||
const requested_hardware = hardware || original_hardware || "cpu-basic";
|
||||
await set_space_hardware(
|
||||
`${user}/${space_name}`,
|
||||
requested_hardware,
|
||||
hf_token
|
||||
);
|
||||
|
||||
await set_space_timeout(
|
||||
`${user}/${space_name}`,
|
||||
timeout || 300,
|
||||
hf_token
|
||||
);
|
||||
return client(duplicated_space.url, options);
|
||||
}
|
||||
const duplicated_space = await response.json();
|
||||
|
||||
let original_hardware;
|
||||
|
||||
if (!hardware) {
|
||||
original_hardware = await get_space_hardware(app_reference, hf_token);
|
||||
}
|
||||
|
||||
const requested_hardware = hardware || original_hardware || "cpu-basic";
|
||||
await set_space_hardware(
|
||||
`${user}/${space_name}`,
|
||||
requested_hardware,
|
||||
hf_token
|
||||
);
|
||||
|
||||
await set_space_timeout(`${user}/${space_name}`, timeout || 300, hf_token);
|
||||
return client(duplicated_space.url, options);
|
||||
} catch (e: any) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to inject a customized fetch implementation for the Wasm version.
|
||||
*/
|
||||
export function api_factory(fetch_implementation: typeof fetch) {
|
||||
interface Client {
|
||||
post_data: (
|
||||
url: string,
|
||||
body: unknown,
|
||||
token?: `hf_${string}`
|
||||
) => Promise<[PostResponse, number]>;
|
||||
upload_files: (
|
||||
root: string,
|
||||
files: File[],
|
||||
token?: `hf_${string}`
|
||||
) => Promise<UploadResponse>;
|
||||
client: (
|
||||
app_reference: string,
|
||||
options: {
|
||||
hf_token?: `hf_${string}`;
|
||||
status_callback?: SpaceStatusCallback;
|
||||
normalise_files?: boolean;
|
||||
}
|
||||
) => Promise<client_return>;
|
||||
handle_blob: (
|
||||
endpoint: string,
|
||||
data: unknown[],
|
||||
api_info: ApiInfo<JsApiData>,
|
||||
token?: `hf_${string}`
|
||||
) => Promise<unknown[]>;
|
||||
}
|
||||
|
||||
export function api_factory(fetch_implementation: typeof fetch): Client {
|
||||
return { post_data, upload_files, client, handle_blob };
|
||||
|
||||
async function post_data(
|
||||
@ -176,7 +195,7 @@ export function api_factory(fetch_implementation: typeof fetch) {
|
||||
|
||||
async function upload_files(
|
||||
root: string,
|
||||
files: Array<File>,
|
||||
files: (Blob | File)[],
|
||||
token?: `hf_${string}`
|
||||
): Promise<UploadResponse> {
|
||||
const headers: {
|
||||
@ -247,7 +266,7 @@ export function api_factory(fetch_implementation: typeof fetch) {
|
||||
jwt = await get_jwt(space_id, hf_token);
|
||||
}
|
||||
|
||||
async function config_success(_config: Config) {
|
||||
async function config_success(_config: Config): Promise<client_return> {
|
||||
config = _config;
|
||||
api_map = map_names_to_ids(_config?.dependencies || []);
|
||||
try {
|
||||
@ -262,7 +281,7 @@ export function api_factory(fetch_implementation: typeof fetch) {
|
||||
};
|
||||
}
|
||||
let api: ApiInfo<JsApiData>;
|
||||
async function handle_space_sucess(status: SpaceStatus) {
|
||||
async function handle_space_sucess(status: SpaceStatus): Promise<void> {
|
||||
if (status_callback) status_callback(status);
|
||||
if (status.status === "running")
|
||||
try {
|
||||
@ -315,17 +334,11 @@ export function api_factory(fetch_implementation: typeof fetch) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a prediction.
|
||||
* @param endpoint - The prediction endpoint to use.
|
||||
* @param status_callback - A function that is called with the current status of the prediction immediately and every time it updates.
|
||||
* @return Returns the data for the prediction or an error message.
|
||||
*/
|
||||
function predict(
|
||||
endpoint: string,
|
||||
data: unknown[],
|
||||
event_data?: unknown
|
||||
) {
|
||||
): Promise<unknown> {
|
||||
let data_returned = false;
|
||||
let status_complete = false;
|
||||
return new Promise((res, rej) => {
|
||||
@ -579,7 +592,7 @@ export function api_factory(fetch_implementation: typeof fetch) {
|
||||
}
|
||||
});
|
||||
|
||||
function fire_event<K extends EventType>(event: Event<K>) {
|
||||
function fire_event<K extends EventType>(event: Event<K>): void {
|
||||
const narrowed_listener_map: ListenerMap<K> = listener_map;
|
||||
const listeners = narrowed_listener_map[event.type] || [];
|
||||
listeners?.forEach((l) => l(event));
|
||||
@ -588,7 +601,7 @@ export function api_factory(fetch_implementation: typeof fetch) {
|
||||
function on<K extends EventType>(
|
||||
eventType: K,
|
||||
listener: EventListener<K>
|
||||
) {
|
||||
): SubmitReturn {
|
||||
const narrowed_listener_map: ListenerMap<K> = listener_map;
|
||||
const listeners = narrowed_listener_map[eventType] || [];
|
||||
narrowed_listener_map[eventType] = listeners;
|
||||
@ -600,7 +613,7 @@ export function api_factory(fetch_implementation: typeof fetch) {
|
||||
function off<K extends EventType>(
|
||||
eventType: K,
|
||||
listener: EventListener<K>
|
||||
) {
|
||||
): SubmitReturn {
|
||||
const narrowed_listener_map: ListenerMap<K> = listener_map;
|
||||
let listeners = narrowed_listener_map[eventType] || [];
|
||||
listeners = listeners?.filter((l) => l !== listener);
|
||||
@ -609,7 +622,7 @@ export function api_factory(fetch_implementation: typeof fetch) {
|
||||
return { on, off, cancel, destroy };
|
||||
}
|
||||
|
||||
async function cancel() {
|
||||
async function cancel(): Promise<void> {
|
||||
const _status: Status = {
|
||||
stage: "complete",
|
||||
queue: false,
|
||||
@ -647,7 +660,7 @@ export function api_factory(fetch_implementation: typeof fetch) {
|
||||
}
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
function destroy(): void {
|
||||
for (const event_type in listener_map) {
|
||||
listener_map[event_type as "data" | "status"].forEach((fn) => {
|
||||
off(event_type as "data" | "status", fn);
|
||||
@ -720,7 +733,7 @@ export function api_factory(fetch_implementation: typeof fetch) {
|
||||
async function handle_blob(
|
||||
endpoint: string,
|
||||
data: unknown[],
|
||||
api_info,
|
||||
api_info: ApiInfo<JsApiData>,
|
||||
token?: `hf_${string}`
|
||||
): Promise<unknown[]> {
|
||||
const blob_refs = await walk_and_store_blobs(
|
||||
@ -737,9 +750,8 @@ export function api_factory(fetch_implementation: typeof fetch) {
|
||||
const file_url = (await upload_files(endpoint, [blob], token))
|
||||
.files[0];
|
||||
return { path, file_url, type };
|
||||
} else {
|
||||
return { path, base64: data, type };
|
||||
}
|
||||
return { path, base64: data, type };
|
||||
})
|
||||
).then((r) => {
|
||||
r.forEach(({ path, file_url, base64, type }) => {
|
||||
@ -783,17 +795,16 @@ function transform_output(
|
||||
});
|
||||
} else if (typeof d === "object" && d?.is_file) {
|
||||
return normalise_file(d, root_url, remote_url);
|
||||
} else {
|
||||
return d;
|
||||
}
|
||||
return d;
|
||||
});
|
||||
}
|
||||
|
||||
function normalise_file(
|
||||
file: Array<FileData>,
|
||||
file: FileData[],
|
||||
root: string,
|
||||
root_url: string | null
|
||||
): Array<FileData>;
|
||||
): FileData[];
|
||||
function normalise_file(
|
||||
file: FileData | string,
|
||||
root: string,
|
||||
@ -804,11 +815,7 @@ function normalise_file(
|
||||
root: string,
|
||||
root_url: string | null
|
||||
): null;
|
||||
function normalise_file(
|
||||
file,
|
||||
root,
|
||||
root_url
|
||||
): Array<FileData> | FileData | null {
|
||||
function normalise_file(file, root, root_url): FileData[] | FileData | null {
|
||||
if (file == null) return null;
|
||||
if (typeof file === "string") {
|
||||
return {
|
||||
@ -816,7 +823,7 @@ function normalise_file(
|
||||
data: file
|
||||
};
|
||||
} else if (Array.isArray(file)) {
|
||||
const normalized_file: Array<FileData | null> = [];
|
||||
const normalized_file: (FileData | null)[] = [];
|
||||
|
||||
for (const x of file) {
|
||||
if (x === null) {
|
||||
@ -826,7 +833,7 @@ function normalise_file(
|
||||
}
|
||||
}
|
||||
|
||||
return normalized_file as Array<FileData>;
|
||||
return normalized_file as FileData[];
|
||||
} else if (file.is_file) {
|
||||
if (!root_url) {
|
||||
file.data = root + "/file=" + file.name;
|
||||
@ -872,7 +879,7 @@ function get_type(
|
||||
component: string,
|
||||
serializer: string,
|
||||
signature_type: "return" | "parameter"
|
||||
) {
|
||||
): string {
|
||||
switch (type.type) {
|
||||
case "string":
|
||||
return "string";
|
||||
@ -896,11 +903,10 @@ function get_type(
|
||||
return signature_type === "parameter"
|
||||
? "(Blob | File | Buffer)[]"
|
||||
: `{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}[]`;
|
||||
} else {
|
||||
return signature_type === "parameter"
|
||||
? "Blob | File | Buffer"
|
||||
: `{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}`;
|
||||
}
|
||||
return signature_type === "parameter"
|
||||
? "Blob | File | Buffer"
|
||||
: `{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}`;
|
||||
} else if (serializer === "GallerySerializable") {
|
||||
return signature_type === "parameter"
|
||||
? "[(Blob | File | Buffer), (string | null)][]"
|
||||
@ -911,16 +917,15 @@ function get_type(
|
||||
function get_description(
|
||||
type: { type: any; description: string },
|
||||
serializer: string
|
||||
) {
|
||||
): string {
|
||||
if (serializer === "GallerySerializable") {
|
||||
return "array of [file, label] tuples";
|
||||
} else if (serializer === "ListStringSerializable") {
|
||||
return "array of strings";
|
||||
} else if (serializer === "FileSerializable") {
|
||||
return "array of files or single file";
|
||||
} else {
|
||||
return type.description;
|
||||
}
|
||||
return type.description;
|
||||
}
|
||||
|
||||
function transform_api_info(
|
||||
@ -988,7 +993,7 @@ async function get_jwt(
|
||||
}
|
||||
}
|
||||
|
||||
function update_object(object, newValue, stack) {
|
||||
function update_object(object, newValue, stack): void {
|
||||
while (stack.length > 1) {
|
||||
object = object[stack.shift()];
|
||||
}
|
||||
@ -1002,7 +1007,14 @@ export async function walk_and_store_blobs(
|
||||
path = [],
|
||||
root = false,
|
||||
api_info = undefined
|
||||
) {
|
||||
): Promise<
|
||||
{
|
||||
path: string[];
|
||||
data: string | false;
|
||||
type: string;
|
||||
blob: Blob | false;
|
||||
}[]
|
||||
> {
|
||||
if (Array.isArray(param)) {
|
||||
let blob_refs = [];
|
||||
|
||||
@ -1049,10 +1061,9 @@ export async function walk_and_store_blobs(
|
||||
data = Buffer.from(buffer).toString("base64");
|
||||
}
|
||||
|
||||
return [{ path, data, type }];
|
||||
} else {
|
||||
return [{ path: path, blob: param, type }];
|
||||
return [{ path, data, type, blob: false }];
|
||||
}
|
||||
return [{ path: path, blob: param, type, data: false }];
|
||||
} else if (typeof param === "object") {
|
||||
let blob_refs = [];
|
||||
for (let key in param) {
|
||||
@ -1071,12 +1082,11 @@ export async function walk_and_store_blobs(
|
||||
}
|
||||
}
|
||||
return blob_refs;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function image_to_data_uri(blob: Blob) {
|
||||
function image_to_data_uri(blob: Blob): Promise<string | ArrayBuffer> {
|
||||
return new Promise((resolve, _) => {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => resolve(reader.result);
|
||||
@ -1084,7 +1094,7 @@ function image_to_data_uri(blob: Blob) {
|
||||
});
|
||||
}
|
||||
|
||||
function skip_queue(id: number, config: Config) {
|
||||
function skip_queue(id: number, config: Config): boolean {
|
||||
return (
|
||||
!(config?.dependencies?.[id]?.queue === null
|
||||
? config.enable_queue
|
||||
@ -1120,9 +1130,8 @@ async function resolve_config(
|
||||
config.path = config.path ?? "";
|
||||
config.root = endpoint;
|
||||
return config;
|
||||
} else {
|
||||
throw new Error("Could not get config.");
|
||||
}
|
||||
throw new Error("Could not get config.");
|
||||
}
|
||||
|
||||
throw new Error("No config or app endpoint found");
|
||||
@ -1132,7 +1141,7 @@ async function check_space_status(
|
||||
id: string,
|
||||
type: "subdomain" | "space_name",
|
||||
status_callback: SpaceStatusCallback
|
||||
) {
|
||||
): Promise<void> {
|
||||
let endpoint =
|
||||
type === "subdomain"
|
||||
? `https://huggingface.co/api/spaces/by-subdomain/${id}`
|
||||
@ -1297,20 +1306,19 @@ function handle_message(
|
||||
success: data.success
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: "complete",
|
||||
status: {
|
||||
queue,
|
||||
message: !data.success ? data.output.error : undefined,
|
||||
stage: data.success ? "complete" : "error",
|
||||
code: data.code,
|
||||
progress_data: data.progress_data,
|
||||
eta: data.output.average_duration
|
||||
},
|
||||
data: data.success ? data.output : null
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: "complete",
|
||||
status: {
|
||||
queue,
|
||||
message: !data.success ? data.output.error : undefined,
|
||||
stage: data.success ? "complete" : "error",
|
||||
code: data.code,
|
||||
progress_data: data.progress_data,
|
||||
eta: data.output.average_duration
|
||||
},
|
||||
data: data.success ? data.output : null
|
||||
};
|
||||
|
||||
case "process_starts":
|
||||
return {
|
||||
|
3
client/js/src/globals.d.ts
vendored
3
client/js/src/globals.d.ts
vendored
@ -1,10 +1,7 @@
|
||||
declare global {
|
||||
interface Window {
|
||||
__gradio_mode__: "app" | "website";
|
||||
launchGradio: Function;
|
||||
launchGradioFromSpaces: Function;
|
||||
gradio_config: Config;
|
||||
scoped_css_attach: (link: HTMLLinkElement) => void;
|
||||
__is_colab__: boolean;
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ export interface Config {
|
||||
}
|
||||
|
||||
export interface Payload {
|
||||
data: Array<unknown>;
|
||||
data: unknown[];
|
||||
fn_index?: number;
|
||||
event_data?: unknown;
|
||||
time?: Date;
|
||||
@ -33,7 +33,7 @@ export interface PostResponse {
|
||||
}
|
||||
export interface UploadResponse {
|
||||
error?: string;
|
||||
files?: Array<string>;
|
||||
files?: string[];
|
||||
}
|
||||
|
||||
export interface Status {
|
||||
@ -46,13 +46,13 @@ export interface Status {
|
||||
position?: number;
|
||||
eta?: number;
|
||||
message?: string;
|
||||
progress_data?: Array<{
|
||||
progress_data?: {
|
||||
progress: number | null;
|
||||
index: number | null;
|
||||
length: number | null;
|
||||
unit: string | null;
|
||||
desc: string | null;
|
||||
}>;
|
||||
}[];
|
||||
time?: Date;
|
||||
}
|
||||
|
||||
|
@ -14,13 +14,12 @@ export function determine_protocol(endpoint: string): {
|
||||
host: host,
|
||||
http_protocol: protocol as "http:" | "https:"
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
ws_protocol: protocol === "https:" ? "wss" : "ws",
|
||||
http_protocol: protocol as "http:" | "https:",
|
||||
host
|
||||
};
|
||||
}
|
||||
return {
|
||||
ws_protocol: protocol === "https:" ? "wss" : "ws",
|
||||
http_protocol: protocol as "http:" | "https:",
|
||||
host
|
||||
};
|
||||
}
|
||||
|
||||
// default to secure if no protocol is provided
|
||||
@ -87,7 +86,9 @@ export async function process_endpoint(
|
||||
};
|
||||
}
|
||||
|
||||
export function map_names_to_ids(fns: Config["dependencies"]) {
|
||||
export function map_names_to_ids(
|
||||
fns: Config["dependencies"]
|
||||
): Record<string, number> {
|
||||
let apis: Record<string, number> = {};
|
||||
|
||||
fns.forEach(({ api_name }, i) => {
|
||||
@ -99,7 +100,7 @@ export function map_names_to_ids(fns: Config["dependencies"]) {
|
||||
|
||||
const RE_DISABLED_DISCUSSION =
|
||||
/^(?=[^]*\b[dD]iscussions{0,1}\b)(?=[^]*\b[dD]isabled\b)[^]*$/;
|
||||
export async function discussions_enabled(space_id: string) {
|
||||
export async function discussions_enabled(space_id: string): Promise<boolean> {
|
||||
try {
|
||||
const r = await fetch(
|
||||
`https://huggingface.co/api/spaces/${space_id}/discussions`,
|
||||
@ -110,7 +111,7 @@ export async function discussions_enabled(space_id: string) {
|
||||
const error = r.headers.get("x-error-message");
|
||||
|
||||
if (error && RE_DISABLED_DISCUSSION.test(error)) return false;
|
||||
else return true;
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
@ -119,7 +120,7 @@ export async function discussions_enabled(space_id: string) {
|
||||
export async function get_space_hardware(
|
||||
space_id: string,
|
||||
token: `hf_${string}`
|
||||
) {
|
||||
): Promise<(typeof hardware_types)[number]> {
|
||||
const headers: { Authorization?: string } = {};
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
@ -146,7 +147,7 @@ export async function set_space_hardware(
|
||||
space_id: string,
|
||||
new_hardware: (typeof hardware_types)[number],
|
||||
token: `hf_${string}`
|
||||
) {
|
||||
): Promise<(typeof hardware_types)[number]> {
|
||||
const headers: { Authorization?: string } = {};
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
@ -175,7 +176,7 @@ export async function set_space_timeout(
|
||||
space_id: string,
|
||||
timeout: number,
|
||||
token: `hf_${string}`
|
||||
) {
|
||||
): Promise<number> {
|
||||
const headers: { Authorization?: string } = {};
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
|
@ -6,11 +6,12 @@
|
||||
|
||||
#### Create Discord Bots from Gradio Apps 🤖 ([#4960](https://github.com/gradio-app/gradio/pull/4960) [`46e4ef67`](https://github.com/gradio-app/gradio/commit/46e4ef67d287dd68a91473b73172b29cbad064bc))
|
||||
|
||||
We're excited to announce that Gradio can now automatically create a discord bot from any `gr.ChatInterface` app.
|
||||
We're excited to announce that Gradio can now automatically create a discord bot from any `gr.ChatInterface` app.
|
||||
|
||||
It's as easy as importing `gradio_client`, connecting to the app, and calling `deploy_discord`!
|
||||
|
||||
*🦙 Turning Llama 2 70b into a discord bot 🦙*
|
||||
_🦙 Turning Llama 2 70b into a discord bot 🦙_
|
||||
|
||||
```python
|
||||
import gradio_client as grc
|
||||
grc.Client("ysharma/Explore_llamav2_with_TGI").deploy_discord(to_id="llama2-70b-discord-bot")
|
||||
@ -24,23 +25,22 @@ To help get you started, we have created an organization on Hugging Face called
|
||||
|
||||
Currently we have template spaces for:
|
||||
|
||||
* [Llama-2-70b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) powered by a FREE Hugging Face Inference Endpoint!
|
||||
* [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.
|
||||
* [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.
|
||||
* [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.
|
||||
* [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Requires an OpenAI key.
|
||||
- [Llama-2-70b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) powered by a FREE Hugging Face Inference Endpoint!
|
||||
- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.
|
||||
- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.
|
||||
- [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.
|
||||
- [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Requires an OpenAI key.
|
||||
|
||||
But once again, you can deploy ANY `gr.ChatInterface` app exposed on the internet! So don't hesitate to try it on your own Chatbots.
|
||||
|
||||
❗️ Additional Note ❗️: Technically, any gradio app that exposes an api route that takes in a single string and outputs a single string can be deployed to discord. But `gr.ChatInterface` apps naturally lend themselves to discord's chat functionality so we suggest you start with those.
|
||||
|
||||
Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
|
||||
Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
|
||||
|
||||
### New Features:
|
||||
|
||||
- Endpoints that return layout components are now properly handled in the `submit` and `view_api` methods. Output layout components are not returned by the API but all other components are (excluding `gr.State`). By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4871](https://github.com/gradio-app/gradio/pull/4871)
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
No changes to highlight
|
||||
@ -69,7 +69,7 @@ No changes to highlight.
|
||||
|
||||
### Full Changelog:
|
||||
|
||||
* Pinned dependencies to major versions to reduce the likelihood of a broken `gradio_client` due to changes in downstream dependencies by [@abidlabs](https://github.com/abidlabs) in [PR 4885](https://github.com/gradio-app/gradio/pull/4885)
|
||||
- Pinned dependencies to major versions to reduce the likelihood of a broken `gradio_client` due to changes in downstream dependencies by [@abidlabs](https://github.com/abidlabs) in [PR 4885](https://github.com/gradio-app/gradio/pull/4885)
|
||||
|
||||
# 0.2.8
|
||||
|
||||
@ -149,6 +149,7 @@ No changes to highlight.
|
||||
# 0.2.4
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
- Fixes missing serialization classes for several components: `Barplot`, `Lineplot`, `Scatterplot`, `AnnotatedImage`, `Interpretation` by [@abidlabs](https://github.com/abidlabs) in [PR 4167](https://github.com/gradio-app/gradio/pull/4167)
|
||||
|
||||
### Documentation Changes:
|
||||
@ -178,6 +179,7 @@ No changes to highlight.
|
||||
No changes to highlight.
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
- Fix example inputs for `gr.File(file_count='multiple')` output components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4153](https://github.com/gradio-app/gradio/pull/4153)
|
||||
|
||||
### Documentation Changes:
|
||||
@ -210,17 +212,14 @@ No changes to highlight.
|
||||
|
||||
- Only send request to `/info` route if demo version is above `3.28.3` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4109](https://github.com/gradio-app/gradio/pull/4109)
|
||||
|
||||
|
||||
### Other Changes:
|
||||
|
||||
- Fix bug in test from gradio 3.29.0 refactor by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4138](https://github.com/gradio-app/gradio/pull/4138)
|
||||
|
||||
|
||||
### Breaking Changes:
|
||||
|
||||
No changes to highlight.
|
||||
|
||||
|
||||
# 0.2.1
|
||||
|
||||
### New Features:
|
||||
@ -239,7 +238,6 @@ No changes to highlight.
|
||||
|
||||
Separates flaky tests from non-flaky tests by [@abidlabs](https://github.com/freddyaboulton) in [PR 4107](https://github.com/gradio-app/gradio/pull/4107)
|
||||
|
||||
|
||||
### Breaking Changes:
|
||||
|
||||
No changes to highlight.
|
||||
@ -314,7 +312,7 @@ No changes to highlight.
|
||||
|
||||
# 0.1.2
|
||||
|
||||
First public release of the Gradio Client library! The `gradio_client` Python library that makes it very easy to use any Gradio app as an API.
|
||||
First public release of the Gradio Client library! The `gradio_client` Python library that makes it very easy to use any Gradio app as an API.
|
||||
|
||||
As an example, consider this [Hugging Face Space that transcribes audio files](https://huggingface.co/spaces/abidlabs/whisper) that are recorded from the microphone.
|
||||
|
||||
@ -327,10 +325,10 @@ Here's the entire code to do it:
|
||||
```python
|
||||
from gradio_client import Client
|
||||
|
||||
client = Client("abidlabs/whisper")
|
||||
client.predict("audio_sample.wav")
|
||||
client = Client("abidlabs/whisper")
|
||||
client.predict("audio_sample.wav")
|
||||
|
||||
>> "This is a test of the whisper speech recognition model."
|
||||
```
|
||||
|
||||
Read more about how to use the `gradio_client` library here: https://gradio.app/getting-started-with-the-python-client/
|
||||
Read more about how to use the `gradio_client` library here: https://gradio.app/getting-started-with-the-python-client/
|
||||
|
@ -1,6 +1,6 @@
|
||||
# `gradio_client`: Use a Gradio app as an API -- in 3 lines of Python
|
||||
|
||||
This directory contains the source code for `gradio_client`, a lightweight Python library that makes it very easy to use any Gradio app as an API.
|
||||
This directory contains the source code for `gradio_client`, a lightweight Python library that makes it very easy to use any Gradio app as an API.
|
||||
|
||||
As an example, consider this [Hugging Face Space that transcribes audio files](https://huggingface.co/spaces/abidlabs/whisper) that are recorded from the microphone.
|
||||
|
||||
@ -13,8 +13,8 @@ Here's the entire code to do it:
|
||||
```python
|
||||
from gradio_client import Client
|
||||
|
||||
client = Client("abidlabs/whisper")
|
||||
client.predict("audio_sample.wav")
|
||||
client = Client("abidlabs/whisper")
|
||||
client.predict("audio_sample.wav")
|
||||
|
||||
>> "This is a test of the whisper speech recognition model."
|
||||
```
|
||||
@ -23,7 +23,7 @@ The Gradio client works with any Gradio Space, whether it be an image generator,
|
||||
|
||||
## Installation
|
||||
|
||||
If you already have a recent version of `gradio`, then the `gradio_client` is included as a dependency.
|
||||
If you already have a recent version of `gradio`, then the `gradio_client` is included as a dependency.
|
||||
|
||||
Otherwise, the lightweight `gradio_client` package can be installed from pip (or pip3) and works with Python versions 3.8 or higher:
|
||||
|
||||
@ -50,7 +50,7 @@ You can also connect to private Spaces by passing in your HF token with the `hf_
|
||||
```python
|
||||
from gradio_client import Client
|
||||
|
||||
client = Client("abidlabs/my-private-space", hf_token="...")
|
||||
client = Client("abidlabs/my-private-space", hf_token="...")
|
||||
```
|
||||
|
||||
**Duplicating a Space for private use**
|
||||
@ -63,17 +63,16 @@ The `gradio_client` includes a class method: `Client.duplicate()` to make this p
|
||||
```python
|
||||
from gradio_client import Client
|
||||
|
||||
client = Client.duplicate("abidlabs/whisper")
|
||||
client.predict("audio_sample.wav")
|
||||
client = Client.duplicate("abidlabs/whisper")
|
||||
client.predict("audio_sample.wav")
|
||||
|
||||
>> "This is a test of the whisper speech recognition model."
|
||||
```
|
||||
|
||||
If you have previously duplicated a Space, re-running `duplicate()` will *not* create a new Space. Instead, the Client will attach to the previously-created Space. So it is safe to re-run the `Client.duplicate()` method multiple times.
|
||||
If you have previously duplicated a Space, re-running `duplicate()` will _not_ create a new Space. Instead, the Client will attach to the previously-created Space. So it is safe to re-run the `Client.duplicate()` method multiple times.
|
||||
|
||||
**Note:** if the original Space uses GPUs, your private Space will as well, and your Hugging Face account will get billed based on the price of the GPU. To minimize charges, your Space will automatically go to sleep after 1 hour of inactivity. You can also set the hardware using the `hardware` parameter of `duplicate()`.
|
||||
|
||||
|
||||
**Connecting a general Gradio app**
|
||||
|
||||
If your app is running somewhere else, just provide the full URL instead, including the "http://" or "https://". Here's an example of making predictions to a Gradio app that is running on a share URL:
|
||||
@ -84,7 +83,6 @@ from gradio_client import Client
|
||||
client = Client("https://bec81a83-5b5c-471e.gradio.live")
|
||||
```
|
||||
|
||||
|
||||
### Inspecting the API endpoints
|
||||
|
||||
Once you have connected to a Gradio app, you can view the APIs that are available to you by calling the `.view_api()` method. For the Whisper Space, we see the following:
|
||||
@ -101,11 +99,10 @@ Named API endpoints: 1
|
||||
- [Textbox] value_0: str (value)
|
||||
```
|
||||
|
||||
This shows us that we have 1 API endpoint in this space, and shows us how to use the API endpoint to make a prediction: we should call the `.predict()` method, providing a parameter `input_audio` of type `str`, which is a `filepath or URL`.
|
||||
This shows us that we have 1 API endpoint in this space, and shows us how to use the API endpoint to make a prediction: we should call the `.predict()` method, providing a parameter `input_audio` of type `str`, which is a `filepath or URL`.
|
||||
|
||||
We should also provide the `api_name='/predict'` argument. Although this isn't necessary if a Gradio app has a single named endpoint, it does allow us to call different endpoints in a single app if they are available. If an app has unnamed API endpoints, these can also be displayed by running `.view_api(all_endpoints=True)`.
|
||||
|
||||
|
||||
### Making a prediction
|
||||
|
||||
The simplest way to make a prediction is simply to call the `.predict()` function with the appropriate arguments:
|
||||
@ -121,7 +118,6 @@ client.predict("Hello")
|
||||
|
||||
If there are multiple parameters, then you should pass them as separate arguments to `.predict()`, like this:
|
||||
|
||||
|
||||
```python
|
||||
from gradio_client import Client
|
||||
|
||||
@ -131,7 +127,7 @@ client.predict(4, "add", 5)
|
||||
>> 9.0
|
||||
```
|
||||
|
||||
For certain inputs, such as images, you should pass in the filepath or URL to the file. Likewise, for the corresponding output types, you will get a filepath or URL returned.
|
||||
For certain inputs, such as images, you should pass in the filepath or URL to the file. Likewise, for the corresponding output types, you will get a filepath or URL returned.
|
||||
|
||||
```python
|
||||
from gradio_client import Client
|
||||
@ -142,7 +138,6 @@ client.predict("https://audio-samples.github.io/samples/mp3/blizzard_uncondition
|
||||
>> "My thought I have nobody by a beauty and will as you poured. Mr. Rochester is serve in that so don't find simpus, and devoted abode, to at might in a r—"
|
||||
```
|
||||
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
For more ways to use the Gradio Python Client, check out our dedicated Guide on the Python client, available here: https://www.gradio.app/getting-started-with-the-python-client/
|
||||
For more ways to use the Gradio Python Client, check out our dedicated Guide on the Python client, available here: https://www.gradio.app/getting-started-with-the-python-client/
|
||||
|
@ -6,11 +6,12 @@
|
||||
|
||||
#### Create Discord Bots from Gradio Apps 🤖 ([#4960](https://github.com/gradio-app/gradio/pull/4960) [`46e4ef67`](https://github.com/gradio-app/gradio/commit/46e4ef67d287dd68a91473b73172b29cbad064bc))
|
||||
|
||||
We're excited to announce that Gradio can now automatically create a discord bot from any `gr.ChatInterface` app.
|
||||
We're excited to announce that Gradio can now automatically create a discord bot from any `gr.ChatInterface` app.
|
||||
|
||||
It's as easy as importing `gradio_client`, connecting to the app, and calling `deploy_discord`!
|
||||
|
||||
*🦙 Turning Llama 2 70b into a discord bot 🦙*
|
||||
_🦙 Turning Llama 2 70b into a discord bot 🦙_
|
||||
|
||||
```python
|
||||
import gradio_client as grc
|
||||
grc.Client("ysharma/Explore_llamav2_with_TGI").deploy_discord(to_id="llama2-70b-discord-bot")
|
||||
@ -24,23 +25,22 @@ To help get you started, we have created an organization on Hugging Face called
|
||||
|
||||
Currently we have template spaces for:
|
||||
|
||||
* [Llama-2-70b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) powered by a FREE Hugging Face Inference Endpoint!
|
||||
* [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.
|
||||
* [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.
|
||||
* [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.
|
||||
* [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Requires an OpenAI key.
|
||||
- [Llama-2-70b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) powered by a FREE Hugging Face Inference Endpoint!
|
||||
- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.
|
||||
- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.
|
||||
- [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.
|
||||
- [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Requires an OpenAI key.
|
||||
|
||||
But once again, you can deploy ANY `gr.ChatInterface` app exposed on the internet! So don't hesitate to try it on your own Chatbots.
|
||||
|
||||
❗️ Additional Note ❗️: Technically, any gradio app that exposes an api route that takes in a single string and outputs a single string can be deployed to discord. But `gr.ChatInterface` apps naturally lend themselves to discord's chat functionality so we suggest you start with those.
|
||||
|
||||
Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
|
||||
Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
|
||||
|
||||
### New Features:
|
||||
|
||||
- Endpoints that return layout components are now properly handled in the `submit` and `view_api` methods. Output layout components are not returned by the API but all other components are (excluding `gr.State`). By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4871](https://github.com/gradio-app/gradio/pull/4871)
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
No changes to highlight
|
||||
@ -69,7 +69,7 @@ No changes to highlight.
|
||||
|
||||
### Full Changelog:
|
||||
|
||||
* Pinned dependencies to major versions to reduce the likelihood of a broken `gradio_client` due to changes in downstream dependencies by [@abidlabs](https://github.com/abidlabs) in [PR 4885](https://github.com/gradio-app/gradio/pull/4885)
|
||||
- Pinned dependencies to major versions to reduce the likelihood of a broken `gradio_client` due to changes in downstream dependencies by [@abidlabs](https://github.com/abidlabs) in [PR 4885](https://github.com/gradio-app/gradio/pull/4885)
|
||||
|
||||
# 0.2.8
|
||||
|
||||
@ -149,6 +149,7 @@ No changes to highlight.
|
||||
# 0.2.4
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
- Fixes missing serialization classes for several components: `Barplot`, `Lineplot`, `Scatterplot`, `AnnotatedImage`, `Interpretation` by [@abidlabs](https://github.com/abidlabs) in [PR 4167](https://github.com/gradio-app/gradio/pull/4167)
|
||||
|
||||
### Documentation Changes:
|
||||
@ -178,6 +179,7 @@ No changes to highlight.
|
||||
No changes to highlight.
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
- Fix example inputs for `gr.File(file_count='multiple')` output components by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4153](https://github.com/gradio-app/gradio/pull/4153)
|
||||
|
||||
### Documentation Changes:
|
||||
@ -210,17 +212,14 @@ No changes to highlight.
|
||||
|
||||
- Only send request to `/info` route if demo version is above `3.28.3` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4109](https://github.com/gradio-app/gradio/pull/4109)
|
||||
|
||||
|
||||
### Other Changes:
|
||||
|
||||
- Fix bug in test from gradio 3.29.0 refactor by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4138](https://github.com/gradio-app/gradio/pull/4138)
|
||||
|
||||
|
||||
### Breaking Changes:
|
||||
|
||||
No changes to highlight.
|
||||
|
||||
|
||||
# 0.2.1
|
||||
|
||||
### New Features:
|
||||
@ -239,7 +238,6 @@ No changes to highlight.
|
||||
|
||||
Separates flaky tests from non-flaky tests by [@abidlabs](https://github.com/freddyaboulton) in [PR 4107](https://github.com/gradio-app/gradio/pull/4107)
|
||||
|
||||
|
||||
### Breaking Changes:
|
||||
|
||||
No changes to highlight.
|
||||
@ -314,7 +312,7 @@ No changes to highlight.
|
||||
|
||||
# 0.1.2
|
||||
|
||||
First public release of the Gradio Client library! The `gradio_client` Python library that makes it very easy to use any Gradio app as an API.
|
||||
First public release of the Gradio Client library! The `gradio_client` Python library that makes it very easy to use any Gradio app as an API.
|
||||
|
||||
As an example, consider this [Hugging Face Space that transcribes audio files](https://huggingface.co/spaces/abidlabs/whisper) that are recorded from the microphone.
|
||||
|
||||
@ -327,10 +325,10 @@ Here's the entire code to do it:
|
||||
```python
|
||||
from gradio_client import Client
|
||||
|
||||
client = Client("abidlabs/whisper")
|
||||
client.predict("audio_sample.wav")
|
||||
client = Client("abidlabs/whisper")
|
||||
client.predict("audio_sample.wav")
|
||||
|
||||
>> "This is a test of the whisper speech recognition model."
|
||||
```
|
||||
|
||||
Read more about how to use the `gradio_client` library here: https://gradio.app/getting-started-with-the-python-client/
|
||||
Read more about how to use the `gradio_client` library here: https://gradio.app/getting-started-with-the-python-client/
|
||||
|
File diff suppressed because one or more lines are too long
@ -7,13 +7,12 @@ import pandas as pd
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import random
|
||||
import os
|
||||
|
||||
|
||||
|
||||
def random_plot():
|
||||
start_year = 2020
|
||||
x = np.arange(start_year, start_year + random.randint(0, 10))
|
||||
x = np.arange(start_year, start_year + 5)
|
||||
year_count = x.shape[0]
|
||||
plt_format = "-"
|
||||
fig = plt.figure()
|
||||
@ -115,7 +114,7 @@ components = [
|
||||
)
|
||||
),
|
||||
gr.Dataframe(
|
||||
value=lambda: pd.DataFrame({"random_number_rows": range(random.randint(0, 10))})
|
||||
value=lambda: pd.DataFrame({"random_number_rows": range(5)}, columns=["one", "two", "three"])
|
||||
),
|
||||
gr.Timeseries(value=lambda: os.path.join(file_dir, "time.csv")),
|
||||
gr.ColorPicker(value=lambda: random.choice(["#000000", "#ff0000", "#0000FF"])),
|
||||
|
@ -258,8 +258,8 @@ Here you will have three files, the first file is for the Svelte application, an
|
||||
<script lang="ts">
|
||||
import { ColorPicker } from "@gradio/form";
|
||||
import { Block } from "@gradio/atoms";
|
||||
import StatusTracker from "../StatusTracker/StatusTracker.svelte";
|
||||
import type { LoadingStatus } from "../StatusTracker/types";
|
||||
import StatusTracker from "@gradio/statustracker";
|
||||
import type { LoadingStatus } from "@gradio/statustracker/types";
|
||||
import type { Styles } from "@gradio/utils";
|
||||
|
||||
export let label: string = "ColorPicker";
|
||||
@ -303,7 +303,7 @@ import { test, describe, assert, afterEach } from "vitest";
|
||||
import { cleanup, render } from "@gradio/tootils";
|
||||
|
||||
import ColorPicker from "./ColorPicker.svelte";
|
||||
import type { LoadingStatus } from "../StatusTracker/types";
|
||||
import type { LoadingStatus } from "@gradio/statustracker/types";
|
||||
|
||||
const loading_status = {
|
||||
eta: 0,
|
||||
|
@ -23,8 +23,8 @@
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@gradio/client": "workspace:^0.1.4",
|
||||
"@gradio/form": "workspace:^0.0.2",
|
||||
"@gradio/theme": "workspace:^0.0.2"
|
||||
"@gradio/client": "workspace:^",
|
||||
"@gradio/form": "workspace:^",
|
||||
"@gradio/theme": "workspace:^"
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,9 @@
|
||||
animation: shadowPulse 2s linear infinite;
|
||||
box-sizing: border-box;
|
||||
margin: var(--spacing-xxl) 0 var(--spacing-lg) var(--spacing-xxl) !important;
|
||||
box-shadow: -24px 0 #fff, 24px 0 #fff;
|
||||
box-shadow:
|
||||
-24px 0 #fff,
|
||||
24px 0 #fff;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
width: 16px;
|
||||
@ -16,15 +18,21 @@
|
||||
|
||||
@keyframes shadowPulse {
|
||||
33% {
|
||||
box-shadow: -24px 0 #ff3d00, 24px 0 #fff;
|
||||
box-shadow:
|
||||
-24px 0 #ff3d00,
|
||||
24px 0 #fff;
|
||||
background: #fff;
|
||||
}
|
||||
66% {
|
||||
box-shadow: -24px 0 #fff, 24px 0 #fff;
|
||||
box-shadow:
|
||||
-24px 0 #fff,
|
||||
24px 0 #fff;
|
||||
background: #ff3d00;
|
||||
}
|
||||
100% {
|
||||
box-shadow: -24px 0 #fff, 24px 0 #ff3d00;
|
||||
box-shadow:
|
||||
-24px 0 #fff,
|
||||
24px 0 #ff3d00;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
@ -8,4 +8,4 @@
|
||||
|
||||
### Fixes
|
||||
|
||||
- [#5007](https://github.com/gradio-app/gradio/pull/5007) [`71c90394`](https://github.com/gradio-app/gradio/commit/71c90394012a9cfe10eae312b437a6deff52da3a) - Make sure tags aren't rendered inside a guide. Thanks [@aliabd](https://github.com/aliabd)!
|
||||
- [#5007](https://github.com/gradio-app/gradio/pull/5007) [`71c90394`](https://github.com/gradio-app/gradio/commit/71c90394012a9cfe10eae312b437a6deff52da3a) - Make sure tags aren't rendered inside a guide. Thanks [@aliabd](https://github.com/aliabd)!
|
||||
|
@ -132,7 +132,8 @@
|
||||
<a
|
||||
class:current-nav-link={current_nav_link == "chatinterface"}
|
||||
class="thin-link px-4 block"
|
||||
href="/docs/chatinterface/">ChatInterface<sup class="text-orange-500">NEW</sup></a
|
||||
href="/docs/chatinterface/"
|
||||
>ChatInterface<sup class="text-orange-500">NEW</sup></a
|
||||
>
|
||||
<a
|
||||
class:current-nav-link={current_nav_link == "themes"}
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
let click_nav = false;
|
||||
let show_help_menu = false;
|
||||
let show_nav = false;
|
||||
$: show_nav = click_nav || $store?.lg;
|
||||
let show_nav = false;
|
||||
$: show_nav = click_nav || $store?.lg;
|
||||
</script>
|
||||
|
||||
<div
|
||||
@ -90,4 +90,4 @@
|
||||
<img src={github_black} class="w-6" alt="Github logo" />
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/** Dispatch event on click outside of node */
|
||||
declare namespace svelte.JSX {
|
||||
namespace svelte.JSX {
|
||||
interface HTMLProps<T> {
|
||||
onclick_outside?: (e: CustomEvent) => void;
|
||||
}
|
||||
|
@ -31,10 +31,10 @@ function highlight(code: string, lang: string | undefined) {
|
||||
|
||||
const highlighted = _lang
|
||||
? `<pre class="language-${lang}"><code>${Prism.highlight(
|
||||
code,
|
||||
Prism.languages[_lang],
|
||||
_lang
|
||||
)}</code></pre>`
|
||||
code,
|
||||
Prism.languages[_lang],
|
||||
_lang
|
||||
)}</code></pre>`
|
||||
: code;
|
||||
|
||||
return highlighted;
|
||||
|
@ -19,7 +19,7 @@
|
||||
const anchor = document.getElementById(anchorId);
|
||||
window.scrollTo({
|
||||
top: anchor?.offsetTop,
|
||||
behavior: "smooth",
|
||||
behavior: "smooth"
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -32,7 +32,7 @@
|
||||
const anchor = document.getElementById(anchorId);
|
||||
window.scrollTo({
|
||||
top: anchor?.offsetTop,
|
||||
behavior: "smooth",
|
||||
behavior: "smooth"
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
const anchor = document.getElementById(anchorId);
|
||||
window.scrollTo({
|
||||
top: anchor?.offsetTop,
|
||||
behavior: "smooth",
|
||||
behavior: "smooth"
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
const anchor = document.getElementById(anchorId);
|
||||
window.scrollTo({
|
||||
top: anchor?.offsetTop,
|
||||
behavior: "smooth",
|
||||
behavior: "smooth"
|
||||
});
|
||||
}
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -27,7 +27,7 @@
|
||||
const anchor = document.getElementById(anchorId);
|
||||
window.scrollTo({
|
||||
top: anchor?.offsetTop,
|
||||
behavior: "smooth",
|
||||
behavior: "smooth"
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
const anchor = document.getElementById(anchorId);
|
||||
window.scrollTo({
|
||||
top: anchor?.offsetTop,
|
||||
behavior: "smooth",
|
||||
behavior: "smooth"
|
||||
});
|
||||
}
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
{"version": "3.39.0"}
|
||||
{ "version": "3.39.0" }
|
||||
|
@ -2,9 +2,7 @@
|
||||
import { sveltekit } from "file:///Users/aliabdalla/Desktop/dev/gradio/node_modules/.pnpm/@sveltejs+kit@1.16.3_svelte@3.59.2_vite@4.3.9/node_modules/@sveltejs/kit/src/exports/vite/index.js";
|
||||
import { defineConfig } from "file:///Users/aliabdalla/Desktop/dev/gradio/node_modules/.pnpm/vite@4.3.9_@types+node@20.3.2_less@4.1.3/node_modules/vite/dist/node/index.js";
|
||||
var vite_config_default = defineConfig({
|
||||
plugins: [sveltekit()]
|
||||
plugins: [sveltekit()]
|
||||
});
|
||||
export {
|
||||
vite_config_default as default
|
||||
};
|
||||
export { vite_config_default as default };
|
||||
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvVXNlcnMvYWxpYWJkYWxsYS9EZXNrdG9wL2Rldi9ncmFkaW8vanMvX3dlYnNpdGVcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9Vc2Vycy9hbGlhYmRhbGxhL0Rlc2t0b3AvZGV2L2dyYWRpby9qcy9fd2Vic2l0ZS92aXRlLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vVXNlcnMvYWxpYWJkYWxsYS9EZXNrdG9wL2Rldi9ncmFkaW8vanMvX3dlYnNpdGUvdml0ZS5jb25maWcudHNcIjtpbXBvcnQgeyBzdmVsdGVraXQgfSBmcm9tIFwiQHN2ZWx0ZWpzL2tpdC92aXRlXCI7XG5pbXBvcnQgeyBkZWZpbmVDb25maWcgfSBmcm9tIFwidml0ZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoe1xuXHRwbHVnaW5zOiBbc3ZlbHRla2l0KCldXG59KTtcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBa1UsU0FBUyxpQkFBaUI7QUFDNVYsU0FBUyxvQkFBb0I7QUFFN0IsSUFBTyxzQkFBUSxhQUFhO0FBQUEsRUFDM0IsU0FBUyxDQUFDLFVBQVUsQ0FBQztBQUN0QixDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo=
|
||||
|
@ -3,9 +3,21 @@
|
||||
"version": "0.0.1",
|
||||
"description": "Gradio UI packages",
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"main": "./static/index.ts",
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"private": true,
|
||||
"main_changeset": true
|
||||
"main_changeset": true,
|
||||
"dependencies": {
|
||||
"@gradio/atoms": "workspace:^",
|
||||
"@gradio/column": "workspace:^",
|
||||
"@gradio/statustracker": "workspace:^"
|
||||
},
|
||||
"exports": {
|
||||
".": "./static/index.ts",
|
||||
"./package.json": "./package.json",
|
||||
"./interactive": "./interactive/index.ts",
|
||||
"./static": "./static/index.ts",
|
||||
"./example": "./example/index.ts"
|
||||
}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
export { default as Accordion } from "./Accordion.svelte";
|
@ -1,8 +1,11 @@
|
||||
<script lang="ts">
|
||||
export let label: string = "";
|
||||
export let open: boolean = true;
|
||||
export let label = "";
|
||||
export let open = true;
|
||||
</script>
|
||||
|
||||
<!-- TODO: fix -->
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div on:click={() => (open = !open)} class="label-wrap" class:open>
|
||||
<span>{label}</span>
|
||||
<span style:transform={open ? "rotate(0)" : "rotate(90deg)"} class="icon">
|
@ -1,16 +1,16 @@
|
||||
<script lang="ts">
|
||||
import { Accordion } from "@gradio/accordion";
|
||||
import Accordion from "./Accordion.svelte";
|
||||
import { Block } from "@gradio/atoms";
|
||||
import StatusTracker from "../StatusTracker/StatusTracker.svelte";
|
||||
import type { LoadingStatus } from "../StatusTracker/types";
|
||||
import { StatusTracker } from "@gradio/statustracker";
|
||||
import type { LoadingStatus } from "@gradio/statustracker/types";
|
||||
|
||||
import { Component as Column } from "../Column";
|
||||
import Column from "@gradio/column";
|
||||
|
||||
export let label: string;
|
||||
export let elem_id: string;
|
||||
export let elem_classes: Array<string>;
|
||||
export let visible: boolean = true;
|
||||
export let open: boolean = true;
|
||||
export let elem_classes: string[];
|
||||
export let visible = true;
|
||||
export let open = true;
|
||||
export let loading_status: LoadingStatus;
|
||||
</script>
|
||||
|
1
js/accordion/static/index.ts
Normal file
1
js/accordion/static/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default } from "./StaticAccordion.svelte";
|
25
js/annotatedimage/package.json
Normal file
25
js/annotatedimage/package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "@gradio/annotatedimage",
|
||||
"version": "0.0.1",
|
||||
"description": "Gradio UI packages",
|
||||
"type": "module",
|
||||
"main": "./static/index.ts",
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"private": true,
|
||||
"main_changeset": true,
|
||||
"exports": {
|
||||
".": "./static/index.ts",
|
||||
"./package.json": "./package.json",
|
||||
"./interactive": "./interactive/index.ts",
|
||||
"./static": "./static/index.ts",
|
||||
"./example": "./example/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@gradio/atoms": "workspace:^",
|
||||
"@gradio/icons": "workspace:^",
|
||||
"@gradio/statustracker": "workspace:^",
|
||||
"@gradio/upload": "workspace:^",
|
||||
"@gradio/utils": "workspace:^"
|
||||
}
|
||||
}
|
@ -2,24 +2,24 @@
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { Block, BlockLabel, Empty } from "@gradio/atoms";
|
||||
import { Image } from "@gradio/icons";
|
||||
import StatusTracker from "../StatusTracker/StatusTracker.svelte";
|
||||
import type { LoadingStatus } from "../StatusTracker/types";
|
||||
import { StatusTracker } from "@gradio/statustracker";
|
||||
import type { LoadingStatus } from "@gradio/statustracker/types";
|
||||
import { type FileData, normalise_file } from "@gradio/upload";
|
||||
import type { SelectData } from "@gradio/utils";
|
||||
|
||||
export let elem_id: string = "";
|
||||
export let elem_classes: Array<string> = [];
|
||||
export let visible: boolean = true;
|
||||
export let value: [FileData, Array<[FileData, string]>] | null;
|
||||
let old_value: [FileData, Array<[FileData, string]>] | null;
|
||||
let _value: [FileData, Array<[FileData, string]>] | null;
|
||||
export let label: string = "Annotated Image";
|
||||
export let show_label: boolean = true;
|
||||
export let show_legend: boolean = true;
|
||||
export let elem_id = "";
|
||||
export let elem_classes: string[] = [];
|
||||
export let visible = true;
|
||||
export let value: [FileData, [FileData, string][]] | null;
|
||||
let old_value: [FileData, [FileData, string][]] | null;
|
||||
let _value: [FileData, [FileData, string][]] | null;
|
||||
export let label = "Annotated Image";
|
||||
export let show_label = true;
|
||||
export let show_legend = true;
|
||||
export let height: number | undefined;
|
||||
export let width: number | undefined;
|
||||
export let color_map: Record<string, string>;
|
||||
export let container: boolean = true;
|
||||
export let container = true;
|
||||
export let scale: number | null = null;
|
||||
export let min_width: number | undefined = undefined;
|
||||
export let root: string;
|
||||
@ -40,19 +40,19 @@
|
||||
if (value) {
|
||||
_value = [
|
||||
normalise_file(value[0], root, root_url) as FileData,
|
||||
value[1].map(([file, label]) => [
|
||||
value[1].map(([file, _label]) => [
|
||||
normalise_file(file, root, root_url) as FileData,
|
||||
label
|
||||
_label
|
||||
])
|
||||
];
|
||||
} else {
|
||||
_value = null;
|
||||
}
|
||||
}
|
||||
function handle_mouseover(label: string) {
|
||||
active = label;
|
||||
function handle_mouseover(_label: string): void {
|
||||
active = _label;
|
||||
}
|
||||
function handle_mouseout() {
|
||||
function handle_mouseout(): void {
|
||||
active = null;
|
||||
}
|
||||
</script>
|
||||
@ -101,7 +101,9 @@
|
||||
{#if show_legend && _value}
|
||||
<div class="legend">
|
||||
{#each _value[1] as [_, label], i}
|
||||
<!-- TODO: fix -->
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
class="legend-item"
|
||||
style="background-color: {color_map && label in color_map
|
1
js/annotatedimage/static/index.ts
Normal file
1
js/annotatedimage/static/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default } from "./AnnotatedImage.svelte";
|
@ -6,4 +6,4 @@
|
||||
|
||||
- [#4995](https://github.com/gradio-app/gradio/pull/4995) [`3f8c210b`](https://github.com/gradio-app/gradio/commit/3f8c210b01ef1ceaaf8ee73be4bf246b5b745bbf) - Implement left and right click in `Gallery` component and show implicit images in `Gallery` grid. Thanks [@hannahblair](https://github.com/hannahblair)!
|
||||
- [#4993](https://github.com/gradio-app/gradio/pull/4993) [`dc07a9f9`](https://github.com/gradio-app/gradio/commit/dc07a9f947de44b419d8384987a02dcf94977851) - Bringing back the "Add download button for audio" PR by [@leuryr](https://github.com/leuryr). Thanks [@abidlabs](https://github.com/abidlabs)!
|
||||
- [#4979](https://github.com/gradio-app/gradio/pull/4979) [`44ac8ad0`](https://github.com/gradio-app/gradio/commit/44ac8ad08d82ea12c503dde5c78f999eb0452de2) - Allow setting sketch color default. Thanks [@aliabid94](https://github.com/aliabid94)!
|
||||
- [#4979](https://github.com/gradio-app/gradio/pull/4979) [`44ac8ad0`](https://github.com/gradio-app/gradio/commit/44ac8ad08d82ea12c503dde5c78f999eb0452de2) - Allow setting sketch color default. Thanks [@aliabid94](https://github.com/aliabid94)!
|
||||
|
@ -89,7 +89,7 @@ export function generate_cdn_entry({
|
||||
};
|
||||
}
|
||||
|
||||
function make_entry(script: string) {
|
||||
function make_entry(script: string): string {
|
||||
const make_script = `
|
||||
function make_script(src) {
|
||||
const script = document.createElement('script');
|
||||
@ -146,9 +146,8 @@ export function handle_ce_css(): Plugin {
|
||||
(acc, next) => {
|
||||
if (/.*\/index(.*?)\.css/.test(next.attributes.href)) {
|
||||
return { ...acc, style: next };
|
||||
} else {
|
||||
return { ...acc, fonts: [...acc.fonts, next.attributes.href] };
|
||||
}
|
||||
return { ...acc, fonts: [...acc.fonts, next.attributes.href] };
|
||||
},
|
||||
{ fonts: [], style: undefined } as {
|
||||
fonts: string[];
|
||||
|
@ -23,34 +23,50 @@
|
||||
"build:css": "pollen -c pollen.config.cjs -o src/pollen-dev.css"
|
||||
},
|
||||
"dependencies": {
|
||||
"@gradio/accordion": "workspace:^0.0.1",
|
||||
"@gradio/atoms": "workspace:^0.0.2",
|
||||
"@gradio/audio": "workspace:^0.1.0",
|
||||
"@gradio/button": "workspace:^0.0.2",
|
||||
"@gradio/chart": "workspace:^0.0.2",
|
||||
"@gradio/chatbot": "workspace:^0.0.2",
|
||||
"@gradio/client": "workspace:^0.1.4",
|
||||
"@gradio/code": "workspace:^0.0.2",
|
||||
"@gradio/file": "workspace:^0.0.2",
|
||||
"@gradio/form": "workspace:^0.0.2",
|
||||
"@gradio/gallery": "workspace:^0.1.0",
|
||||
"@gradio/highlighted-text": "workspace:^0.0.2",
|
||||
"@gradio/html": "workspace:^0.0.1",
|
||||
"@gradio/icons": "workspace:^0.0.1",
|
||||
"@gradio/image": "workspace:^0.1.0",
|
||||
"@gradio/json": "workspace:^0.0.2",
|
||||
"@gradio/label": "workspace:^0.0.2",
|
||||
"@gradio/markdown": "workspace:^0.0.1",
|
||||
"@gradio/model3D": "workspace:^0.0.2",
|
||||
"@gradio/plot": "workspace:^0.0.2",
|
||||
"@gradio/table": "workspace:^0.0.2",
|
||||
"@gradio/tabs": "workspace:^0.0.2",
|
||||
"@gradio/theme": "workspace:^0.0.2",
|
||||
"@gradio/upload": "workspace:^0.0.2",
|
||||
"@gradio/upload-button": "workspace:^0.0.2",
|
||||
"@gradio/utils": "workspace:^0.0.2",
|
||||
"@gradio/video": "workspace:^0.0.2",
|
||||
"@gradio/wasm": "workspace:^0.0.1",
|
||||
"@gradio/accordion": "workspace:^",
|
||||
"@gradio/annotatedimage": "workspace:^",
|
||||
"@gradio/atoms": "workspace:^",
|
||||
"@gradio/audio": "workspace:^",
|
||||
"@gradio/box": "workspace:^",
|
||||
"@gradio/button": "workspace:^",
|
||||
"@gradio/chatbot": "workspace:^",
|
||||
"@gradio/checkbox": "workspace:^",
|
||||
"@gradio/checkboxgroup": "workspace:^",
|
||||
"@gradio/client": "workspace:^",
|
||||
"@gradio/code": "workspace:^",
|
||||
"@gradio/colorpicker": "workspace:^",
|
||||
"@gradio/column": "workspace:^",
|
||||
"@gradio/dataframe": "workspace:^",
|
||||
"@gradio/dropdown": "workspace:^",
|
||||
"@gradio/file": "workspace:^",
|
||||
"@gradio/form": "workspace:^",
|
||||
"@gradio/gallery": "workspace:^",
|
||||
"@gradio/group": "workspace:^",
|
||||
"@gradio/highlightedtext": "workspace:^",
|
||||
"@gradio/html": "workspace:^",
|
||||
"@gradio/icons": "workspace:^",
|
||||
"@gradio/image": "workspace:^",
|
||||
"@gradio/json": "workspace:^",
|
||||
"@gradio/label": "workspace:^",
|
||||
"@gradio/markdown": "workspace:^",
|
||||
"@gradio/model3d": "workspace:^",
|
||||
"@gradio/number": "workspace:^",
|
||||
"@gradio/plot": "workspace:^",
|
||||
"@gradio/radio": "workspace:^",
|
||||
"@gradio/row": "workspace:^",
|
||||
"@gradio/slider": "workspace:^",
|
||||
"@gradio/state": "workspace:^",
|
||||
"@gradio/statustracker": "workspace:^",
|
||||
"@gradio/tabitem": "workspace:^",
|
||||
"@gradio/tabs": "workspace:^",
|
||||
"@gradio/textbox": "workspace:^",
|
||||
"@gradio/theme": "workspace:^",
|
||||
"@gradio/timeseries": "workspace:^",
|
||||
"@gradio/upload": "workspace:^",
|
||||
"@gradio/uploadbutton": "workspace:^",
|
||||
"@gradio/utils": "workspace:^",
|
||||
"@gradio/video": "workspace:^",
|
||||
"@gradio/wasm": "workspace:^",
|
||||
"@playwright/test": "^1.35.1",
|
||||
"d3-dsv": "^3.0.1",
|
||||
"mime-types": "^2.1.34",
|
||||
|
@ -17,8 +17,8 @@
|
||||
import Render from "./Render.svelte";
|
||||
import { ApiDocs } from "./api_docs/";
|
||||
import type { ThemeMode } from "./components/types";
|
||||
import Toast from "./components/StatusTracker/Toast.svelte";
|
||||
import type { ToastMessage } from "./components/StatusTracker/types";
|
||||
import { Toast } from "@gradio/statustracker";
|
||||
import type { ToastMessage } from "@gradio/statustracker";
|
||||
import type { ShareData } from "@gradio/utils";
|
||||
|
||||
import logo from "./images/logo.svg";
|
||||
@ -79,7 +79,7 @@
|
||||
|
||||
let params = new URLSearchParams(window.location.search);
|
||||
let api_docs_visible = params.get("view") === "api";
|
||||
const set_api_docs_visible = (visible: boolean) => {
|
||||
function set_api_docs_visible(visible: boolean): void {
|
||||
api_docs_visible = visible;
|
||||
let params = new URLSearchParams(window.location.search);
|
||||
if (visible) {
|
||||
@ -88,9 +88,13 @@
|
||||
params.delete("view");
|
||||
}
|
||||
history.replaceState(null, "", "?" + params.toString());
|
||||
};
|
||||
}
|
||||
|
||||
function is_dep(id: number, type: "inputs" | "outputs", deps: Dependency[]) {
|
||||
function is_dep(
|
||||
id: number,
|
||||
type: "inputs" | "outputs",
|
||||
deps: Dependency[]
|
||||
): boolean {
|
||||
for (const dep of deps) {
|
||||
for (const dep_item of dep[type]) {
|
||||
if (dep_item === id) return true;
|
||||
@ -112,7 +116,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function has_no_default_value(value: any) {
|
||||
function has_no_default_value(value: any): boolean {
|
||||
return (
|
||||
(Array.isArray(value) && value.length === 0) ||
|
||||
value === "" ||
|
||||
@ -121,10 +125,13 @@
|
||||
);
|
||||
}
|
||||
|
||||
let instance_map = components.reduce((acc, next) => {
|
||||
acc[next.id] = next;
|
||||
return acc;
|
||||
}, {} as { [id: number]: ComponentMeta });
|
||||
let instance_map = components.reduce(
|
||||
(acc, next) => {
|
||||
acc[next.id] = next;
|
||||
return acc;
|
||||
},
|
||||
{} as { [id: number]: ComponentMeta }
|
||||
);
|
||||
|
||||
type LoadedComponent = {
|
||||
Component: ComponentMeta["component"];
|
||||
@ -159,7 +166,7 @@
|
||||
Promise<{ name: ComponentMeta["type"]; component: LoadedComponent }>
|
||||
>();
|
||||
|
||||
async function walk_layout(node: LayoutNode) {
|
||||
async function walk_layout(node: LayoutNode): Promise<void> {
|
||||
let instance = instance_map[node.id];
|
||||
const _component = (await _component_map.get(instance.type))!.component;
|
||||
instance.component = _component.Component;
|
||||
@ -193,7 +200,7 @@
|
||||
});
|
||||
});
|
||||
|
||||
function handle_update(data: any, fn_index: number) {
|
||||
function handle_update(data: any, fn_index: number): void {
|
||||
const outputs = dependencies[fn_index].outputs;
|
||||
data?.forEach((value: any, i: number) => {
|
||||
const output = instance_map[outputs[i]];
|
||||
@ -219,7 +226,11 @@
|
||||
|
||||
let submit_map: Map<number, ReturnType<typeof app.submit>> = new Map();
|
||||
|
||||
function set_prop<T extends ComponentMeta>(obj: T, prop: string, val: any) {
|
||||
function set_prop<T extends ComponentMeta>(
|
||||
obj: T,
|
||||
prop: string,
|
||||
val: any
|
||||
): void {
|
||||
if (!obj?.props) {
|
||||
obj.props = {};
|
||||
}
|
||||
@ -229,19 +240,22 @@
|
||||
let handled_dependencies: number[][] = [];
|
||||
|
||||
let messages: (ToastMessage & { fn_index: number })[] = [];
|
||||
const new_message = (
|
||||
function new_message(
|
||||
message: string,
|
||||
fn_index: number,
|
||||
type: ToastMessage["type"]
|
||||
) => ({
|
||||
message,
|
||||
fn_index,
|
||||
type,
|
||||
id: ++_error_id
|
||||
});
|
||||
): ToastMessage & { fn_index: number } {
|
||||
return {
|
||||
message,
|
||||
fn_index,
|
||||
type,
|
||||
id: ++_error_id
|
||||
};
|
||||
}
|
||||
|
||||
let _error_id = -1;
|
||||
|
||||
let user_left_page: boolean = false;
|
||||
let user_left_page = false;
|
||||
document.addEventListener("visibilitychange", function () {
|
||||
if (document.visibilityState === "hidden") {
|
||||
user_left_page = true;
|
||||
@ -265,10 +279,10 @@
|
||||
let showed_duplicate_message = false;
|
||||
let showed_mobile_warning = false;
|
||||
|
||||
const trigger_api_call = async (
|
||||
async function trigger_api_call(
|
||||
dep_index: number,
|
||||
event_data: unknown = null
|
||||
) => {
|
||||
): Promise<void> {
|
||||
let dep = dependencies[dep_index];
|
||||
const current_status = loading_status.get_status_for_fn(dep_index);
|
||||
messages = messages.filter(({ fn_index }) => fn_index !== dep_index);
|
||||
@ -299,7 +313,7 @@
|
||||
dep.outputs.map((id) => instance_map[id].props.value)
|
||||
)
|
||||
)
|
||||
.then((v: []) => {
|
||||
.then((v: unknown[]) => {
|
||||
if (dep.backend_fn) {
|
||||
payload.data = v;
|
||||
make_prediction();
|
||||
@ -313,13 +327,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
function make_prediction() {
|
||||
function make_prediction(): void {
|
||||
const submission = app
|
||||
.submit(payload.fn_index, payload.data as unknown[], payload.event_data)
|
||||
.on("data", ({ data, fn_index }) => {
|
||||
handle_update(data, fn_index);
|
||||
})
|
||||
.on("status", ({ fn_index, ...status }) => {
|
||||
//@ts-ignore
|
||||
loading_status.update({
|
||||
...status,
|
||||
status: status.stage,
|
||||
@ -400,9 +415,9 @@
|
||||
|
||||
submit_map.set(dep_index, submission);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const trigger_share = (title: string | undefined, description: string) => {
|
||||
function trigger_share(title: string | undefined, description: string): void {
|
||||
if (space_id === null) {
|
||||
return;
|
||||
}
|
||||
@ -414,19 +429,19 @@
|
||||
}
|
||||
discussion_url.searchParams.set("description", description);
|
||||
window.open(discussion_url.toString(), "_blank");
|
||||
};
|
||||
}
|
||||
|
||||
function handle_error_close(e: Event & { detail: number }) {
|
||||
function handle_error_close(e: Event & { detail: number }): void {
|
||||
const _id = e.detail;
|
||||
messages = messages.filter((m) => m.id !== _id);
|
||||
}
|
||||
|
||||
const is_external_url = (link: string | null) =>
|
||||
link && new URL(link, location.href).origin !== location.origin;
|
||||
const is_external_url = (link: string | null): boolean =>
|
||||
!!(link && new URL(link, location.href).origin !== location.origin);
|
||||
|
||||
let attached_error_listeners: number[] = [];
|
||||
let shareable_components: number[] = [];
|
||||
async function handle_mount() {
|
||||
async function handle_mount(): Promise<void> {
|
||||
await tick();
|
||||
|
||||
var a = target.getElementsByTagName("a");
|
||||
@ -502,7 +517,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
function handle_destroy(id: number) {
|
||||
function handle_destroy(id: number): void {
|
||||
handled_dependencies = handled_dependencies.map((dep) => {
|
||||
return dep.filter((_id) => _id !== id);
|
||||
});
|
||||
@ -514,7 +529,7 @@
|
||||
loading_status.register(i, v.inputs, v.outputs);
|
||||
});
|
||||
|
||||
function set_status(statuses: LoadingStatusCollection) {
|
||||
function set_status(statuses: LoadingStatusCollection): void {
|
||||
for (const id in statuses) {
|
||||
let loading_status = statuses[id];
|
||||
let dependency = dependencies[loading_status.fn_index];
|
||||
@ -599,6 +614,9 @@
|
||||
|
||||
{#if api_docs_visible && ready}
|
||||
<div class="api-docs">
|
||||
<!-- TODO: fix -->
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events-->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions-->
|
||||
<div
|
||||
class="backdrop"
|
||||
on:click={() => {
|
||||
|
@ -36,7 +36,9 @@
|
||||
<span>
|
||||
Hosted on
|
||||
<a class="hf" href="https://huggingface.co/spaces"
|
||||
><span class="space-logo"><img src={space_logo} /></span> Spaces</a
|
||||
><span class="space-logo">
|
||||
<img src={space_logo} alt="Hugging Face space logo" />
|
||||
</span> Spaces</a
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -31,7 +31,10 @@
|
||||
|
||||
let id = -1;
|
||||
|
||||
function create_intersection_store() {
|
||||
function create_intersection_store(): {
|
||||
register: (n: number, el: HTMLDivElement) => void;
|
||||
subscribe: (typeof intersecting)["subscribe"];
|
||||
} {
|
||||
const intersecting = writable<Record<string, boolean>>({});
|
||||
|
||||
const els = new Map<HTMLDivElement, number>();
|
||||
@ -46,8 +49,8 @@
|
||||
});
|
||||
});
|
||||
|
||||
function register(id: number, el: HTMLDivElement) {
|
||||
els.set(el, id);
|
||||
function register(_id: number, el: HTMLDivElement): void {
|
||||
els.set(el, _id);
|
||||
observer.observe(el);
|
||||
}
|
||||
|
||||
@ -62,7 +65,7 @@
|
||||
import type { api_factory, SpaceStatus } from "@gradio/client";
|
||||
import Embed from "./Embed.svelte";
|
||||
import type { ThemeMode } from "./components/types";
|
||||
import { Component as Loader } from "./components/StatusTracker";
|
||||
import { StatusTracker } from "@gradio/statustracker";
|
||||
|
||||
export let autoscroll: boolean;
|
||||
export let version: string;
|
||||
@ -90,15 +93,15 @@
|
||||
"pending";
|
||||
let app_id: string | null = null;
|
||||
let wrapper: HTMLDivElement;
|
||||
let ready: boolean = false;
|
||||
let ready = false;
|
||||
let config: Config;
|
||||
let loading_text: string = "Loading...";
|
||||
let loading_text = "Loading...";
|
||||
let active_theme_mode: ThemeMode;
|
||||
|
||||
async function mount_custom_css(
|
||||
target: HTMLElement,
|
||||
css_string: string | null
|
||||
) {
|
||||
): Promise<void> {
|
||||
if (css_string) {
|
||||
let style = document.createElement("style");
|
||||
style.innerHTML = css_string;
|
||||
@ -119,7 +122,7 @@
|
||||
);
|
||||
}
|
||||
|
||||
async function reload_check(root: string) {
|
||||
async function reload_check(root: string): Promise<void> {
|
||||
const result = await (await fetch(root + "/app_id")).text();
|
||||
|
||||
if (app_id === null) {
|
||||
@ -152,20 +155,20 @@
|
||||
?.matchMedia("(prefers-color-scheme: dark)")
|
||||
?.addEventListener("change", update_scheme);
|
||||
|
||||
function update_scheme() {
|
||||
let theme: "light" | "dark" = window?.matchMedia?.(
|
||||
function update_scheme(): "light" | "dark" {
|
||||
let _theme: "light" | "dark" = window?.matchMedia?.(
|
||||
"(prefers-color-scheme: dark)"
|
||||
).matches
|
||||
? "dark"
|
||||
: "light";
|
||||
|
||||
darkmode(target, theme);
|
||||
return theme;
|
||||
darkmode(target, _theme);
|
||||
return _theme;
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
function darkmode(target: HTMLDivElement, theme: "dark" | "light") {
|
||||
function darkmode(target: HTMLDivElement, theme: "dark" | "light"): void {
|
||||
const dark_class_element = is_embed ? target.parentElement! : document.body;
|
||||
const bg_element = is_embed ? target : target.parentElement!;
|
||||
bg_element.style.background = "var(--body-background-fill)";
|
||||
@ -185,7 +188,7 @@
|
||||
|
||||
let app: Awaited<ReturnType<typeof client>>;
|
||||
let css_ready = false;
|
||||
function handle_status(_status: SpaceStatus) {
|
||||
function handle_status(_status: SpaceStatus): void {
|
||||
status = _status;
|
||||
}
|
||||
onMount(async () => {
|
||||
@ -235,14 +238,14 @@
|
||||
let Blocks: typeof import("./Blocks.svelte").default;
|
||||
let Login: typeof import("./Login.svelte").default;
|
||||
|
||||
async function get_blocks() {
|
||||
async function get_blocks(): Promise<void> {
|
||||
Blocks = (await import("./Blocks.svelte")).default;
|
||||
}
|
||||
async function get_login() {
|
||||
async function get_login(): Promise<void> {
|
||||
Login = (await import("./Login.svelte")).default;
|
||||
}
|
||||
|
||||
function load_demo() {
|
||||
function load_demo(): void {
|
||||
if (config.auth_required) get_login();
|
||||
else get_blocks();
|
||||
}
|
||||
@ -262,14 +265,14 @@
|
||||
RUNTIME_ERROR: "there is a runtime error",
|
||||
PAUSED: "the space is paused"
|
||||
} as const,
|
||||
title(error: error_types) {
|
||||
title(error: error_types): string {
|
||||
return encodeURIComponent(
|
||||
`Space isn't working because ${
|
||||
this.readable_error[error] || "an error"
|
||||
}`
|
||||
);
|
||||
},
|
||||
description(error: error_types, site: string) {
|
||||
description(error: error_types, site: string): string {
|
||||
return encodeURIComponent(
|
||||
`Hello,\n\nFirstly, thanks for creating this space!\n\nI noticed that the space isn't working correctly because there is ${
|
||||
this.readable_error[error] || "an error"
|
||||
@ -294,7 +297,7 @@
|
||||
bind:wrapper
|
||||
>
|
||||
{#if (loader_status === "pending" || loader_status === "error") && !(config && config?.auth_required)}
|
||||
<Loader
|
||||
<StatusTracker
|
||||
absolute={!is_embed}
|
||||
status={loader_status}
|
||||
timer={false}
|
||||
@ -322,7 +325,7 @@
|
||||
<p>Please contact the author of the page to let them know.</p>
|
||||
{/if}
|
||||
</div>
|
||||
</Loader>
|
||||
</StatusTracker>
|
||||
{/if}
|
||||
{#if config?.auth_required && Login}
|
||||
<Login
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Component as Form } from "./components/Form";
|
||||
import { Component as Textbox } from "./components/Textbox";
|
||||
import { Button } from "@gradio/button";
|
||||
import Form from "@gradio/form";
|
||||
import Textbox from "@gradio/textbox";
|
||||
import { BaseButton } from "@gradio/button/static";
|
||||
import { Component as Column } from "./components/Column";
|
||||
export let root: string;
|
||||
export let auth_message: string | null;
|
||||
@ -12,7 +12,7 @@
|
||||
let password = "";
|
||||
let incorrect_credentials = false;
|
||||
|
||||
const submit = async () => {
|
||||
const submit = async (): Promise<void> => {
|
||||
const formData = new FormData();
|
||||
formData.append("username", username);
|
||||
formData.append("password", password);
|
||||
@ -68,7 +68,7 @@
|
||||
/>
|
||||
</Form>
|
||||
|
||||
<Button size="lg" variant="primary" on:click={submit}>Login</Button>
|
||||
<BaseButton size="lg" variant="primary" on:click={submit}>Login</BaseButton>
|
||||
</Column>
|
||||
</div>
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
setContext("BLOCK_KEY", parent);
|
||||
|
||||
function handle_prop_change(e: { detail: Record<string, any> }) {
|
||||
function handle_prop_change(e: { detail: Record<string, any> }): void {
|
||||
for (const k in e.detail) {
|
||||
instance_map[id].props[k] = e.detail[k];
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
/* eslint-disable */
|
||||
import { onMount, createEventDispatcher } from "svelte";
|
||||
import type { ComponentMeta, Dependency } from "../components/types";
|
||||
import { post_data } from "@gradio/client";
|
||||
@ -19,7 +20,7 @@
|
||||
export let instance_map: {
|
||||
[id: number]: ComponentMeta;
|
||||
};
|
||||
export let dependencies: Array<Dependency>;
|
||||
export let dependencies: Dependency[];
|
||||
export let root: string;
|
||||
export let app: Awaited<ReturnType<typeof client>>;
|
||||
|
||||
@ -59,12 +60,15 @@
|
||||
new Array(dependency.inputs.length).fill(false)
|
||||
);
|
||||
|
||||
async function get_info() {
|
||||
async function get_info(): Promise<{
|
||||
named_endpoints: any;
|
||||
unnamed_endpoints: any;
|
||||
}> {
|
||||
let response = await fetch(root + "info");
|
||||
let data = await response.json();
|
||||
return data;
|
||||
}
|
||||
async function get_js_info() {
|
||||
async function get_js_info(): Promise<Record<string, any>> {
|
||||
let js_api_info = await app.view_api();
|
||||
return js_api_info;
|
||||
}
|
||||
@ -76,13 +80,11 @@
|
||||
|
||||
let js_info: Record<string, any>;
|
||||
|
||||
get_info()
|
||||
.then((data) => (info = data))
|
||||
.catch((err) => console.log(err));
|
||||
get_info().then((data) => (info = data));
|
||||
|
||||
get_js_info().then((js_api_info) => (js_info = js_api_info));
|
||||
|
||||
const run = async (index: number) => {
|
||||
async function run(index: number): Promise<void> {
|
||||
is_running = true;
|
||||
let dependency = dependencies[index];
|
||||
let attempted_component_index = 0;
|
||||
@ -90,6 +92,7 @@
|
||||
var inputs = dependency_inputs[index].map((input_val, i) => {
|
||||
attempted_component_index = i;
|
||||
let component = instance_map[dependency.inputs[i]];
|
||||
// @ts-ignore
|
||||
input_val = represent_value(
|
||||
input_val,
|
||||
component.documentation?.type?.input_payload ||
|
||||
@ -128,7 +131,7 @@
|
||||
dependency_failures[index].length
|
||||
).fill(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
document.body.style.overflow = "hidden";
|
||||
@ -194,13 +197,10 @@
|
||||
js_parameters={js_info.named_endpoints[
|
||||
"/" + dependency.api_name
|
||||
].parameters}
|
||||
{instance_map}
|
||||
{dependency}
|
||||
{dependency_index}
|
||||
{current_language}
|
||||
{root}
|
||||
{dependency_inputs}
|
||||
{dependencies}
|
||||
{dependency_failures}
|
||||
/>
|
||||
|
||||
@ -211,18 +211,12 @@
|
||||
/> -->
|
||||
|
||||
<ResponseObject
|
||||
named={true}
|
||||
endpoint_returns={info.named_endpoints[
|
||||
"/" + dependency.api_name
|
||||
].returns}
|
||||
js_returns={js_info.named_endpoints["/" + dependency.api_name]
|
||||
.returns}
|
||||
{instance_map}
|
||||
{dependency}
|
||||
{dependency_index}
|
||||
{is_running}
|
||||
{dependency_outputs}
|
||||
{root}
|
||||
{current_language}
|
||||
/>
|
||||
</div>
|
||||
@ -242,34 +236,19 @@
|
||||
.parameters}
|
||||
js_parameters={js_info.unnamed_endpoints[dependency_index]
|
||||
.parameters}
|
||||
{instance_map}
|
||||
{dependency}
|
||||
{dependency_index}
|
||||
{current_language}
|
||||
{root}
|
||||
{dependency_inputs}
|
||||
{dependencies}
|
||||
{dependency_failures}
|
||||
/>
|
||||
|
||||
<!-- <TryButton
|
||||
named={false}
|
||||
{dependency_index}
|
||||
{run}
|
||||
/> -->
|
||||
|
||||
<ResponseObject
|
||||
named={false}
|
||||
endpoint_returns={info.unnamed_endpoints[dependency_index]
|
||||
.returns}
|
||||
js_returns={js_info.unnamed_endpoints[dependency_index].returns}
|
||||
{instance_map}
|
||||
{dependency}
|
||||
{dependency_index}
|
||||
{is_running}
|
||||
{dependency_outputs}
|
||||
{current_language}
|
||||
{root}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -6,13 +6,8 @@
|
||||
import EndpointDetail from "./EndpointDetail.svelte";
|
||||
|
||||
export let dependency: Dependency;
|
||||
export let dependencies: Dependency[];
|
||||
export let dependency_index: number;
|
||||
export let instance_map: {
|
||||
[id: number]: ComponentMeta;
|
||||
};
|
||||
export let root: string;
|
||||
export let dependency_inputs: string[][];
|
||||
export let dependency_failures: boolean[][];
|
||||
export let endpoint_parameters: any;
|
||||
export let js_parameters: any;
|
||||
@ -69,7 +64,8 @@ result = client.predict(<!--
|
||||
-->{/if}<!--
|
||||
--><span class="desc"
|
||||
><!--
|
||||
--> # {python_type.type} {#if python_type.description}({python_type.description}) {/if}<!--
|
||||
--> # {python_type.type} {#if python_type.description}({python_type.description})
|
||||
{/if}<!--
|
||||
-->in '{label}' <!--
|
||||
-->{component} component<!--
|
||||
--></span
|
||||
|
@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { Button } from "@gradio/button";
|
||||
import { BaseButton } from "@gradio/button/static";
|
||||
export let code: string;
|
||||
let copy_text = "copy";
|
||||
|
||||
function copy() {
|
||||
function copy(): void {
|
||||
navigator.clipboard.writeText(code);
|
||||
copy_text = "copied!";
|
||||
setTimeout(() => {
|
||||
@ -12,6 +12,6 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Button size="sm" on:click={copy}>
|
||||
<BaseButton size="sm" on:click={copy}>
|
||||
{copy_text}
|
||||
</Button>
|
||||
</BaseButton>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { ComponentMeta, Dependency } from "../components/types";
|
||||
import { Button } from "@gradio/button";
|
||||
import { BaseButton } from "@gradio/button/static";
|
||||
import { Block } from "@gradio/atoms";
|
||||
|
||||
export let dependency: Dependency;
|
||||
@ -12,7 +12,7 @@
|
||||
export let run: (id: number) => Promise<void>;
|
||||
export let dependency_inputs: string[][];
|
||||
|
||||
function format_label(label: unknown) {
|
||||
function format_label(label: unknown): string {
|
||||
return label ? "'" + label + "'" : "the";
|
||||
}
|
||||
</script>
|
||||
@ -60,9 +60,9 @@
|
||||
</Block>
|
||||
|
||||
<span class="space" />
|
||||
<Button variant="primary" on:click={run.bind(null, dependency_index)}>
|
||||
<BaseButton variant="primary" on:click={run.bind(null, dependency_index)}>
|
||||
Try It Out
|
||||
</Button>
|
||||
</BaseButton>
|
||||
|
||||
<style>
|
||||
.payload-details {
|
||||
@ -109,10 +109,6 @@
|
||||
background: var(--color-grey-400);
|
||||
}
|
||||
|
||||
.details {
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
--ring-color: transparent;
|
||||
margin: var(--size-1) 0;
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
export let current_language: "python" | "javascript";
|
||||
|
||||
let py_install: string = "pip install gradio_client";
|
||||
let js_install: string = "npm i -D @gradio/client";
|
||||
let py_install = "pip install gradio_client";
|
||||
let js_install = "npm i -D @gradio/client";
|
||||
</script>
|
||||
|
||||
<Block>
|
||||
|
@ -1,23 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { ComponentMeta, Dependency } from "../components/types";
|
||||
import Loader from "../components/StatusTracker/Loader.svelte";
|
||||
import { Loader } from "@gradio/statustracker";
|
||||
import { Block } from "@gradio/atoms";
|
||||
|
||||
export let dependency: Dependency;
|
||||
export let dependency_index: number;
|
||||
export let instance_map: {
|
||||
[id: number]: ComponentMeta;
|
||||
};
|
||||
|
||||
export let dependency_outputs: any[][];
|
||||
|
||||
export let is_running: boolean;
|
||||
|
||||
export let root: string;
|
||||
export let endpoint_returns: any;
|
||||
export let js_returns: any;
|
||||
|
||||
export let named: boolean;
|
||||
export let current_language: "python" | "javascript";
|
||||
</script>
|
||||
|
||||
|
@ -1,15 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { Button } from "@gradio/button";
|
||||
import { BaseButton } from "@gradio/button/static";
|
||||
|
||||
export let dependency_index: number;
|
||||
export let named: boolean;
|
||||
export let run: (id: number) => Promise<void>;
|
||||
</script>
|
||||
|
||||
<span class="space" />
|
||||
<Button variant="primary" on:click={run.bind(null, dependency_index)}>
|
||||
<BaseButton variant="primary" on:click={run.bind(null, dependency_index)}>
|
||||
Try It Out
|
||||
</Button>
|
||||
</BaseButton>
|
||||
|
||||
<style>
|
||||
.space {
|
||||
|
@ -2,7 +2,7 @@ export function represent_value(
|
||||
value: string,
|
||||
type: string | undefined,
|
||||
lang: "js" | "py" | null = null
|
||||
) {
|
||||
): string | null | number | boolean | Record<string, unknown> {
|
||||
if (type === undefined) {
|
||||
return lang === "py" ? "None" : null;
|
||||
}
|
||||
@ -16,23 +16,20 @@ export function represent_value(
|
||||
return value === "true" ? "True" : "False";
|
||||
} else if (lang === "js") {
|
||||
return value;
|
||||
} else {
|
||||
return value === "true";
|
||||
}
|
||||
return value === "true";
|
||||
} else if (type === "List[str]") {
|
||||
value = JSON.stringify(value);
|
||||
return value;
|
||||
} else {
|
||||
// assume object type
|
||||
if (lang === null) {
|
||||
return value === "" ? null : JSON.parse(value);
|
||||
} else if (typeof value === "string") {
|
||||
if (value === "") {
|
||||
return lang === "py" ? "None" : "null";
|
||||
}
|
||||
return value;
|
||||
} else {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
}
|
||||
// assume object type
|
||||
if (lang === null) {
|
||||
return value === "" ? null : JSON.parse(value);
|
||||
} else if (typeof value === "string") {
|
||||
if (value === "") {
|
||||
return lang === "py" ? "None" : "null";
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
export { default as Component } from "./Accordion.svelte";
|
||||
export { default as Component } from "@gradio/accordion";
|
||||
export const modes = ["static"];
|
||||
|
@ -1,12 +1,2 @@
|
||||
export { default as Component } from "./AnnotatedImage.svelte";
|
||||
export { default as Component } from "@gradio/annotatedimage";
|
||||
export const modes = ["static"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
payload: "[string, Array<[string, string]>]"
|
||||
},
|
||||
description: {
|
||||
payload:
|
||||
"path to base image, followed by a list of tuples [mask image path, label]"
|
||||
}
|
||||
});
|
||||
|
@ -1,352 +0,0 @@
|
||||
import { test, describe, assert, afterEach, vi, beforeAll } from "vitest";
|
||||
import { spy, spyOn } from "tinyspy";
|
||||
import { cleanup, render, wait_for_event, wait } from "@gradio/tootils";
|
||||
import event from "@testing-library/user-event";
|
||||
import { setupi18n } from "../../i18n";
|
||||
import { tick } from "svelte";
|
||||
|
||||
import Audio from "./Audio.svelte";
|
||||
import type { LoadingStatus } from "../StatusTracker/types";
|
||||
|
||||
const loading_status = {
|
||||
eta: 0,
|
||||
queue_position: 1,
|
||||
queue_size: 1,
|
||||
status: "complete" as LoadingStatus["status"],
|
||||
scroll_to_output: false,
|
||||
visible: true,
|
||||
fn_index: 0,
|
||||
show_progress: "full" as LoadingStatus["show_progress"]
|
||||
};
|
||||
|
||||
describe("Audio", () => {
|
||||
beforeAll(() => {
|
||||
window.HTMLMediaElement.prototype.play = vi.fn();
|
||||
window.HTMLMediaElement.prototype.pause = vi.fn();
|
||||
});
|
||||
afterEach(() => cleanup());
|
||||
|
||||
test("renders provided value and label", async () => {
|
||||
const { getByTestId, queryAllByText } = await render(Audio, {
|
||||
show_label: true,
|
||||
loading_status,
|
||||
mode: "dynamic",
|
||||
value: {
|
||||
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
label: "Audio Component",
|
||||
root: "foo",
|
||||
root_url: null,
|
||||
streaming: false,
|
||||
pending: false,
|
||||
name: "bar",
|
||||
source: "upload"
|
||||
});
|
||||
|
||||
assert.isTrue(
|
||||
getByTestId("Audio Component-audio").src.endsWith(
|
||||
"foo/file=https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav"
|
||||
)
|
||||
);
|
||||
assert(queryAllByText("Audio Component").length, 1);
|
||||
});
|
||||
|
||||
test("hides label", async () => {
|
||||
const { queryAllByText } = await render(Audio, {
|
||||
show_label: false,
|
||||
loading_status,
|
||||
mode: "dynamic",
|
||||
value: {
|
||||
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
label: "Audio Component",
|
||||
root: "foo",
|
||||
root_url: null,
|
||||
streaming: false,
|
||||
pending: false,
|
||||
name: "bar",
|
||||
source: "upload"
|
||||
});
|
||||
|
||||
assert(queryAllByText("Audio Component").length, 0);
|
||||
});
|
||||
|
||||
test("upload sets change event", async () => {
|
||||
setupi18n();
|
||||
const { container, component } = await render(Audio, {
|
||||
show_label: false,
|
||||
loading_status,
|
||||
value: null,
|
||||
mode: "dynamic",
|
||||
label: "audio",
|
||||
root: "foo",
|
||||
root_url: null,
|
||||
streaming: false,
|
||||
name: "bar",
|
||||
source: "upload"
|
||||
});
|
||||
|
||||
const item = container.querySelectorAll("input")[0];
|
||||
const file = new File(["hello"], "my-audio.wav", { type: "audio/wav" });
|
||||
event.upload(item, file);
|
||||
const mock = await wait_for_event(component, "change");
|
||||
assert.equal(mock.callCount, 1);
|
||||
assert.equal(
|
||||
component.$capture_state().value.data,
|
||||
"data:audio/wav;base64,aGVsbG8="
|
||||
);
|
||||
assert.equal(component.$capture_state().value.name, "my-audio.wav");
|
||||
});
|
||||
|
||||
test("static audio sets value", async () => {
|
||||
const { getByTestId } = await render(Audio, {
|
||||
show_label: true,
|
||||
loading_status,
|
||||
mode: "static",
|
||||
value: {
|
||||
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
label: "Audio Component",
|
||||
root: "foo",
|
||||
root_url: null,
|
||||
streaming: false,
|
||||
pending: false,
|
||||
name: "bar",
|
||||
source: "upload"
|
||||
});
|
||||
|
||||
assert.isTrue(
|
||||
getByTestId("Audio Component-audio").src.endsWith(
|
||||
"foo/file=https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav"
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
test("stop recording sets data", async () => {
|
||||
let data_event;
|
||||
let stop_event;
|
||||
|
||||
const media_recorder_mock = vi.fn((s, x) => {
|
||||
return {
|
||||
start: vi.fn(() => {
|
||||
data_event({ data: "hello" });
|
||||
data_event({ data: "hello" });
|
||||
data_event({ data: "hello" });
|
||||
data_event({ data: "hello" });
|
||||
}),
|
||||
stop: vi.fn(async () => {
|
||||
await stop_event();
|
||||
}),
|
||||
addEventListener: vi.fn((evt, cb) => {
|
||||
if (evt === "dataavailable") {
|
||||
data_event = cb;
|
||||
}
|
||||
|
||||
if (evt === "stop") {
|
||||
stop_event = cb;
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
const media_mock = {
|
||||
mediaDevices: {
|
||||
getUserMedia: vi.fn(() => Promise.resolve(true))
|
||||
}
|
||||
};
|
||||
|
||||
vi.stubGlobal("navigator", media_mock);
|
||||
vi.stubGlobal("MediaRecorder", media_recorder_mock);
|
||||
|
||||
const { component, getByText } = await render(Audio, {
|
||||
show_label: true,
|
||||
loading_status,
|
||||
mode: "dynamic",
|
||||
value: null,
|
||||
label: "Audio Component",
|
||||
root: "foo",
|
||||
root_url: null,
|
||||
streaming: false,
|
||||
pending: false,
|
||||
source: "microphone",
|
||||
name: "bar"
|
||||
});
|
||||
|
||||
const startButton = getByText("Record from microphone");
|
||||
await event.click(startButton);
|
||||
const stopButton = getByText("Stop recording");
|
||||
await event.click(stopButton);
|
||||
const mock = await wait_for_event(component, "stop_recording");
|
||||
|
||||
assert.equal(
|
||||
component.$capture_state().value.data,
|
||||
"data:audio/wav;base64,aGVsbG9oZWxsb2hlbGxvaGVsbG8="
|
||||
);
|
||||
assert.equal(component.$capture_state().value.name, "audio.wav");
|
||||
assert.equal(mock.callCount, 1);
|
||||
});
|
||||
|
||||
test("when autoplay is true `media.play` should be called in static mode", async () => {
|
||||
const { getByTestId } = await render(Audio, {
|
||||
show_label: true,
|
||||
loading_status,
|
||||
mode: "static",
|
||||
value: {
|
||||
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
label: "static",
|
||||
root: "foo",
|
||||
root_url: null,
|
||||
streaming: false,
|
||||
pending: false,
|
||||
source: "microphone",
|
||||
autoplay: true
|
||||
});
|
||||
|
||||
const startButton = getByTestId<HTMLAudioElement>("static-audio");
|
||||
const fn = spyOn(startButton, "play");
|
||||
startButton.dispatchEvent(new Event("loadeddata"));
|
||||
|
||||
assert.equal(fn.callCount, 1);
|
||||
});
|
||||
|
||||
test("when autoplay is true `media.play` should be called in dynamic mode", async () => {
|
||||
const { getByTestId } = await render(Audio, {
|
||||
show_label: true,
|
||||
loading_status,
|
||||
mode: "dynamic",
|
||||
value: {
|
||||
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
label: "dynamic",
|
||||
root: "foo",
|
||||
root_url: null,
|
||||
streaming: false,
|
||||
pending: false,
|
||||
source: "microphone",
|
||||
autoplay: true
|
||||
});
|
||||
|
||||
const startButton = getByTestId<HTMLAudioElement>("dynamic-audio");
|
||||
const fn = spyOn(startButton, "play");
|
||||
startButton.dispatchEvent(new Event("loadeddata"));
|
||||
|
||||
assert.equal(fn.callCount, 1);
|
||||
});
|
||||
|
||||
test("when autoplay is true `media.play` should be called in static mode when the audio data is updated", async () => {
|
||||
const { component, getByTestId } = await render(Audio, {
|
||||
show_label: true,
|
||||
loading_status,
|
||||
mode: "static",
|
||||
value: {
|
||||
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
label: "static",
|
||||
root: "foo",
|
||||
root_url: null,
|
||||
streaming: false,
|
||||
pending: false,
|
||||
source: "microphone",
|
||||
autoplay: true
|
||||
});
|
||||
|
||||
const startButton = getByTestId<HTMLAudioElement>("static-audio");
|
||||
const fn = spyOn(startButton, "play");
|
||||
|
||||
startButton.dispatchEvent(new Event("loadeddata"));
|
||||
|
||||
component.$set({
|
||||
value: {
|
||||
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
|
||||
data: null,
|
||||
is_file: true
|
||||
}
|
||||
});
|
||||
|
||||
startButton.dispatchEvent(new Event("loadeddata"));
|
||||
|
||||
assert.equal(fn.callCount, 2);
|
||||
});
|
||||
|
||||
test("when autoplay is true `media.play` should be called in dynamic mode when the audio data is updated", async () => {
|
||||
const { component, getByTestId } = await render(Audio, {
|
||||
show_label: true,
|
||||
loading_status,
|
||||
mode: "dynamic",
|
||||
value: {
|
||||
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
label: "dynamic",
|
||||
root: "foo",
|
||||
root_url: null,
|
||||
streaming: false,
|
||||
pending: false,
|
||||
source: "microphone",
|
||||
autoplay: true
|
||||
});
|
||||
|
||||
const startButton = getByTestId<HTMLAudioElement>("dynamic-audio");
|
||||
const fn = spyOn(startButton, "play");
|
||||
|
||||
startButton.dispatchEvent(new Event("loadeddata"));
|
||||
|
||||
component.$set({
|
||||
value: {
|
||||
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
|
||||
data: null,
|
||||
is_file: true
|
||||
}
|
||||
});
|
||||
|
||||
startButton.dispatchEvent(new Event("loadeddata"));
|
||||
|
||||
assert.equal(fn.callCount, 2);
|
||||
});
|
||||
|
||||
test("audio change event trigger fires when value is changed and only fires once", async () => {
|
||||
const { component } = await render(Audio, {
|
||||
show_label: true,
|
||||
loading_status,
|
||||
mode: "static",
|
||||
value: {
|
||||
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
label: "static",
|
||||
root: "foo",
|
||||
root_url: null,
|
||||
streaming: false,
|
||||
pending: false,
|
||||
source: "microphone",
|
||||
autoplay: true
|
||||
});
|
||||
|
||||
const mock = spy();
|
||||
component.$on("change", mock);
|
||||
|
||||
(component.value = [
|
||||
{
|
||||
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample2.wav",
|
||||
data: null,
|
||||
is_file: true
|
||||
}
|
||||
]),
|
||||
assert.equal(mock.callCount, 1);
|
||||
});
|
||||
});
|
@ -1,18 +1,2 @@
|
||||
export { default as Component } from "./Audio.svelte";
|
||||
export { default as Component } from "@gradio/audio";
|
||||
export const modes = ["static", "dynamic"];
|
||||
|
||||
export const document = () => ({
|
||||
type: {
|
||||
input_payload: "{ name: string; data: string }",
|
||||
response_object: "{ name: string; data: string, is_file: boolean }"
|
||||
},
|
||||
description: {
|
||||
input_payload: "audio data as object with filename and base64 string",
|
||||
response_object:
|
||||
"object that includes path to audio file. The URL: {ROOT}file={name} contains the data"
|
||||
},
|
||||
example_data: {
|
||||
name: "audio.wav",
|
||||
data: "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA="
|
||||
}
|
||||
});
|
||||
|
@ -1,8 +0,0 @@
|
||||
export interface Value {
|
||||
data: string;
|
||||
is_example: boolean;
|
||||
name: string;
|
||||
size?: number;
|
||||
crop_min?: number;
|
||||
crop_max?: number;
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
export { default as Component } from "./Box.svelte";
|
||||
export { default as Component } from "@gradio/box";
|
||||
export const modes = ["static"];
|
||||
|
@ -1,60 +0,0 @@
|
||||
<script>
|
||||
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||
import { Button } from "@gradio/button";
|
||||
</script>
|
||||
|
||||
<Meta
|
||||
title="Components/Button"
|
||||
component={Button}
|
||||
argTypes={{
|
||||
label: {
|
||||
control: "text",
|
||||
description: "The text to display on the button",
|
||||
name: "label",
|
||||
value: "Gradio Button"
|
||||
},
|
||||
variant: {
|
||||
options: ["primary", "secondary", "stop"],
|
||||
description: "The variant of the button",
|
||||
control: { type: "select" },
|
||||
defaultValue: "primary"
|
||||
},
|
||||
size: {
|
||||
options: ["sm", "lg"],
|
||||
description: "The size of the button",
|
||||
control: { type: "select" },
|
||||
defaultValue: "lg"
|
||||
},
|
||||
visible: {
|
||||
options: [true, false],
|
||||
description: "Sets the visibility of the button",
|
||||
control: { type: "boolean" },
|
||||
defaultValue: true
|
||||
},
|
||||
interactive: {
|
||||
options: [true, false],
|
||||
description: "If false, the button will be in a disabled state",
|
||||
control: { type: "boolean" },
|
||||
defaultValue: true
|
||||
},
|
||||
disabled: {
|
||||
options: [true, false],
|
||||
control: { type: "boolean" },
|
||||
defaultValue: false
|
||||
},
|
||||
scale: {
|
||||
options: [null, 0.5, 1, 2],
|
||||
description:
|
||||
"relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.",
|
||||
control: { type: "select" }
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<Template let:args>
|
||||
<Button {...args}>{args.label || "Gradio Button"}</Button>
|
||||
</Template>
|
||||
|
||||
<Story name="Primary" args={{ variant: "primary", size: "lg", scale: 1 }} />
|
||||
<Story name="Secondary" args={{ variant: "secondary", size: "lg" }} />
|
||||
<Story name="Stop" source args={{ variant: "stop", size: "lg" }} />
|
@ -1,28 +0,0 @@
|
||||
import { test, describe, assert, afterEach } from "vitest";
|
||||
import { spy } from "tinyspy";
|
||||
import { cleanup, fireEvent, render } from "@gradio/tootils";
|
||||
|
||||
import Button from "./Button.svelte";
|
||||
|
||||
describe("Hello.svelte", () => {
|
||||
afterEach(() => cleanup());
|
||||
|
||||
test.skip("renders label text", async () => {
|
||||
const { container, component } = await render(Button, {
|
||||
value: "Click Me"
|
||||
});
|
||||
assert.equal(container.innerText, "Click Me");
|
||||
});
|
||||
|
||||
test.skip("triggers callback when clicked", async () => {
|
||||
const { container, component } = await render(Button, {
|
||||
value: "Click Me"
|
||||
});
|
||||
const mock = spy();
|
||||
component.$on("click", mock);
|
||||
|
||||
fireEvent.click(container.querySelector("button")!);
|
||||
|
||||
assert.isTrue(mock.called);
|
||||
});
|
||||
});
|
@ -1,12 +1,2 @@
|
||||
export { default as Component } from "./Button.svelte";
|
||||
export { default as Component } from "@gradio/button";
|
||||
export const modes = ["static", "dynamic"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
payload: "string"
|
||||
},
|
||||
description: {
|
||||
payload: "button label"
|
||||
},
|
||||
example_data: config.value || "Run"
|
||||
});
|
||||
|
@ -1,12 +1,2 @@
|
||||
export { default as Component } from "./Checkbox.svelte";
|
||||
export { default as Component } from "@gradio/checkbox";
|
||||
export const modes = ["static", "dynamic"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
payload: "boolean"
|
||||
},
|
||||
description: {
|
||||
payload: "checked status"
|
||||
},
|
||||
example_data: config.value
|
||||
});
|
||||
|
@ -1,12 +1,2 @@
|
||||
export { default as Component } from "./CheckboxGroup.svelte";
|
||||
export { default as Component } from "@gradio/checkboxgroup";
|
||||
export const modes = ["static", "dynamic"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
payload: "Array<string>"
|
||||
},
|
||||
description: {
|
||||
payload: "list of selected choices"
|
||||
},
|
||||
example_data: config.choices.length ? [config.choices[0]] : []
|
||||
});
|
||||
|
@ -1,52 +0,0 @@
|
||||
import { test, describe, assert, afterEach } from "vitest";
|
||||
import { cleanup, render } from "@gradio/tootils";
|
||||
|
||||
import ColorPicker from "./ColorPicker.svelte";
|
||||
import type { LoadingStatus } from "../StatusTracker/types";
|
||||
|
||||
const loading_status = {
|
||||
eta: 0,
|
||||
queue_position: 1,
|
||||
queue_size: 1,
|
||||
status: "complete" as LoadingStatus["status"],
|
||||
scroll_to_output: false,
|
||||
visible: true,
|
||||
fn_index: 0
|
||||
};
|
||||
|
||||
describe("ColorPicker", () => {
|
||||
afterEach(() => cleanup());
|
||||
|
||||
test("renders provided value", async () => {
|
||||
const { getByDisplayValue } = await render(ColorPicker, {
|
||||
loading_status,
|
||||
show_label: true,
|
||||
mode: "dynamic",
|
||||
value: "#000000",
|
||||
label: "ColorPicker"
|
||||
});
|
||||
|
||||
const item: HTMLInputElement = getByDisplayValue("#000000");
|
||||
assert.equal(item.value, "#000000");
|
||||
});
|
||||
|
||||
test("changing the color should update the value", async () => {
|
||||
const { component, getByDisplayValue } = await render(ColorPicker, {
|
||||
loading_status,
|
||||
show_label: true,
|
||||
mode: "dynamic",
|
||||
value: "#000000",
|
||||
label: "ColorPicker"
|
||||
});
|
||||
|
||||
const item: HTMLInputElement = getByDisplayValue("#000000");
|
||||
|
||||
assert.equal(item.value, "#000000");
|
||||
|
||||
await component.$set({
|
||||
value: "#FFFFFF"
|
||||
});
|
||||
|
||||
assert.equal(component.value, "#FFFFFF");
|
||||
});
|
||||
});
|
@ -1,12 +1,2 @@
|
||||
export { default as Component } from "./ColorPicker.svelte";
|
||||
export { default as Component } from "@gradio/colorpicker";
|
||||
export const modes = ["static", "dynamic"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
payload: "string"
|
||||
},
|
||||
description: {
|
||||
payload: "hex color code"
|
||||
},
|
||||
example_data: config.value ?? "#000000"
|
||||
});
|
||||
|
@ -1,2 +1,2 @@
|
||||
export { default as Component } from "./Column.svelte";
|
||||
export { default as Component } from "@gradio/column";
|
||||
export const modes = ["static"];
|
||||
|
@ -1,12 +1,2 @@
|
||||
export { default as Component } from "./DataFrame.svelte";
|
||||
export { default as Component } from "@gradio/dataframe";
|
||||
export const modes = ["static", "dynamic"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
payload: "{ data: Array<Array<string | number>>; headers: Array<string> }"
|
||||
},
|
||||
description: {
|
||||
payload: "an object with an array of data and an array of headers"
|
||||
},
|
||||
example_data: config.value
|
||||
});
|
||||
|
@ -37,10 +37,10 @@
|
||||
|
||||
let current_hover = -1;
|
||||
|
||||
function handle_mouseenter(i: number) {
|
||||
function handle_mouseenter(i: number): void {
|
||||
current_hover = i;
|
||||
}
|
||||
function handle_mouseleave() {
|
||||
function handle_mouseleave(): void {
|
||||
current_hover = -1;
|
||||
}
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { Value } from "../../Audio/types";
|
||||
|
||||
export let value: Value;
|
||||
export let type: "gallery" | "table";
|
||||
export let selected: boolean = false;
|
||||
</script>
|
||||
|
||||
<div
|
||||
class:table={type === "table"}
|
||||
class:gallery={type === "gallery"}
|
||||
class:selected
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.gallery {
|
||||
padding: var(--size-1) var(--size-2);
|
||||
}
|
||||
</style>
|
@ -1,21 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { Value } from "../../Audio/types";
|
||||
|
||||
export let value: Value;
|
||||
export let type: "gallery" | "table";
|
||||
export let selected: boolean = false;
|
||||
</script>
|
||||
|
||||
<div
|
||||
class:table={type === "table"}
|
||||
class:gallery={type === "gallery"}
|
||||
class:selected
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.gallery {
|
||||
padding: var(--size-1) var(--size-2);
|
||||
}
|
||||
</style>
|
@ -1,21 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { Value } from "../../Audio/types";
|
||||
|
||||
export let value: Value;
|
||||
export let type: "gallery" | "table";
|
||||
export let selected: boolean = false;
|
||||
</script>
|
||||
|
||||
<div
|
||||
class:table={type === "table"}
|
||||
class:gallery={type === "gallery"}
|
||||
class:selected
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.gallery {
|
||||
padding: var(--size-1) var(--size-2);
|
||||
}
|
||||
</style>
|
@ -1,21 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { Value } from "../../Audio/types";
|
||||
|
||||
export let value: Value;
|
||||
export let type: "gallery" | "table";
|
||||
export let selected: boolean = false;
|
||||
</script>
|
||||
|
||||
<div
|
||||
class:table={type === "table"}
|
||||
class:gallery={type === "gallery"}
|
||||
class:selected
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.gallery {
|
||||
padding: var(--size-1) var(--size-2);
|
||||
}
|
||||
</style>
|
@ -1,21 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { Value } from "../../Audio/types";
|
||||
|
||||
export let value: Value;
|
||||
export let type: "gallery" | "table";
|
||||
export let selected: boolean = false;
|
||||
</script>
|
||||
|
||||
<div
|
||||
class:table={type === "table"}
|
||||
class:gallery={type === "gallery"}
|
||||
class:selected
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.gallery {
|
||||
padding: var(--size-1) var(--size-2);
|
||||
}
|
||||
</style>
|
@ -1,21 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { Value } from "../../Audio/types";
|
||||
|
||||
export let value: Value;
|
||||
export let type: "gallery" | "table";
|
||||
export let selected: boolean = false;
|
||||
</script>
|
||||
|
||||
<div
|
||||
class:table={type === "table"}
|
||||
class:gallery={type === "gallery"}
|
||||
class:selected
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.gallery {
|
||||
padding: var(--size-1) var(--size-2);
|
||||
}
|
||||
</style>
|
@ -1,21 +1,21 @@
|
||||
import ExampleNumber from "./ExampleComponents/Number.svelte";
|
||||
import ExampleDropdown from "./ExampleComponents/Dropdown.svelte";
|
||||
import ExampleCheckbox from "./ExampleComponents/Checkbox.svelte";
|
||||
import ExampleCheckboxGroup from "./ExampleComponents/CheckboxGroup.svelte";
|
||||
import ExampleSlider from "./ExampleComponents/Slider.svelte";
|
||||
import ExampleRadio from "./ExampleComponents/Radio.svelte";
|
||||
import ExampleImage from "./ExampleComponents/Image.svelte";
|
||||
import ExampleTextbox from "./ExampleComponents/Textbox.svelte";
|
||||
import ExampleAudio from "./ExampleComponents/Audio.svelte";
|
||||
import ExampleVideo from "./ExampleComponents/Video.svelte";
|
||||
import ExampleFile from "./ExampleComponents/File.svelte";
|
||||
import ExampleDataframe from "./ExampleComponents/Dataframe.svelte";
|
||||
import ExampleModel3D from "./ExampleComponents/Model3D.svelte";
|
||||
import ExampleColorPicker from "./ExampleComponents/ColorPicker.svelte";
|
||||
import ExampleTimeSeries from "./ExampleComponents/TimeSeries.svelte";
|
||||
import ExampleMarkdown from "./ExampleComponents/Markdown.svelte";
|
||||
import ExampleHTML from "./ExampleComponents/HTML.svelte";
|
||||
import ExampleCode from "./ExampleComponents/Code.svelte";
|
||||
import ExampleNumber from "@gradio/number/example";
|
||||
import ExampleDropdown from "@gradio/dropdown/example";
|
||||
import ExampleCheckbox from "@gradio/checkbox/example";
|
||||
import ExampleCheckboxGroup from "@gradio/checkboxgroup/example";
|
||||
import ExampleSlider from "@gradio/slider/example";
|
||||
import ExampleRadio from "@gradio/radio/example";
|
||||
import ExampleImage from "@gradio/image/example";
|
||||
import ExampleTextbox from "@gradio/textbox/example";
|
||||
import ExampleAudio from "@gradio/audio/example";
|
||||
import ExampleVideo from "@gradio/video/example";
|
||||
import ExampleFile from "@gradio/file/example";
|
||||
import ExampleDataframe from "@gradio/dataframe/example";
|
||||
import ExampleModel3D from "@gradio/model3d/example";
|
||||
import ExampleColorPicker from "@gradio/colorpicker/example";
|
||||
import ExampleTimeSeries from "@gradio/timeseries/example";
|
||||
import ExampleMarkdown from "@gradio/markdown/example";
|
||||
import ExampleHTML from "@gradio/html/example";
|
||||
import ExampleCode from "@gradio/code/example";
|
||||
|
||||
export const component_map = {
|
||||
dropdown: ExampleDropdown,
|
||||
|
@ -1,12 +1,2 @@
|
||||
export { default as Component } from "./Dataset.svelte";
|
||||
export const modes = ["dynamic"];
|
||||
|
||||
export const document = () => ({
|
||||
type: {
|
||||
payload: "number"
|
||||
},
|
||||
description: {
|
||||
payload: "index of selected row"
|
||||
},
|
||||
example_data: 0
|
||||
});
|
||||
|
@ -1,54 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { Dropdown } from "@gradio/form";
|
||||
import { Block } from "@gradio/atoms";
|
||||
import StatusTracker from "../StatusTracker/StatusTracker.svelte";
|
||||
import type { LoadingStatus } from "../StatusTracker/types";
|
||||
|
||||
export let label: string = "Dropdown";
|
||||
export let info: string | undefined = undefined;
|
||||
export let elem_id: string = "";
|
||||
export let elem_classes: Array<string> = [];
|
||||
export let visible: boolean = true;
|
||||
export let value: string | Array<string>;
|
||||
export let value_is_output: boolean = false;
|
||||
export let multiselect: boolean = false;
|
||||
export let max_choices: number;
|
||||
export let choices: Array<string>;
|
||||
export let show_label: boolean;
|
||||
export let container: boolean = true;
|
||||
export let scale: number | null = null;
|
||||
export let min_width: number | undefined = undefined;
|
||||
export let loading_status: LoadingStatus;
|
||||
export let allow_custom_value: boolean = false;
|
||||
|
||||
export let mode: "static" | "dynamic";
|
||||
|
||||
if (multiselect && !value) {
|
||||
value = [];
|
||||
} else if (!value) {
|
||||
value = "";
|
||||
}
|
||||
</script>
|
||||
|
||||
<Block {visible} {elem_id} {elem_classes} padding={container} allow_overflow={false} {scale} {min_width}>
|
||||
<StatusTracker {...loading_status} />
|
||||
|
||||
<Dropdown
|
||||
bind:value
|
||||
bind:value_is_output
|
||||
{choices}
|
||||
{multiselect}
|
||||
{max_choices}
|
||||
{label}
|
||||
{info}
|
||||
{show_label}
|
||||
{allow_custom_value}
|
||||
{container}
|
||||
on:change
|
||||
on:input
|
||||
on:select
|
||||
on:blur
|
||||
on:focus
|
||||
disabled={mode === "static"}
|
||||
/>
|
||||
</Block>
|
@ -1,12 +1,2 @@
|
||||
export { default as Component } from "./Dropdown.svelte";
|
||||
export { default as Component } from "@gradio/dropdown";
|
||||
export const modes = ["static", "dynamic"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
payload: "string"
|
||||
},
|
||||
description: {
|
||||
payload: "selected choice"
|
||||
},
|
||||
example_data: config.choices.length ? config.choices[0] : ""
|
||||
});
|
||||
|
@ -1,76 +0,0 @@
|
||||
import { test, describe, expect, afterEach, vi, assert } from "vitest";
|
||||
import { cleanup, render } from "@gradio/tootils";
|
||||
import { spy } from "tinyspy";
|
||||
|
||||
import File from "./File.svelte";
|
||||
import type { LoadingStatus } from "../StatusTracker/types";
|
||||
import { upload_files } from "@gradio/client";
|
||||
|
||||
const loading_status = {
|
||||
eta: 0,
|
||||
queue_position: 1,
|
||||
queue_size: 1,
|
||||
status: "complete" as LoadingStatus["status"],
|
||||
scroll_to_output: false,
|
||||
visible: true,
|
||||
fn_index: 0
|
||||
};
|
||||
|
||||
describe("File", () => {
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
test("gr.File uploads with blob", async () => {
|
||||
vi.mock("@gradio/client", async () => {
|
||||
return {
|
||||
upload_files: vi.fn((f) => new Promise((res) => res({})))
|
||||
};
|
||||
});
|
||||
|
||||
const api = await import("@gradio/client");
|
||||
|
||||
await render(File, {
|
||||
loading_status,
|
||||
label: "file",
|
||||
// @ts-ignore
|
||||
value: { name: "freddy.json", data: "{'name': 'freddy'}", blob: vi.fn() },
|
||||
show_label: true,
|
||||
mode: "dynamic",
|
||||
root: "http://localhost:7860",
|
||||
file_count: "1",
|
||||
root_url: null
|
||||
});
|
||||
|
||||
expect(api.upload_files).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("gr.File does not upload without blob", async () => {
|
||||
const mockUpload = vi.fn(upload_files);
|
||||
|
||||
const { component } = await render(File, {
|
||||
loading_status,
|
||||
label: "file",
|
||||
value: { name: "freddy.json", data: "{'name': 'freddy'}" },
|
||||
show_label: true,
|
||||
mode: "dynamic",
|
||||
root: "http://localhost:7860",
|
||||
file_count: "1",
|
||||
root_url: null
|
||||
});
|
||||
|
||||
expect(mockUpload).not.toHaveBeenCalled();
|
||||
|
||||
const mock = spy();
|
||||
component.$on("change", mock);
|
||||
|
||||
component.value = {
|
||||
name: "freddy_2.json",
|
||||
data: "{'name': 'freddy'}",
|
||||
is_file: true
|
||||
};
|
||||
|
||||
assert.equal(mock.callCount, 1);
|
||||
});
|
||||
});
|
@ -1,19 +1,2 @@
|
||||
export { default as Component } from "./File.svelte";
|
||||
export { default as Component } from "@gradio/file";
|
||||
export const modes = ["static", "dynamic"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
input_payload: "{ name: string; data: string }",
|
||||
response_object:
|
||||
"{ orig_name: string; name: string, size: number, data: string, is_file: boolean}"
|
||||
},
|
||||
description: {
|
||||
input_payload: "object with file name and base64 data",
|
||||
response_object:
|
||||
"object that includes path to file. The URL: {ROOT}file={name} contains the data"
|
||||
},
|
||||
example_data: {
|
||||
name: "zip.zip",
|
||||
data: "data:@file/octet-stream;base64,UEsFBgAAAAAAAAAAAAAAAAAAAAAAAA=="
|
||||
}
|
||||
});
|
||||
|
@ -1,2 +1,2 @@
|
||||
export { default as Component } from "./Form.svelte";
|
||||
export { default as Component } from "@gradio/form";
|
||||
export const modes = ["static"];
|
||||
|
@ -1,104 +0,0 @@
|
||||
import { test, describe, assert, afterEach, vi } from "vitest";
|
||||
import { cleanup, render } from "@gradio/tootils";
|
||||
|
||||
import Gallery from "./Gallery.svelte";
|
||||
import type { LoadingStatus } from "../StatusTracker/types";
|
||||
|
||||
const loading_status: LoadingStatus = {
|
||||
eta: 0,
|
||||
queue_position: 1,
|
||||
queue_size: 1,
|
||||
status: "complete",
|
||||
scroll_to_output: false,
|
||||
visible: true,
|
||||
fn_index: 0,
|
||||
show_progress: "full"
|
||||
};
|
||||
|
||||
describe("Gallery", () => {
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
test("preview shows detailed image by default", async () => {
|
||||
window.Element.prototype.scrollTo = vi.fn(() => {});
|
||||
|
||||
const { getAllByTestId, getByTestId } = await render(Gallery, {
|
||||
loading_status,
|
||||
label: "gallery",
|
||||
// @ts-ignore
|
||||
value: [
|
||||
[
|
||||
{
|
||||
name: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
"label 0"
|
||||
],
|
||||
[
|
||||
{
|
||||
name: "https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
"label 1"
|
||||
]
|
||||
],
|
||||
show_label: true,
|
||||
mode: "dynamic",
|
||||
root: "http://localhost:7860",
|
||||
root_url: null,
|
||||
preview: true
|
||||
});
|
||||
|
||||
const details = getAllByTestId("detailed-image");
|
||||
|
||||
assert.equal(details.length, 1);
|
||||
});
|
||||
|
||||
test("detailed view does not show larger image", async () => {
|
||||
const { queryAllByTestId, getByTestId } = await render(Gallery, {
|
||||
loading_status,
|
||||
label: "gallery",
|
||||
// @ts-ignore
|
||||
value: [
|
||||
[
|
||||
{
|
||||
name: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
"label 0"
|
||||
],
|
||||
[
|
||||
{
|
||||
name: "https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
"label 1"
|
||||
],
|
||||
[
|
||||
{
|
||||
name: "https://images.unsplash.com/photo-1601412436009-d964bd02edbc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=464&q=80",
|
||||
data: null,
|
||||
is_file: true
|
||||
},
|
||||
"label 2"
|
||||
]
|
||||
],
|
||||
show_label: true,
|
||||
mode: "dynamic",
|
||||
root: "http://localhost:7860",
|
||||
root_url: null,
|
||||
preview: true,
|
||||
allow_preview: false
|
||||
});
|
||||
|
||||
const details = queryAllByTestId("detailed-image");
|
||||
|
||||
assert.equal(details.length, 0);
|
||||
});
|
||||
});
|
@ -1,11 +1,2 @@
|
||||
export { default as Component } from "./Gallery.svelte";
|
||||
export { default as Component } from "@gradio/gallery";
|
||||
export const modes = ["static"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
payload: "Array<{ name: string } | [{ name: string }, string]>"
|
||||
},
|
||||
description: {
|
||||
payload: "list of objects, with filename and optional caption,"
|
||||
}
|
||||
});
|
||||
|
@ -1,2 +1,2 @@
|
||||
export { default as Component } from "./Group.svelte";
|
||||
export { default as Component } from "@gradio/group";
|
||||
export const modes = ["static"];
|
||||
|
@ -1,11 +1,2 @@
|
||||
export { default as Component } from "./HTML.svelte";
|
||||
export { default as Component } from "@gradio/html";
|
||||
export const modes = ["static"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
payload: "string"
|
||||
},
|
||||
description: {
|
||||
payload: "HTML output"
|
||||
}
|
||||
});
|
||||
|
@ -1,11 +1,2 @@
|
||||
export { default as Component } from "./HighlightedText.svelte";
|
||||
export { default as Component } from "@gradio/highlightedtext";
|
||||
export const modes = ["static"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
payload: "Array<[string, string | number]>"
|
||||
},
|
||||
description: {
|
||||
payload: "list of text spans and corresponding label / value"
|
||||
}
|
||||
});
|
||||
|
@ -1,14 +1,3 @@
|
||||
export { default as Component } from "./Image.svelte";
|
||||
export { default as ExampleComponent } from "../Dataset/ExampleComponents/Image.svelte";
|
||||
export { default as Component } from "@gradio/image";
|
||||
export { default as ExampleComponent } from "@gradio/image/example";
|
||||
export const modes = ["static", "dynamic"];
|
||||
|
||||
export const document = (config: Record<string, any>) => ({
|
||||
type: {
|
||||
payload: "string"
|
||||
},
|
||||
description: {
|
||||
payload: "image data as base64 string"
|
||||
},
|
||||
example_data:
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg=="
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { getSaliencyColor } from "../utils";
|
||||
import { BlockTitle } from "@gradio/atoms";
|
||||
export let interpretation: Array<number>;
|
||||
export let label: string = "";
|
||||
export let interpretation: number[];
|
||||
export let label = "";
|
||||
</script>
|
||||
|
||||
<div>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user