feat: scaffold FloorPlan custom component, add Python backend
Browse files- floorplan/.gitignore +12 -0
- floorplan/README.md +10 -0
- floorplan/backend/gradio_floorplan/__init__.py +4 -0
- floorplan/backend/gradio_floorplan/floorplan.py +126 -0
- floorplan/backend/tests/__init__.py +0 -0
- floorplan/backend/tests/test_floorplan.py +52 -0
- floorplan/demo/__init__.py +0 -0
- floorplan/demo/app.py +17 -0
- floorplan/frontend/Example.svelte +52 -0
- floorplan/frontend/Index.svelte +112 -0
- floorplan/frontend/gradio.config.js +9 -0
- floorplan/frontend/package.json +41 -0
- floorplan/frontend/tsconfig.json +14 -0
- floorplan/frontend/types.ts +14 -0
- floorplan/pyproject.toml +59 -0
- floorplan/uv.lock +0 -0
floorplan/.gitignore
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.eggs/
|
| 2 |
+
dist/
|
| 3 |
+
*.pyc
|
| 4 |
+
__pycache__/
|
| 5 |
+
*.py[cod]
|
| 6 |
+
*$py.class
|
| 7 |
+
__tmp/*
|
| 8 |
+
*.pyi
|
| 9 |
+
.mypycache
|
| 10 |
+
.ruff_cache
|
| 11 |
+
node_modules
|
| 12 |
+
backend/**/templates/
|
floorplan/README.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
# gradio_floorplan
|
| 3 |
+
A Custom Gradio component.
|
| 4 |
+
|
| 5 |
+
## Example usage
|
| 6 |
+
|
| 7 |
+
```python
|
| 8 |
+
import gradio as gr
|
| 9 |
+
from gradio_floorplan import FloorPlan
|
| 10 |
+
```
|
floorplan/backend/gradio_floorplan/__init__.py
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
from .floorplan import FloorPlan
|
| 3 |
+
|
| 4 |
+
__all__ = ['FloorPlan']
|
floorplan/backend/gradio_floorplan/floorplan.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
import copy
|
| 3 |
+
from typing import TYPE_CHECKING
|
| 4 |
+
from gradio.components.base import Component
|
| 5 |
+
|
| 6 |
+
if TYPE_CHECKING:
|
| 7 |
+
from gradio.components import Timer
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
_DEFAULTS = {
|
| 11 |
+
"corners": [[50, 50], [550, 50], [550, 450], [50, 450]],
|
| 12 |
+
"furnitures": [
|
| 13 |
+
{
|
| 14 |
+
"object": "Sofa",
|
| 15 |
+
"localisation": [150, 100, 250, 300],
|
| 16 |
+
"description": "3-seat sofa",
|
| 17 |
+
},
|
| 18 |
+
{
|
| 19 |
+
"object": "Table",
|
| 20 |
+
"localisation": [300, 200, 380, 400],
|
| 21 |
+
"description": "Coffee table",
|
| 22 |
+
},
|
| 23 |
+
],
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class FloorPlan(Component):
|
| 28 |
+
"""
|
| 29 |
+
A Gradio component that renders an interactive SVG floor plan.
|
| 30 |
+
|
| 31 |
+
Input/Output value shape:
|
| 32 |
+
{
|
| 33 |
+
"corners": [[x, y], ...],
|
| 34 |
+
"furnitures": [
|
| 35 |
+
{
|
| 36 |
+
"object": str,
|
| 37 |
+
"localisation": [ymin, xmin, ymax, xmax],
|
| 38 |
+
"description": str,
|
| 39 |
+
},
|
| 40 |
+
...
|
| 41 |
+
]
|
| 42 |
+
}
|
| 43 |
+
"""
|
| 44 |
+
|
| 45 |
+
EVENTS = ["change"]
|
| 46 |
+
|
| 47 |
+
def __init__(
|
| 48 |
+
self,
|
| 49 |
+
value: dict | None = None,
|
| 50 |
+
*,
|
| 51 |
+
label: str | None = None,
|
| 52 |
+
info: str | None = None,
|
| 53 |
+
every: "Timer | float | None" = None,
|
| 54 |
+
show_label: bool | None = None,
|
| 55 |
+
container: bool = True,
|
| 56 |
+
scale: int | None = None,
|
| 57 |
+
min_width: int = 160,
|
| 58 |
+
interactive: bool | None = None,
|
| 59 |
+
visible: bool = True,
|
| 60 |
+
elem_id: str | None = None,
|
| 61 |
+
elem_classes: list[str] | str | None = None,
|
| 62 |
+
render: bool = True,
|
| 63 |
+
):
|
| 64 |
+
super().__init__(
|
| 65 |
+
value=value,
|
| 66 |
+
label=label,
|
| 67 |
+
info=info,
|
| 68 |
+
every=every,
|
| 69 |
+
show_label=show_label,
|
| 70 |
+
container=container,
|
| 71 |
+
scale=scale,
|
| 72 |
+
min_width=min_width,
|
| 73 |
+
interactive=interactive,
|
| 74 |
+
visible=visible,
|
| 75 |
+
elem_id=elem_id,
|
| 76 |
+
elem_classes=elem_classes,
|
| 77 |
+
render=render,
|
| 78 |
+
)
|
| 79 |
+
|
| 80 |
+
def preprocess(self, payload: dict | None) -> dict | None:
|
| 81 |
+
"""Pass the value dict through to the Python function unchanged."""
|
| 82 |
+
return payload
|
| 83 |
+
|
| 84 |
+
def postprocess(self, value: dict | None) -> dict | None:
|
| 85 |
+
"""Pass the dict from Python through to the frontend unchanged."""
|
| 86 |
+
return value
|
| 87 |
+
|
| 88 |
+
def api_info(self) -> dict:
|
| 89 |
+
return {
|
| 90 |
+
"type": "object",
|
| 91 |
+
"properties": {
|
| 92 |
+
"corners": {
|
| 93 |
+
"type": "array",
|
| 94 |
+
"items": {
|
| 95 |
+
"type": "array",
|
| 96 |
+
"items": {"type": "integer"},
|
| 97 |
+
"minItems": 2,
|
| 98 |
+
"maxItems": 2,
|
| 99 |
+
},
|
| 100 |
+
},
|
| 101 |
+
"furnitures": {
|
| 102 |
+
"type": "array",
|
| 103 |
+
"items": {
|
| 104 |
+
"type": "object",
|
| 105 |
+
"properties": {
|
| 106 |
+
"object": {"type": "string"},
|
| 107 |
+
"localisation": {
|
| 108 |
+
"type": "array",
|
| 109 |
+
"items": {"type": "integer"},
|
| 110 |
+
"minItems": 4,
|
| 111 |
+
"maxItems": 4,
|
| 112 |
+
},
|
| 113 |
+
"description": {"type": "string"},
|
| 114 |
+
},
|
| 115 |
+
"required": ["object", "localisation", "description"],
|
| 116 |
+
},
|
| 117 |
+
},
|
| 118 |
+
},
|
| 119 |
+
"required": ["corners", "furnitures"],
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
def example_value(self) -> dict:
|
| 123 |
+
return copy.deepcopy(_DEFAULTS)
|
| 124 |
+
|
| 125 |
+
def example_payload(self) -> dict:
|
| 126 |
+
return copy.deepcopy(_DEFAULTS)
|
floorplan/backend/tests/__init__.py
ADDED
|
File without changes
|
floorplan/backend/tests/test_floorplan.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import copy
|
| 2 |
+
from gradio_floorplan import FloorPlan
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
SAMPLE_CORNERS = [[50, 50], [550, 50], [550, 450], [50, 450]]
|
| 6 |
+
SAMPLE_FURNITURES = [
|
| 7 |
+
{"object": "Sofa", "localisation": [150, 100, 250, 300], "description": "3-seat sofa"},
|
| 8 |
+
{"object": "Table", "localisation": [300, 200, 380, 400], "description": "Coffee table"},
|
| 9 |
+
]
|
| 10 |
+
SAMPLE_VALUE = {"corners": SAMPLE_CORNERS, "furnitures": SAMPLE_FURNITURES}
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def test_postprocess_returns_dict():
|
| 14 |
+
comp = FloorPlan()
|
| 15 |
+
result = comp.postprocess(SAMPLE_VALUE)
|
| 16 |
+
assert result is not None
|
| 17 |
+
assert result["corners"] == SAMPLE_CORNERS
|
| 18 |
+
assert len(result["furnitures"]) == 2
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def test_postprocess_none():
|
| 22 |
+
comp = FloorPlan()
|
| 23 |
+
assert comp.postprocess(None) is None
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def test_preprocess_passes_through_unchanged():
|
| 27 |
+
comp = FloorPlan()
|
| 28 |
+
payload = copy.deepcopy(SAMPLE_VALUE)
|
| 29 |
+
result = comp.preprocess(payload)
|
| 30 |
+
assert result == payload
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def test_preprocess_none():
|
| 34 |
+
comp = FloorPlan()
|
| 35 |
+
assert comp.preprocess(None) is None
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def test_example_value_shape():
|
| 39 |
+
comp = FloorPlan()
|
| 40 |
+
ex = comp.example_value()
|
| 41 |
+
assert "corners" in ex
|
| 42 |
+
assert "furnitures" in ex
|
| 43 |
+
assert len(ex["corners"]) >= 3
|
| 44 |
+
assert len(ex["furnitures"]) >= 1
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def test_example_value_returns_independent_copies():
|
| 48 |
+
comp = FloorPlan()
|
| 49 |
+
a = comp.example_value()
|
| 50 |
+
b = comp.example_value()
|
| 51 |
+
a["corners"].append([999, 999])
|
| 52 |
+
assert [999, 999] not in b["corners"], "example_value must return a deep copy"
|
floorplan/demo/__init__.py
ADDED
|
File without changes
|
floorplan/demo/app.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import gradio as gr
|
| 3 |
+
from gradio_floorplan import FloorPlan
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
example = FloorPlan().example_value()
|
| 7 |
+
|
| 8 |
+
demo = gr.Interface(
|
| 9 |
+
lambda x:x,
|
| 10 |
+
FloorPlan(), # interactive version of your component
|
| 11 |
+
FloorPlan(), # static version of your component
|
| 12 |
+
# examples=[[example]], # uncomment this line to view the "example version" of your component
|
| 13 |
+
)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
if __name__ == "__main__":
|
| 17 |
+
demo.launch()
|
floorplan/frontend/Example.svelte
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import { onMount } from "svelte";
|
| 3 |
+
|
| 4 |
+
export let value: string | null;
|
| 5 |
+
export let type: "gallery" | "table";
|
| 6 |
+
export let selected = false;
|
| 7 |
+
|
| 8 |
+
let size: number;
|
| 9 |
+
let el: HTMLDivElement;
|
| 10 |
+
|
| 11 |
+
function set_styles(element: HTMLElement, el_width: number): void {
|
| 12 |
+
element.style.setProperty(
|
| 13 |
+
"--local-text-width",
|
| 14 |
+
`${el_width && el_width < 150 ? el_width : 200}px`
|
| 15 |
+
);
|
| 16 |
+
element.style.whiteSpace = "unset";
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
function truncate_text(text: string | null, max_length = 60): string {
|
| 20 |
+
if (!text) return "";
|
| 21 |
+
const str = String(text);
|
| 22 |
+
if (str.length <= max_length) return str;
|
| 23 |
+
return str.slice(0, max_length) + "...";
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
onMount(() => {
|
| 27 |
+
set_styles(el, size);
|
| 28 |
+
});
|
| 29 |
+
</script>
|
| 30 |
+
|
| 31 |
+
<div
|
| 32 |
+
bind:clientWidth={size}
|
| 33 |
+
bind:this={el}
|
| 34 |
+
class:table={type === "table"}
|
| 35 |
+
class:gallery={type === "gallery"}
|
| 36 |
+
class:selected
|
| 37 |
+
>
|
| 38 |
+
{truncate_text(value)}
|
| 39 |
+
</div>
|
| 40 |
+
|
| 41 |
+
<style>
|
| 42 |
+
.gallery {
|
| 43 |
+
padding: var(--size-1) var(--size-2);
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
div {
|
| 47 |
+
overflow: hidden;
|
| 48 |
+
min-width: var(--local-text-width);
|
| 49 |
+
|
| 50 |
+
white-space: nowrap;
|
| 51 |
+
}
|
| 52 |
+
</style>
|
floorplan/frontend/Index.svelte
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<svelte:options accessors={true} />
|
| 2 |
+
|
| 3 |
+
<script lang="ts">
|
| 4 |
+
import type { SimpleTextboxProps, SimpleTextboxEvents } from "./types";
|
| 5 |
+
import { Gradio } from "@gradio/utils";
|
| 6 |
+
import { BlockTitle } from "@gradio/atoms";
|
| 7 |
+
import { Block } from "@gradio/atoms";
|
| 8 |
+
import { StatusTracker } from "@gradio/statustracker";
|
| 9 |
+
import { tick } from "svelte";
|
| 10 |
+
|
| 11 |
+
const props = $props();
|
| 12 |
+
const gradio = new Gradio<SimpleTextboxEvents, SimpleTextboxProps>(props);
|
| 13 |
+
|
| 14 |
+
let el: HTMLTextAreaElement | HTMLInputElement;
|
| 15 |
+
const container = true;
|
| 16 |
+
let old_value = $state(gradio.props.value);
|
| 17 |
+
|
| 18 |
+
async function handle_keypress(e: KeyboardEvent): Promise<void> {
|
| 19 |
+
await tick();
|
| 20 |
+
if (e.key === "Enter") {
|
| 21 |
+
e.preventDefault();
|
| 22 |
+
gradio.dispatch("submit");
|
| 23 |
+
}
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
$effect(() => {
|
| 27 |
+
if (old_value != gradio.props.value) {
|
| 28 |
+
old_value = gradio.props.value;
|
| 29 |
+
gradio.dispatch("change");
|
| 30 |
+
}
|
| 31 |
+
});
|
| 32 |
+
</script>
|
| 33 |
+
|
| 34 |
+
<Block
|
| 35 |
+
visible={gradio.shared.visible}
|
| 36 |
+
elem_id={gradio.shared.elem_id}
|
| 37 |
+
elem_classes={gradio.shared.elem_classes}
|
| 38 |
+
scale={gradio.shared.scale}
|
| 39 |
+
min_width={gradio.shared.min_width}
|
| 40 |
+
allow_overflow={false}
|
| 41 |
+
padding={true}
|
| 42 |
+
rtl={gradio.props.rtl}
|
| 43 |
+
>
|
| 44 |
+
{#if gradio.shared.loading_status}
|
| 45 |
+
<StatusTracker
|
| 46 |
+
autoscroll={gradio.shared.autoscroll}
|
| 47 |
+
i18n={gradio.i18n}
|
| 48 |
+
{...gradio.shared.loading_status}
|
| 49 |
+
on_clear_status={() =>
|
| 50 |
+
gradio.dispatch("clear_status", gradio.shared.loading_status)}
|
| 51 |
+
/>
|
| 52 |
+
{/if}
|
| 53 |
+
|
| 54 |
+
<label class:container>
|
| 55 |
+
<BlockTitle show_label={gradio.shared.show_label} info={undefined}
|
| 56 |
+
>{gradio.shared.label}</BlockTitle
|
| 57 |
+
>
|
| 58 |
+
|
| 59 |
+
<input
|
| 60 |
+
data-testid="textbox"
|
| 61 |
+
type="text"
|
| 62 |
+
class="scroll-hide"
|
| 63 |
+
bind:value={gradio.props.value}
|
| 64 |
+
bind:this={el}
|
| 65 |
+
placeholder={gradio.props.placeholder}
|
| 66 |
+
disabled={!gradio.shared.interactive}
|
| 67 |
+
dir={gradio.props.rtl ? "rtl" : "ltr"}
|
| 68 |
+
on:input={() => gradio.dispatch("input")}
|
| 69 |
+
on:keypress={handle_keypress}
|
| 70 |
+
/>
|
| 71 |
+
</label>
|
| 72 |
+
</Block>
|
| 73 |
+
|
| 74 |
+
<style>
|
| 75 |
+
label {
|
| 76 |
+
display: block;
|
| 77 |
+
width: 100%;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
input {
|
| 81 |
+
display: block;
|
| 82 |
+
position: relative;
|
| 83 |
+
outline: none !important;
|
| 84 |
+
box-shadow: var(--input-shadow);
|
| 85 |
+
background: var(--input-background-fill);
|
| 86 |
+
padding: var(--input-padding);
|
| 87 |
+
width: 100%;
|
| 88 |
+
color: var(--body-text-color);
|
| 89 |
+
font-weight: var(--input-text-weight);
|
| 90 |
+
font-size: var(--input-text-size);
|
| 91 |
+
line-height: var(--line-sm);
|
| 92 |
+
border: none;
|
| 93 |
+
}
|
| 94 |
+
.container > input {
|
| 95 |
+
border: var(--input-border-width) solid var(--input-border-color);
|
| 96 |
+
border-radius: var(--input-radius);
|
| 97 |
+
}
|
| 98 |
+
input:disabled {
|
| 99 |
+
-webkit-text-fill-color: var(--body-text-color);
|
| 100 |
+
-webkit-opacity: 1;
|
| 101 |
+
opacity: 1;
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
input:focus {
|
| 105 |
+
box-shadow: var(--input-shadow-focus);
|
| 106 |
+
border-color: var(--input-border-color-focus);
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
input::placeholder {
|
| 110 |
+
color: var(--input-placeholder-color);
|
| 111 |
+
}
|
| 112 |
+
</style>
|
floorplan/frontend/gradio.config.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export default {
|
| 2 |
+
plugins: [],
|
| 3 |
+
svelte: {
|
| 4 |
+
preprocess: [],
|
| 5 |
+
},
|
| 6 |
+
build: {
|
| 7 |
+
target: "modules",
|
| 8 |
+
},
|
| 9 |
+
};
|
floorplan/frontend/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "gradio_floorplan",
|
| 3 |
+
"version": "0.3.37",
|
| 4 |
+
"description": "Gradio UI packages",
|
| 5 |
+
"type": "module",
|
| 6 |
+
"author": "",
|
| 7 |
+
"license": "ISC",
|
| 8 |
+
"private": false,
|
| 9 |
+
"main_changeset": true,
|
| 10 |
+
"exports": {
|
| 11 |
+
".": {
|
| 12 |
+
"gradio": "./Index.svelte",
|
| 13 |
+
"svelte": "./dist/Index.svelte",
|
| 14 |
+
"types": "./dist/Index.svelte.d.ts"
|
| 15 |
+
},
|
| 16 |
+
"./example": {
|
| 17 |
+
"gradio": "./Example.svelte",
|
| 18 |
+
"svelte": "./dist/Example.svelte",
|
| 19 |
+
"types": "./dist/Example.svelte.d.ts"
|
| 20 |
+
},
|
| 21 |
+
"./package.json": "./package.json"
|
| 22 |
+
},
|
| 23 |
+
"dependencies": {
|
| 24 |
+
"@gradio/atoms": "0.22.2",
|
| 25 |
+
"@gradio/icons": "0.15.1",
|
| 26 |
+
"@gradio/statustracker": "0.12.5",
|
| 27 |
+
"@gradio/utils": "0.12.0",
|
| 28 |
+
"svelte": "^5.48.0"
|
| 29 |
+
},
|
| 30 |
+
"devDependencies": {
|
| 31 |
+
"@gradio/preview": "0.16.0"
|
| 32 |
+
},
|
| 33 |
+
"peerDependencies": {
|
| 34 |
+
"svelte": "^5.48.0"
|
| 35 |
+
},
|
| 36 |
+
"repository": {
|
| 37 |
+
"type": "git",
|
| 38 |
+
"url": "git+https://github.com/gradio-app/gradio.git",
|
| 39 |
+
"directory": "js/simpletextbox"
|
| 40 |
+
}
|
| 41 |
+
}
|
floorplan/frontend/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"compilerOptions": {
|
| 3 |
+
"allowJs": true,
|
| 4 |
+
"checkJs": true,
|
| 5 |
+
"esModuleInterop": true,
|
| 6 |
+
"forceConsistentCasingInFileNames": true,
|
| 7 |
+
"resolveJsonModule": true,
|
| 8 |
+
"skipLibCheck": true,
|
| 9 |
+
"sourceMap": true,
|
| 10 |
+
"strict": true,
|
| 11 |
+
"verbatimModuleSyntax": true
|
| 12 |
+
},
|
| 13 |
+
"exclude": ["node_modules", "dist", "./gradio.config.js"]
|
| 14 |
+
}
|
floorplan/frontend/types.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import type { LoadingStatus } from "@gradio/statustracker";
|
| 2 |
+
|
| 3 |
+
export interface SimpleTextboxProps {
|
| 4 |
+
value: string;
|
| 5 |
+
placeholder: string;
|
| 6 |
+
rtl: boolean;
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
export interface SimpleTextboxEvents {
|
| 10 |
+
change: never;
|
| 11 |
+
submit: never;
|
| 12 |
+
input: never;
|
| 13 |
+
clear_status: LoadingStatus;
|
| 14 |
+
}
|
floorplan/pyproject.toml
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[build-system]
|
| 2 |
+
requires = [
|
| 3 |
+
"hatchling",
|
| 4 |
+
"hatch-requirements-txt",
|
| 5 |
+
"hatch-fancy-pypi-readme>=22.5.0",
|
| 6 |
+
]
|
| 7 |
+
build-backend = "hatchling.build"
|
| 8 |
+
|
| 9 |
+
[project]
|
| 10 |
+
name = "gradio_floorplan"
|
| 11 |
+
version = "0.0.1"
|
| 12 |
+
description = "Python library for easily interacting with trained machine learning models"
|
| 13 |
+
readme = "README.md"
|
| 14 |
+
license = "Apache-2.0"
|
| 15 |
+
requires-python = ">=3.10"
|
| 16 |
+
authors = [{ name = "YOUR NAME", email = "YOUREMAIL@domain.com" }]
|
| 17 |
+
keywords = [
|
| 18 |
+
"gradio-custom-component",
|
| 19 |
+
"gradio-template-SimpleTextbox"
|
| 20 |
+
]
|
| 21 |
+
# Add dependencies here
|
| 22 |
+
dependencies = ["gradio>=6.0,<7.0"]
|
| 23 |
+
classifiers = [
|
| 24 |
+
'Development Status :: 3 - Alpha',
|
| 25 |
+
'Operating System :: OS Independent',
|
| 26 |
+
'Programming Language :: Python :: 3',
|
| 27 |
+
'Programming Language :: Python :: 3 :: Only',
|
| 28 |
+
'Programming Language :: Python :: 3.8',
|
| 29 |
+
'Programming Language :: Python :: 3.9',
|
| 30 |
+
'Programming Language :: Python :: 3.10',
|
| 31 |
+
'Programming Language :: Python :: 3.11',
|
| 32 |
+
'Topic :: Scientific/Engineering',
|
| 33 |
+
'Topic :: Scientific/Engineering :: Artificial Intelligence',
|
| 34 |
+
'Topic :: Scientific/Engineering :: Visualization',
|
| 35 |
+
]
|
| 36 |
+
|
| 37 |
+
# The repository and space URLs are optional, but recommended.
|
| 38 |
+
# Adding a repository URL will create a badge in the auto-generated README that links to the repository.
|
| 39 |
+
# Adding a space URL will create a badge in the auto-generated README that links to the space.
|
| 40 |
+
# This will make it easy for people to find your deployed demo or source code when they
|
| 41 |
+
# encounter your project in the wild.
|
| 42 |
+
|
| 43 |
+
# [project.urls]
|
| 44 |
+
# repository = "your github repository"
|
| 45 |
+
# space = "your space url"
|
| 46 |
+
|
| 47 |
+
[project.optional-dependencies]
|
| 48 |
+
dev = ["build", "twine"]
|
| 49 |
+
|
| 50 |
+
[tool.hatch.build]
|
| 51 |
+
artifacts = ["/backend/gradio_floorplan/templates", "*.pyi"]
|
| 52 |
+
|
| 53 |
+
[tool.hatch.build.targets.wheel]
|
| 54 |
+
packages = ["/backend/gradio_floorplan"]
|
| 55 |
+
|
| 56 |
+
[dependency-groups]
|
| 57 |
+
dev = [
|
| 58 |
+
"pytest>=9.0.2",
|
| 59 |
+
]
|
floorplan/uv.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|