Skip to content

Commit

Permalink
V4: Single-file implementation of form components (#6026)
Browse files Browse the repository at this point in the history
* Checkbox and number

* Number, Checkboxgroup, Radio, and Slider

* Format

* remove range

* Refactor checkbox

* Forgot to add

* Refactor

* Lint

* add changeset

* use rich emoji markup

* Fix ts

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
  • Loading branch information
freddyaboulton and gradio-pr-bot committed Oct 25, 2023
1 parent 825c9cd commit 338969a
Show file tree
Hide file tree
Showing 18 changed files with 550 additions and 607 deletions.
10 changes: 10 additions & 0 deletions .changeset/plenty-parks-glow.md
@@ -0,0 +1,10 @@
---
"@gradio/checkbox": minor
"@gradio/checkboxgroup": minor
"@gradio/number": minor
"@gradio/radio": minor
"@gradio/slider": minor
"gradio": minor
---

feat:V4: Single-file implementation of form components
11 changes: 9 additions & 2 deletions gradio/_simple_templates/simpledropdown.py
Expand Up @@ -33,7 +33,9 @@ def __init__(
visible: bool = True,
elem_id: str | None = None,
elem_classes: list[str] | str | None = None,
**kwargs,
render: bool = True,
root_url: str | None = None,
_skip_init_processing: bool = False,
):
"""
Parameters:
Expand All @@ -49,6 +51,9 @@ def __init__(
visible: If False, component will be hidden.
elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
render: bool = True,
root_url: str | None = None,
_skip_init_processing: bool = False,
"""
self.choices = (
# Although we expect choices to be a list of lists, it can be a list of tuples if the Gradio app
Expand All @@ -69,7 +74,9 @@ def __init__(
elem_id=elem_id,
elem_classes=elem_classes,
value=value,
**kwargs,
render=render,
root_url=root_url,
_skip_init_processing=_skip_init_processing,
)

def api_info(self) -> dict[str, Any]:
Expand Down
10 changes: 8 additions & 2 deletions gradio/_simple_templates/simpletextbox.py
Expand Up @@ -35,7 +35,9 @@ def __init__(
rtl: bool = False,
elem_id: str | None = None,
elem_classes: list[str] | str | None = None,
**kwargs,
render: bool = True,
root_url: str | None = None,
_skip_init_processing: bool = False,
):
"""
Parameters:
Expand All @@ -51,6 +53,8 @@ def __init__(
rtl: If True and `type` is "text", sets the direction of the text to right-to-left (cursor appears on the left of the text). Default is False, which renders cursor on the right.
elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
root_url: The remote URL that of the Gradio app that this component belongs to. Used in `gr.load()`. Should not be set manually.
"""
self.placeholder = placeholder
self.rtl = rtl
Expand All @@ -65,7 +69,9 @@ def __init__(
elem_id=elem_id,
elem_classes=elem_classes,
value=value,
**kwargs,
render=render,
root_url=root_url,
_skip_init_processing=_skip_init_processing,
)

def preprocess(self, x: str | None) -> str | None:
Expand Down
10 changes: 6 additions & 4 deletions gradio/cli/commands/components/show.py
Expand Up @@ -25,6 +25,8 @@
"State",
}

_BEGINNER_FRIENDLY = {"Slider", "Radio", "Checkbox", "Number", "CheckboxGroup", "File"}


def _get_table_items(module):
items = []
Expand All @@ -35,12 +37,12 @@ def _get_table_items(module):
) or (name in _IGNORE):
continue
tags = []
if "Simple" in name or name in {"File"}:
tags.append("馃尡馃Beginner Friendly馃尡馃")
if "Simple" in name or name in _BEGINNER_FRIENDLY:
tags.append(":seedling::handshake:Beginner Friendly:seedling::handshake:")
if issubclass(gr_cls, FormComponent):
tags.append("馃摑馃ЗForm Component馃摑馃З")
tags.append(":pencil::jigsaw:Form Component:pencil::jigsaw:")
if name in gradio.layouts.__all__:
tags.append("馃搻Layout馃搻")
tags.append(":triangular_ruler:Layout:triangular_ruler:")
doc = inspect.getdoc(gr_cls) or "No description available."
doc = doc.split(".")[0]
if tags:
Expand Down
1 change: 1 addition & 0 deletions gradio/components/video.py
Expand Up @@ -52,6 +52,7 @@ class Video(Component):
Events.play,
Events.pause,
Events.end,
Events.upload,
]

