Skip to content

Commit

Permalink
Add step param to Number (#5047)
Browse files Browse the repository at this point in the history
* add step param to number component

* add changeset

* fix test

* fix BE test

* fix test again

* update number.py

* fix test

* test fix

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
  • Loading branch information
hannahblair and gradio-pr-bot committed Aug 1, 2023
1 parent 6693660 commit 883ac36
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 18 deletions.
7 changes: 7 additions & 0 deletions .changeset/plain-ties-pick.md
@@ -0,0 +1,7 @@
---
"@gradio/app": minor
"@gradio/form": minor
"gradio": minor
---

feat:Add `step` param to `Number`
6 changes: 6 additions & 0 deletions gradio/components/number.py
Expand Up @@ -60,6 +60,7 @@ def __init__(
precision: int | None = None,
minimum: float | None = None,
maximum: float | None = None,
step: float = 1,
**kwargs,
):
"""
Expand All @@ -79,10 +80,12 @@ def __init__(
precision: Precision to round input/output to. If set to 0, will round to nearest integer and convert type to int. If None, no rounding happens.
minimum: Minimum value. Only applied when component is used as an input. If a user provides a smaller value, a gr.Error exception is raised by the backend.
maximum: Maximum value. Only applied when component is used as an input. If a user provides a larger value, a gr.Error exception is raised by the backend.
step: The interval between allowed numbers in the component. Can be used along with optional parameters `minimum` and `maximum` to create a range of legal values starting from `minimum` and incrementing according to this parameter.
"""
self.precision = precision
self.minimum = minimum
self.maximum = maximum
self.step = step

IOComponent.__init__(
self,
Expand Down Expand Up @@ -127,6 +130,7 @@ def get_config(self):
"value": self.value,
"minimum": self.minimum,
"maximum": self.maximum,
"step": self.step,
"container": self.container,
**IOComponent.get_config(self),
}
Expand All @@ -136,6 +140,7 @@ def update(
value: float | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
minimum: float | None = None,
maximum: float | None = None,
step: float = 1,
label: str | None = None,
info: str | None = None,
show_label: bool | None = None,
Expand All @@ -156,6 +161,7 @@ def update(
"value": value,
"minimum": minimum,
"maximum": maximum,
"step": step,
"interactive": interactive,
"__type__": "update",
}
Expand Down
39 changes: 39 additions & 0 deletions js/app/src/components/Number/Number.stories.svelte
@@ -0,0 +1,39 @@
<script>
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
import Number from "./Number.svelte";
</script>

<Meta title="Components/Number" component={Number} />

<Template let:args>
<Number {...args} />
</Template>

<Story
name="Number with min 0 and max 100"
args={{
minimum: 0,
maximum: 100,
}}
/>

<Story
name="Number with step of 10"
args={{
step: 10,
}}
/>

<Story
name="Number in disabled state"
args={{
mode: "static",
}}
/>

<Story
name="Number with hidden label"
args={{
show_label: false,
}}
/>
26 changes: 18 additions & 8 deletions js/app/src/components/Number/Number.svelte
Expand Up @@ -4,24 +4,33 @@
import StatusTracker from "../StatusTracker/StatusTracker.svelte";
import type { LoadingStatus } from "../StatusTracker/types";
export let label: string = "Number";
export let label = "Number";
export let info: string | undefined = undefined;
export let elem_id: string = "";
export let elem_classes: Array<string> = [];
export let visible: boolean = true;
export let container: boolean = true;
export let elem_id = "";
export let elem_classes: string[] = [];
export let visible = true;
export let container = true;
export let scale: number | null = null;
export let min_width: number | undefined = undefined;
export let value: number = 0;
export let value = 0;
export let show_label: boolean;
export let minimum: number | undefined = undefined;
export let maximum: number | undefined = undefined;
export let loading_status: LoadingStatus;
export let mode: "static" | "dynamic";
export let value_is_output: boolean = false;
export let value_is_output = false;
export let step: number | null = null;
</script>

<Block {visible} {elem_id} {elem_classes} padding={container} allow_overflow={false} {scale} {min_width}>
<Block
{visible}
{elem_id}
{elem_classes}
padding={container}
allow_overflow={false}
{scale}
{min_width}
>
<StatusTracker {...loading_status} />

<Number
Expand All @@ -32,6 +41,7 @@
{show_label}
{minimum}
{maximum}
{step}
{container}
disabled={mode === "static"}
on:change
Expand Down
22 changes: 12 additions & 10 deletions js/form/src/Number.svelte
Expand Up @@ -2,15 +2,16 @@
import { afterUpdate, createEventDispatcher, tick } from "svelte";
import { BlockTitle } from "@gradio/atoms";
export let value: number = 0;
export let value = 0;
export let minimum: number | undefined = undefined;
export let maximum: number | undefined = undefined;
export let value_is_output: boolean = false;
export let disabled: boolean = false;
export let value_is_output = false;
export let disabled = false;
export let label: string;
export let info: string | undefined = undefined;
export let show_label: boolean = true;
export let container: boolean = true;
export let show_label = true;
export let container = true;
export let step: number | null = 1;
const dispatch = createEventDispatcher<{
change: number;
Expand All @@ -19,7 +20,7 @@
input: undefined;
}>();
function handle_change() {
function handle_change(): void {
if (!isNaN(value) && value !== null) {
dispatch("change", value);
if (!value_is_output) {
Expand All @@ -32,35 +33,36 @@
});
$: value, handle_change();
async function handle_keypress(e: KeyboardEvent) {
async function handle_keypress(e: KeyboardEvent): Promise<void> {
await tick();
if (e.key === "Enter") {
e.preventDefault();
dispatch("submit");
}
}
function handle_blur(e: FocusEvent) {
function handle_blur(e: FocusEvent): void {
dispatch("blur");
}
</script>

<!-- svelte-ignore a11y-label-has-associated-control -->
<label class="block" class:container>
<BlockTitle {show_label} {info}>{label}</BlockTitle>
<input
type="number"
bind:value
min={minimum}
max={maximum}
{step}
on:keypress={handle_keypress}
on:blur={handle_blur}
{disabled}
/>
</label>

<style>
label:not(.container), label:not(.container) > input {
label:not(.container),
label:not(.container) > input {
height: 100%;
border: none;
}
Expand Down
2 changes: 2 additions & 0 deletions test/test_components.py
Expand Up @@ -216,6 +216,7 @@ def test_component_functions(self):
"value": None,
"name": "number",
"show_label": True,
"step": 1,
"label": None,
"minimum": None,
"maximum": None,
Expand Down Expand Up @@ -265,6 +266,7 @@ def test_component_functions_integer(self):
"value": 42,
"name": "number",
"show_label": True,
"step": 1,
"label": None,
"minimum": None,
"maximum": None,
Expand Down

1 comment on commit 883ac36

@vercel
Copy link

@vercel vercel bot commented on 883ac36 Aug 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.