def __init__(
Expand Down
30 changes: 23 additions & 7 deletions js/checkbox/Index.svelte
@@ -1,10 +1,15 @@
<script context="module" lang="ts">
export { default as BaseCheckbox } from "./shared/Checkbox.svelte";
</script>

<script lang="ts">
import type { Gradio } from "@gradio/utils";
import Checkbox from "./shared/Checkbox.svelte";
import { Block, Info } from "@gradio/atoms";
import { StatusTracker } from "@gradio/statustracker";
import type { LoadingStatus } from "@gradio/statustracker";
import type { SelectData } from "@gradio/utils";
import { afterUpdate } from "svelte";
import BaseCheckbox from "./shared/Checkbox.svelte";
export let elem_id = "";
export let elem_classes: string[] = [];
Expand All @@ -23,6 +28,19 @@
input: never;
}>;
export let mode: "static" | "interactive";
function handle_change(): void {
gradio.dispatch("change");
if (!value_is_output) {
gradio.dispatch("input");
}
}
afterUpdate(() => {
value_is_output = false;
});
// When the value changes, dispatch the change event via handle_change()
// See the docs for an explanation: https://svelte.dev/docs/svelte-components#script-3-$-marks-a-statement-as-reactive
</script>

<Block {visible} {elem_id} {elem_classes} {container} {scale} {min_width}>
Expand All @@ -36,13 +54,11 @@
<Info>{info}</Info>
{/if}

<Checkbox
{label}
<BaseCheckbox
bind:value
bind:value_is_output
on:change={() => gradio.dispatch("change")}
on:input={() => gradio.dispatch("input")}
{label}
{mode}
on:change={handle_change}
on:select={(e) => gradio.dispatch("select", e.detail)}
disabled={mode === "static"}
/>
</Block>
1 change: 1 addition & 0 deletions js/checkbox/package.json
Expand Up @@ -7,6 +7,7 @@
"license": "ISC",
"private": false,
"main_changeset": true,
"main": "./Index.svelte",
"exports": {
".": "./Index.svelte",
"./example": "./Example.svelte",
Expand Down
64 changes: 32 additions & 32 deletions js/checkbox/shared/Checkbox.svelte
@@ -1,51 +1,51 @@
<script lang="ts">
import { createEventDispatcher, afterUpdate } from "svelte";
import type { SelectData } from "@gradio/utils";
import { createEventDispatcher } from "svelte";
export let value: boolean;
export let value_is_output = false;
export let disabled = false;
export let label: string;
export let value = false;
export let label = "Checkbox";
export let mode: "static" | "interactive";
const dispatch = createEventDispatcher<{
change: boolean;
select: SelectData;
input: undefined;
}>();
function handle_change(): void {
dispatch("change", value);
if (!value_is_output) {
dispatch("input");
// When the value changes, dispatch the change event via handle_change()
// See the docs for an explanation: https://svelte.dev/docs/svelte-components#script-3-$-marks-a-statement-as-reactive
$: value, dispatch("change", value);
$: disabled = mode === "static";
async function handle_enter(
event: KeyboardEvent & { currentTarget: EventTarget & HTMLInputElement }
): Promise<void> {
if (event.key === "Enter") {
value = !value;
dispatch("select", {
index: 0,
value: event.currentTarget.checked,
selected: event.currentTarget.checked
});
}
}
afterUpdate(() => {
value_is_output = false;
});
$: value, handle_change();
async function handle_input(
event: Event & { currentTarget: EventTarget & HTMLInputElement }
): Promise<void> {
value = event.currentTarget.checked;
dispatch("select", {
index: 0,
value: event.currentTarget.checked,
selected: event.currentTarget.checked
});
}
</script>

<label class:disabled>
<input
bind:checked={value}
on:keydown={(event) => {
if (event.key === "Enter") {
value = !value;
dispatch("select", {
index: 0,
value: label,
selected: value
});
}
}}
on:input={(evt) => {
value = evt.currentTarget.checked;
dispatch("select", {
index: 0,
value: label,
selected: evt.currentTarget.checked
});
}}
on:keydown={handle_enter}
on:input={handle_input}
{disabled}
type="checkbox"
name="test"
Expand Down
2 changes: 1 addition & 1 deletion js/checkboxgroup/Checkboxgroup.stories.svelte
@@ -1,6 +1,6 @@
<script>
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
import Checkboxgroup from "./shared/Checkboxgroup.svelte";
import Checkboxgroup from "./Index.svelte";
</script>

<Meta
Expand Down

0 comments on commit 338969a

Please sign in to comment.