more stuff

This commit is contained in:
pngwn 2022-03-11 16:00:48 +00:00
parent ec80912433
commit 50cb72b4ea
61 changed files with 498 additions and 121 deletions

View File

@ -1,6 +0,0 @@
{
"name": "gradio",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}

View File

@ -45,10 +45,9 @@
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js"></script>
<title>Gradio</title>
<script type="module" crossorigin src="/assets/index.75e4bf7f.js"></script>
<link rel="modulepreload" href="/assets/vendor.3cba5ef5.js">
<link rel="stylesheet" href="/assets/vendor.327fceeb.css">
<link rel="stylesheet" href="/assets/index.859c7146.css">
<script type="module" crossorigin src="/assets/index.2bae3baf.js"></script>
<link rel="modulepreload" href="/assets/vendor.d9166d01.js">
<link rel="stylesheet" href="/assets/index.3418770d.css">
</head>
<body style="height: 100%; margin: 0; padding: 0">

View File

@ -25,6 +25,7 @@
"@gradio/json": "workspace:^0.0.1",
"@gradio/label": "workspace:^0.0.1",
"@gradio/table": "workspace:^0.0.1",
"@gradio/tabs": "workspace:^0.0.1",
"@gradio/theme": "workspace:^0.0.1",
"@gradio/upload": "workspace:^0.0.1",
"@gradio/video": "workspace:^0.0.1",

View File

@ -3,6 +3,5 @@ module.exports = {
plugins: [
require("tailwindcss/nesting"),
require("tailwindcss"),
require("autoprefixer")
]
};

View File

@ -1,13 +1,110 @@
<script lang="ts">
import Pane from "./page_layouts/Pane.svelte";
import type { SvelteComponentTyped } from "svelte";
import { component_map } from "./components/directory";
import { _ } from "svelte-i18n";
import { setupi18n } from "./i18n";
import Render from "./Render.svelte";
import { tick } from "svelte";
setupi18n();
const json = {
mode: "blocks",
components: [
{
id: 1,
type: "markdown",
props: {
label:
"\n\t# Detect Disease From Scan\n\tWith this model you can lorem ipsum\n\t- ipsum 1\n\t- ipsum 2\n\t"
}
},
{
id: 2,
type: "checkboxgroup",
props: {
choices: ["Covid", "Malaria", "Lung Cancer"],
default: [],
label: "Disease to Scan For"
}
},
{ id: 3, type: "tabs" },
{ id: 4, type: "tabitem", props: { label: "X-ray" } },
{ id: 5, type: "row" },
{
id: 6,
type: "image",
props: {
image_mode: "RGB",
shape: null,
source: "upload",
tool: "editor",
optional: false,
label: null
}
},
{ id: 7, type: "json" },
{ id: 8, type: "button", props: { label: "Run" } },
{ id: 9, type: "tabitem", props: { label: "CT Scan" } },
{ id: 10, type: "row" },
{
id: 11,
type: "image",
props: {
image_mode: "RGB",
shape: null,
source: "upload",
tool: "editor",
optional: false,
label: null
}
},
{ id: 12, type: "json", props: { label: null } },
{ id: 13, type: "button", props: { label: "Run" } },
{ id: 14, type: "textbox", props: { label: null } }
],
theme: "default",
layout: {
children: [
{ id: 1 },
{ id: 2 },
{
id: 3,
children: [
{
id: 4,
children: [{ id: 5, children: [{ id: 6 }, { id: 7 }] }, { id: 8 }]
},
{
id: 9,
children: [
{ id: 10, children: [{ id: 11 }, { id: 12 }] },
{ id: 13 }
]
}
]
},
{ id: 14 }
],
type: "root"
},
dependencies: [
{ targets: [8], trigger: "click", inputs: [2, 6], outputs: [7] },
{ targets: [13], trigger: "click", inputs: [2, 11], outputs: [12] }
]
};
const dynamic_ids = json.dependencies.reduce((acc, next) => {
next.inputs.forEach((i) => acc.add(i));
return acc;
}, new Set());
interface Component {
name: string;
id: string;
props: Record<string, unknown>;
props: {
name: keyof typeof component_map;
[key: string]: unknown;
};
}
interface Layout {
@ -30,55 +127,176 @@
export let theme: string;
export let static_src: string;
$: console.log(components, layout, dependencies);
let values: Record<string, unknown> = {};
let component_id_map: Record<string, Component> = {};
let event_listener_map: Record<string, Array<number>> = {};
for (let component of components) {
component_id_map[component.id] = component;
if (component.props && "default" in component.props) {
values[component.id] = component.props.default;
} else {
values[component.id] = null;
}
event_listener_map[component.id] = [];
interface Instance {
props?: Record<string, unknown>;
id: number;
type: string;
instance?: SvelteComponentTyped;
value?: unknown;
}
dependencies.forEach((dependency, i) => {
if (dependency.trigger === "click") {
for (let target of dependency.targets) {
event_listener_map[target].push(i);
const instance_map = json.components.reduce((acc, next) => {
return {
...acc,
[next.id]: {
...next
}
};
}, {} as { [id: number]: Instance });
function load_component<T extends keyof typeof component_map>(
name: T
): Promise<{ name: T; component: SvelteComponentDev }> {
return new Promise(async (res, rej) => {
try {
const c = await component_map[name]();
res({ name, component: c });
} catch (e) {
rej(e);
}
});
}
async function walk_layout(node) {
const _n = { id: node.id };
const meta = instance_map[_n.id];
_n.props = meta.props || {};
const _module = (await _component_map.get(meta.type)).component;
_n.component = _module.Component;
if (_module.modes.length > 1) {
_n.has_modes = true;
}
// console.log(await _component_map.get(meta.type));
if (node.children) {
_n.children = await Promise.all(node.children.map((v) => walk_layout(v)));
}
return _n;
}
const component_set = new Set();
const _component_map = new Map();
json.components.forEach((c) => {
const _c = load_component(c.type);
component_set.add(_c);
_component_map.set(c.type, _c);
});
const setValues = (i: string, value: unknown) => {
values[i] = value;
};
const triggerTarget = (i: string) => {
event_listener_map[i].forEach((fn_index: number) => {
let dependency = dependencies[fn_index];
fn("predict", {
fn_index: fn_index,
data: dependency.inputs.map((i) => values[i])
}).then((output) => {
output["data"].forEach((value, i) => {
values[dependency.outputs[i]] = value;
let tree;
Promise.all(Array.from(component_set)).then((v) => {
Promise.all(json.layout.children.map((c) => walk_layout(c))).then((v) => {
// console.log(v);
tree = v;
});
});
// let values: Record<string, unknown> = {};
// let component_id_map: Record<string, Component> = {};
// let event_listener_map: Record<string, Array<number>> = {};
// for (let component of components) {
// component_id_map[component.id] = component;
// if (component.props && "default" in component.props) {
// values[component.id] = component.props.default;
// } else {
// values[component.id] = null;
// }
// event_listener_map[component.id] = [];
// }
// dependencies.forEach((dependency, i) => {
// if (dependency.trigger === "click") {
// for (let target of dependency.targets) {
// event_listener_map[target].push(i);
// }
// }
// });
// const setValues = (i: string, value: unknown) => {
// values[i] = value;
// };
// const triggerTarget = (i: string) => {
// event_listener_map[i].forEach((fn_index: number) => {
// let dependency = dependencies[fn_index];
// fn("predict", {
// fn_index: fn_index,
// data: dependency.inputs.map((i) => values[i])
// }).then((output) => {
// output["data"].forEach((value, i) => {
// values[dependency.outputs[i]] = value;
// });
// });
// });
// };
let handled_dependencies: Array<number[]> = [];
async function handle_mount({ detail }) {
console.log("mount", detail);
// console.log("boo");
await tick();
json.dependencies.forEach(({ targets, trigger, inputs, outputs }, i) => {
const target_instances: [number, Instance][] = targets.map((t) => [
t,
instance_map[t]
]);
target_instances.forEach(([id, { instance }]: [number, Instance]) => {
// console.log(id, handled_dependencies[i]?.includes(id) || !instance);
if (handled_dependencies[i]?.includes(id) || !instance) return;
// console.log(trigger, target_instances, instance);
instance?.$on(trigger, () => {
console.log("boo");
fn("predict", {
fn_index: i,
data: inputs.map((id) => instance_map[id].value)
}).then((output) => {
console.log(output);
output.data.forEach((value, i) => {
instance_map[outputs[i]].value = value;
});
});
});
if (!handled_dependencies[i]) handled_dependencies[i] = [];
handled_dependencies[i].push(id);
});
});
};
}
function handle_destroy(id: number) {
console.log("destroy", id);
// console.log(
// id,
// handled_dependencies,
// handled_dependencies.map((dep) => {
// return dep.filter((_id) => _id !== id);
// })
// );
handled_dependencies = handled_dependencies.map((dep) => {
return dep.filter((_id) => _id !== id);
});
}
$: console.log(handled_dependencies);
</script>
<div class="mx-auto container p-4">
<Pane
{component_id_map}
children={layout.children}
{dependencies}
{values}
{setValues}
{triggerTarget}
{theme}
{static_src}
/>
{#if tree}
{#each tree as { component, id, props, children, has_modes }}
<Render
{has_modes}
{dynamic_ids}
{component}
{id}
{props}
{children}
{instance_map}
theme={json.theme}
on:mount={handle_mount}
on:destroy={({ detail }) => handle_destroy(detail)}
/>
{/each}
{/if}
</div>

View File

@ -1,5 +1,5 @@
<script lang="ts">
import { input_component_map } from "./components/directory";
// import { input_component_map } from "./components/directory";
import { _ } from "svelte-i18n";
interface Component {
@ -19,6 +19,7 @@
let gallery = input_components.length === 1;
</script>
<!--
<div class="examples" {theme}>
<h4 class="text-lg font-semibold my-2">{$_("interface.examples")}</h4>
<div
@ -103,4 +104,4 @@
}
}
}
</style>
</style> -->

View File

@ -1,8 +1,4 @@
<script lang="ts">
import {
input_component_map,
output_component_map
} from "./components/directory";
import { deepCopy } from "./components/utils/helpers";
import ExampleSet from "./ExampleSet.svelte";
import { _ } from "svelte-i18n";

View File

@ -0,0 +1,51 @@
<script lang="ts">
import { onMount, createEventDispatcher } from "svelte";
export let component;
export let instance_map;
export let id: number;
export let props;
export let children;
export let theme;
export let dynamic_ids: Set<number>;
export let has_modes: boolean;
const dispatch = createEventDispatcher<{ mount: number; destroy: number }>();
if (has_modes && dynamic_ids.has(id)) {
props.mode = "dynamic";
} else if (has_modes) {
props.mode = "static";
}
onMount(() => {
dispatch("mount", id);
return () => dispatch("destroy", id);
});
</script>
<svelte:component
this={component}
bind:this={instance_map[id].instance}
bind:value={instance_map[id].value}
{...props}
{theme}
>
{#if children.length}
{#each children as { component, id, props, children, has_modes }}
<svelte:self
{component}
{id}
{props}
{theme}
{instance_map}
{children}
{dynamic_ids}
{has_modes}
on:destroy
on:mount
/>
{/each}
{/if}
</svelte:component>

View File

@ -2,14 +2,14 @@
import { Audio } from "@gradio/audio";
import type { FileData } from "@gradio/upload";
export let is_static: boolean;
export let value: null | FileData;
export let mode: "static" | "dynamic";
export let value: null | FileData = null;
export let theme: string;
export let name: string;
export let source: "microphone" | "upload";
</script>
{#if is_static}
{#if mode === "static"}
<Audio
{value}
{theme}

View File

@ -2,3 +2,4 @@ export { default as Component } from "./Audio.svelte";
export { default as ExampleComponent } from "./Example.svelte";
export { default as Interpretation } from "./Interpretation.svelte";
export { loadAsFile } from "../utils/example_processors";
export const modes = ["static", "dynamic"];

View File

@ -1 +1,2 @@
export { default as Component } from "./Button.svelte";
export const modes = ["static"];

View File

@ -1 +1,2 @@
export { default as Component } from "./Carousel.svelte";
export const modes = ["static"];

View File

@ -1 +1,2 @@
export { default as Component } from "./CarouselItem.svelte";
export const modes = ["static"];

View File

@ -1 +1,2 @@
export { default as Component } from "./Chatbot.svelte";
export const modes = ["static"];

View File

@ -1,7 +1,9 @@
<script lang="ts">
import { Checkbox } from "@gradio/form";
export let value: boolean;
export let value: boolean = false;
export let theme: string;
export let mode: "static" | "dynamic";
</script>
<Checkbox {theme} bind:value on:change />
<Checkbox {theme} bind:value on:change disabled={mode === "static"} />

View File

@ -1,3 +1,4 @@
export { default as Component } from "./Checkbox.svelte";
export { default as ExampleComponent } from "./Example.svelte";
export { default as Interpretation } from "./Interpretation.svelte";
export const modes = ["static", "dynamic"];

View File

@ -1,10 +1,17 @@
<script lang="ts">
import { CheckboxGroup } from "@gradio/form";
export let value: Array<string>;
export let value: Array<string> = [];
export let choices: Array<string>;
export let mode: "static" | "dynamic";
export let theme: string;
</script>
<CheckboxGroup bind:value {choices} {theme} on:change />
<CheckboxGroup
bind:value
{choices}
{theme}
on:change
disabled={mode === "static"}
/>

View File

@ -1,3 +1,4 @@
export { default as Component } from "./CheckboxGroup.svelte";
export { default as ExampleComponent } from "./Example.svelte";
export { default as Interpretation } from "./Interpretation.svelte";
export const modes = ["static", "dynamic"];

View File

@ -1 +1,2 @@
export { default as Component } from "./DataFrame.svelte";
export const modes = ["static"];

View File

@ -1,7 +1,7 @@
<script lang="ts">
import { Dropdown } from "@gradio/form";
export let label: string = "";
export let value: string;
export let value: string = "";
export let theme: string;
export let choices: Array<string>;
</script>

View File

@ -1,3 +1,4 @@
export { default as Component } from "./Dropdown.svelte";
export { default as ExampleComponent } from "./Example.svelte";
export { default as Interpretation } from "./Interpretation.svelte";
export const modes = ["dynamic"];

View File

@ -2,12 +2,12 @@
import { File, FileUpload } from "@gradio/file";
import type { FileData } from "@gradio/upload";
export let value: null | FileData;
export let value: null | FileData = null;
export let theme: string;
export let is_static: boolean;
export let mode: "static" | "dynamic";
</script>
{#if is_static}
{#if mode === "static"}
<FileUpload bind:value {theme} on:change />
{:else if value}
<File {value} {theme} />

View File

@ -1,3 +1,4 @@
export { default as Component } from "./File.svelte";
export { default as ExampleComponent } from "./Example.svelte";
export { loadAsFile } from "../utils/example_processors";
export const modes = ["static", "dynamic"];

View File

@ -1,7 +1,7 @@
<script lang="ts">
import { HTML } from "@gradio/html";
export let value: string;
export let label: string;
export let theme: string;
</script>
<HTML {value} {theme} />
<HTML value={label} {theme} />

View File

@ -1 +1,2 @@
export { default as Component } from "./HTML.svelte";
export const modes = ["static"];

View File

@ -1 +1,2 @@
export { default as Component } from "./HighlightedText.svelte";
export const modes = ["static"];

View File

@ -1,15 +1,15 @@
<script lang="ts">
import { Image } from "@gradio/image";
export let value: null | string;
export let value: null | string = null;
export let theme: string;
export let source: "canvas" | "webcam" | "upload" = "upload";
export let tool: "editor" | "select" = "editor";
export let is_static: boolean;
export let mode: "static" | "dynamic";
</script>
{#if is_static}
{#if mode === "static"}
<div
class="output-image w-full h-60 flex justify-center items-center bg-gray-200 dark:bg-gray-600 relative"
{theme}

View File

@ -2,3 +2,4 @@ export { default as Component } from "./Image.svelte";
export { default as ExampleComponent } from "./Example.svelte";
export { default as Interpretation } from "./Interpretation.svelte";
export { loadAsData } from "../utils/example_processors";
export const modes = ["static", "dynamic"];

View File

@ -1 +1,2 @@
export { default as Component } from "./Json.svelte";
export const modes = ["static"];

View File

@ -1 +1,2 @@
export { default as Component } from "./Label.svelte";
export const modes = ["static"];

View File

@ -1,7 +1,8 @@
<script lang="ts">
import { Number } from "@gradio/form";
export let value: number;
export let value: number = 0;
export let theme: string;
export let mode: "static" | "dynamic";
</script>
<Number bind:value {theme} on:change />
<Number bind:value {theme} on:change disabled={mode === "static"} />

View File

@ -1,3 +1,4 @@
export { default as Component } from "./Number.svelte";
export { default as ExampleComponent } from "./Example.svelte";
export { default as Interpretation } from "./Interpretation.svelte";
export const modes = ["static", "dynamic"];

View File

@ -1,9 +1,10 @@
<script lang="ts">
import { Radio } from "@gradio/form";
export let value: string;
export let value: string = "";
export let theme: string;
export let choices: Array<string>;
export let choices: Array<string> = [];
export let mode: "static" | "dynamic";
</script>
<Radio bind:value {theme} {choices} on:change />
<Radio bind:value {theme} {choices} disabled={mode === "static"} on:change />

View File

@ -1,3 +1,4 @@
export { default as Component } from "./Radio.svelte";
export { default as ExampleComponent } from "./Example.svelte";
export { default as Interpretation } from "./Interpretation.svelte";
export const modes = ["static", "dynamic"];

View File

@ -0,0 +1,3 @@
<div class="flex flex-row">
<slot />
</div>

View File

@ -0,0 +1,2 @@
export { default as Component } from "./Row.svelte";
export const modes = ["static"];

View File

@ -1,11 +1,20 @@
<script lang="ts">
import { Range } from "@gradio/form";
export let value: number;
export let value: number = 0;
export let theme: string;
export let minimum: number;
export let maximum: number;
export let step: number;
export let mode: "static" | "dynamic";
</script>
<Range bind:value {theme} {minimum} {maximum} {step} on:change />
<Range
bind:value
{theme}
{minimum}
{maximum}
{step}
disabled={mode === "static"}
on:change
/>

View File

@ -1,3 +1,4 @@
export { default as Component } from "./Slider.svelte";
export { default as ExampleComponent } from "./Example.svelte";
export { default as Interpretation } from "./Interpretation.svelte";
export const modes = ["static", "dynamic"];

View File

@ -0,0 +1,9 @@
<script lang="ts">
import { TabItem } from "@gradio/tabs";
export let label: string;
</script>
<TabItem name={label}>
<slot />
</TabItem>

View File

@ -0,0 +1,2 @@
export { default as Component } from "./Tabs.svelte";
export const modes = ["static"];

View File

@ -0,0 +1,7 @@
<script lang="ts">
import { Tabs } from "@gradio/tabs";
</script>
<Tabs on:change>
<slot />
</Tabs>

View File

@ -0,0 +1,2 @@
export { default as Component } from "./Tabs.svelte";
export const modes = ["static"];

View File

@ -1,15 +1,15 @@
<script lang="ts">
import { TextBox } from "@gradio/form";
export let value: string;
export let value: string = " ";
export let theme: string;
export let lines: number;
export let placeholder: string;
export let is_static: boolean;
export let mode: "static" | "dynamic";
</script>
{#if is_static}
{#if mode === "static"}
<div
class="output-text w-full bg-white dark:bg-gray-800 rounded box-border p-2 whitespace-pre-wrap"
{theme}

View File

@ -1,2 +1,3 @@
export { default as Component } from "./Textbox.svelte";
export { default as ExampleComponent } from "./Example.svelte";
export const modes = ["static", "dynamic"];

View File

@ -1 +1,2 @@
export { default as Component } from "./TimeSeries.svelte";
export const modes = ["static"];

View File

@ -1,5 +1,5 @@
<script lang="ts">
import { playable } from "../../utils/helpers";
import { playable } from "../utils/helpers";
export let value: string;
export let examples_dir: string;

View File

@ -5,14 +5,14 @@
import { Video } from "@gradio/video";
import { _ } from "svelte-i18n";
export let value: FileData;
export let value: FileData | null = null;
export let theme: string;
export let source: string;
export let is_static: boolean;
export let mode: "static" | "dynamic";
</script>
{#if is_static}
{#if mode === "static" && value}
<div
class="output-video w-full h-60 flex justify-center items-center bg-gray-200 dark:bg-gray-600 relative"
>

View File

@ -1,3 +1,4 @@
export { default as Component } from "./Video.svelte";
export { default as ExampleComponent } from "./Example.svelte";
export { loadAsFile } from "../utils/example_processors";
export const modes = ["static", "dynamic"];

View File

@ -15,8 +15,12 @@ export const component_map = {
json: () => import("./Json"),
label: () => import("./Label"),
number: () => import("./Number"),
markdown: () => import("./HTML"),
radio: () => import("./Radio"),
row: () => import("./Row"),
slider: () => import("./Slider"),
tabs: () => import("./Tabs"),
tabitem: () => import("./TabItem"),
textbox: () => import("./Textbox"),
timeseries: () => import("./TimeSeries"),
video: () => import("./Video")

View File

@ -1,6 +1,6 @@
<script>
import TabSet from "./TabSet.svelte";
import { all_components_map } from "../components/directory";
// import { all_components_map } from "../components/directory";
export let component_id_map,
children,
@ -11,11 +11,10 @@
triggerTarget,
theme,
static_src;
</script>
<div class="flex gap-4" class:flex-col={type !== "row"}>
{#each children as child}
<!-- {#each children as child}
{#if typeof child === "object"}
{#if child.type === "tabset"}
<TabSet
@ -52,5 +51,5 @@
/>
</div>
{/if}
{/each}
{/each} -->
</div>

View File

@ -5,7 +5,6 @@ import sveltePreprocess from "svelte-preprocess";
// this is dupe config, gonna try fix this
import tailwind from "tailwindcss";
import nested from "tailwindcss/nesting";
import autoprefix from "autoprefixer";
export default defineConfig(({ mode }) => {
const production = mode === "production";
@ -23,7 +22,7 @@ export default defineConfig(({ mode }) => {
plugins: [
svelte({
preprocess: sveltePreprocess({
postcss: { plugins: [tailwind, nested, autoprefix] }
postcss: { plugins: [tailwind, nested] }
})
})
]

View File

@ -12,5 +12,10 @@
"d3-dsv": "^3.0.1",
"d3-scale": "^4.0.2",
"d3-shape": "^3.1.0"
},
"devDependencies": {
"@types/d3-dsv": "^3.0.0",
"@types/d3-scale": "^4.0.2",
"@types/d3-shape": "^3.0.2"
}
}

View File

@ -1,6 +1,8 @@
<script lang="ts">
import { createEventDispatcher } from "svelte";
export let value: boolean;
export let disabled: boolean = false;
export let theme: string = "default";
const dispatch = createEventDispatcher<{ change: boolean }>();

View File

@ -1,9 +1,10 @@
<script lang="ts">
import { createEventDispatcher } from "svelte";
export let value: Array<string>;
export let choices: Array<string>;
export let value: Array<string> = [];
export let choices: Array<string>;
export let theme: string = "default";
export let disabled: boolean = false;
const dispatch = createEventDispatcher<{ change: Array<string> }>();

View File

@ -4,6 +4,7 @@
export let value: number = 0;
export let theme: string = "default";
export let disabled: boolean = false;
const dispatch = createEventDispatcher<{ change: number }>();

View File

@ -4,6 +4,7 @@
export let value: string;
export let theme: string = "default";
export let choices: Array<string>;
export let disabled: boolean = false;
const dispatch = createEventDispatcher();

View File

@ -5,6 +5,7 @@
export let minimum: number;
export let maximum: number;
export let step: number;
export let disabled: boolean = false;
const dispatch = createEventDispatcher<{ change: number }>();

View File

@ -39,7 +39,7 @@
$: dispatch("change", value);
</script>
<div class="input-image">
<div class="input-image w-full">
<div
class="image-preview w-full h-60 flex justify-center items-center dark:bg-gray-600 relative"
class:bg-gray-200={value}

View File

@ -1,11 +1,11 @@
<script lang="ts">
import JSONNode from "./JSONNode.svelte";
export let value: any;
export let value: any = {};
export let theme: string = "default";
</script>
<div class="output-json font-mono leading-relaxed" {theme}>
<div class="output-json font-mono leading-relaxed w-full" {theme}>
<JSONNode {value} depth={0} {theme} />
</div>

View File

@ -3,7 +3,7 @@
</script>
<script lang="ts">
import { setContext } from "svelte";
import { setContext, createEventDispatcher } from "svelte";
import { writable } from "svelte/store";
interface Tab {
@ -14,6 +14,7 @@
const tabs: Array<Tab> = [];
const selected_tab = writable<false | object>(false);
const dispatch = createEventDispatcher<{ change: undefined }>();
setContext(TABS, {
register_tab: (tab: Tab) => {
@ -30,9 +31,14 @@
selected_tab
});
function handle_click(id: object) {
$selected_tab = id;
dispatch("change");
}
</script>
<div class="flex flex-col">
<div class="flex flex-col my-4">
<div class="flex">
{#each tabs as t, i}
{#if t.id === $selected_tab}
@ -44,9 +50,7 @@
{:else}
<button
class="px-4 py-2 border-b-2 border-gray-200"
on:click={() => {
$selected_tab = t.id;
}}
on:click={() => handle_click(t.id)}
>
{t.name}
</button>

View File

@ -43,6 +43,7 @@ importers:
'@gradio/json': workspace:^0.0.1
'@gradio/label': workspace:^0.0.1
'@gradio/table': workspace:^0.0.1
'@gradio/tabs': workspace:^0.0.1
'@gradio/theme': workspace:^0.0.1
'@gradio/upload': workspace:^0.0.1
'@gradio/video': workspace:^0.0.1
@ -65,6 +66,7 @@ importers:
'@gradio/json': link:../json
'@gradio/label': link:../label
'@gradio/table': link:../table
'@gradio/tabs': link:../tabs
'@gradio/theme': link:../theme
'@gradio/upload': link:../upload
'@gradio/video': link:../video
@ -92,6 +94,9 @@ importers:
packages/chart:
specifiers:
'@gradio/tooltip': workspace:^0.0.1
'@types/d3-dsv': ^3.0.0
'@types/d3-scale': ^4.0.2
'@types/d3-shape': ^3.0.2
d3-dsv: ^3.0.1
d3-scale: ^4.0.2
d3-shape: ^3.1.0
@ -100,6 +105,10 @@ importers:
d3-dsv: 3.0.1
d3-scale: 4.0.2
d3-shape: 3.1.0
devDependencies:
'@types/d3-dsv': 3.0.0
'@types/d3-scale': 4.0.2
'@types/d3-shape': 3.0.2
packages/chatbot:
specifiers: {}
@ -172,6 +181,7 @@ importers:
'@gradio/json': workspace:^0.0.1
'@gradio/label': workspace:^0.0.1
'@gradio/table': workspace:^0.0.1
'@gradio/tabs': workspace:^0.0.1
'@gradio/theme': workspace:^0.0.1
'@gradio/upload': workspace:^0.0.1
'@gradio/video': workspace:^0.0.1
@ -200,12 +210,13 @@ importers:
'@gradio/json': link:../json
'@gradio/label': link:../label
'@gradio/table': link:../table
'@gradio/tabs': link:../tabs
'@gradio/theme': link:../theme
'@gradio/upload': link:../upload
'@gradio/video': link:../video
devDependencies:
'@sveltejs/adapter-auto': 1.0.0-next.30
'@sveltejs/kit': 1.0.0-next.291_svelte@3.46.3
'@sveltejs/adapter-auto': 1.0.0-next.31
'@sveltejs/kit': 1.0.0-next.294_svelte@3.46.3
autoprefixer: 10.4.2_postcss@8.4.6
postcss: 8.4.6
postcss-load-config: 3.1.1
@ -319,36 +330,36 @@ packages:
picomatch: 2.3.1
dev: true
/@sveltejs/adapter-auto/1.0.0-next.30:
resolution: {integrity: sha512-kKKDvv2bwH66l/A97u26973OG3Zh7V1WlTKgkOr95Koo1/Y6rBhBfkz0Jw+WLzsZ+hcTzgIrcegtWVt+GQRJpw==}
/@sveltejs/adapter-auto/1.0.0-next.31:
resolution: {integrity: sha512-N1ZFGxulcSAOJrtdFR567diwbWKUvLrHZiUE9TiEvIahnndeRa50MF9LDg/CuIvpa6fHqz5K827XXrADlPAr9g==}
dependencies:
'@sveltejs/adapter-cloudflare': 1.0.0-next.14
'@sveltejs/adapter-netlify': 1.0.0-next.49
'@sveltejs/adapter-vercel': 1.0.0-next.45
'@sveltejs/adapter-cloudflare': 1.0.0-next.15
'@sveltejs/adapter-netlify': 1.0.0-next.50
'@sveltejs/adapter-vercel': 1.0.0-next.46
dev: true
/@sveltejs/adapter-cloudflare/1.0.0-next.14:
resolution: {integrity: sha512-vD0+LdVIZO5/758KZuWzM58JIAeY+r/YKgoRkMjP9IUx+w+MJ869EyzOT81u/xN7x6cX2Ilu+/M60BwjqSDA7g==}
/@sveltejs/adapter-cloudflare/1.0.0-next.15:
resolution: {integrity: sha512-kq3vNFpKmRVgAOfz4HrcleBnUADs++dfVF8S61EAFqNTEvGtOVdJKLql66Pe/uxlY0VxAp1dplxtEDf4/R70lQ==}
dependencies:
esbuild: 0.14.23
dev: true
/@sveltejs/adapter-netlify/1.0.0-next.49:
resolution: {integrity: sha512-EYP0/eK1foC90fBNn6V9fP0ngrMF3MrkaNN+wCnMj0rHGKOKUzXlIeyPtGtQnDL9cqHac39pbPhSyMaMuWZF/w==}
/@sveltejs/adapter-netlify/1.0.0-next.50:
resolution: {integrity: sha512-lpHvjcHiC77SPyLp7OjhenJF9KYfKsXlmUua7icNh0Hc8SKtRQf0dn+a1Zy77AslikvOX7/4HZE8zPIyIvYYqw==}
dependencies:
'@iarna/toml': 2.2.5
esbuild: 0.14.23
tiny-glob: 0.2.9
dev: true
/@sveltejs/adapter-vercel/1.0.0-next.45:
resolution: {integrity: sha512-WoOMu4FSWjVeRiPq2NKfdZhobfOLmDykObZmm8JHptMDb0/I5SB+6wstzAeaNtQr2ZbQkUy0k7EX95riJifEEQ==}
/@sveltejs/adapter-vercel/1.0.0-next.46:
resolution: {integrity: sha512-6Rwf3kZF6uX2JxDMoYgZWZe5TjVTTWZa57VukdNGjnlAT3CrfsEOBWyskX/8hx7AiYX5fucZaAtYPNZpUmueIA==}
dependencies:
esbuild: 0.14.23
dev: true
/@sveltejs/kit/1.0.0-next.291_svelte@3.46.3:
resolution: {integrity: sha512-mFd1EJbxoyPGiomYwYhZnjNLPYahCC2gHfKvPetguL/7BCHcyUjjYQbwTTmjVxtgBs0oLzKVA9bt45gpr9JqBQ==}
/@sveltejs/kit/1.0.0-next.294_svelte@3.46.3:
resolution: {integrity: sha512-whTYeri/oaV672KErlhCAvAawlsnd8iu/MQmjdu85TApDYolLe8FDTg6GQ55+0IJbx1N7dOer/HopWzKudPgFA==}
engines: {node: '>=14.13'}
hasBin: true
peerDependencies:
@ -420,6 +431,30 @@ packages:
resolution: {integrity: sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==}
dev: false
/@types/d3-dsv/3.0.0:
resolution: {integrity: sha512-o0/7RlMl9p5n6FQDptuJVMxDf/7EDEv2SYEO/CwdG2tr1hTfUVi0Iavkk2ax+VpaQ/1jVhpnj5rq1nj8vwhn2A==}
dev: true
/@types/d3-path/3.0.0:
resolution: {integrity: sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==}
dev: true
/@types/d3-scale/4.0.2:
resolution: {integrity: sha512-Yk4htunhPAwN0XGlIwArRomOjdoBFXC3+kCxK2Ubg7I9shQlVSJy/pG/Ht5ASN+gdMIalpk8TJ5xV74jFsetLA==}
dependencies:
'@types/d3-time': 3.0.0
dev: true
/@types/d3-shape/3.0.2:
resolution: {integrity: sha512-5+ButCmIfNX8id5seZ7jKj3igdcxx+S9IDBiT35fQGTLZUfkFgTv+oBH34xgeoWDKpWcMITSzBILWQtBoN5Piw==}
dependencies:
'@types/d3-path': 3.0.0
dev: true
/@types/d3-time/3.0.0:
resolution: {integrity: sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==}
dev: true
/@types/node/17.0.14:
resolution: {integrity: sha512-SbjLmERksKOGzWzPNuW7fJM7fk3YXVTFiZWB/Hs99gwhk+/dnrQRPBQjPW9aO+fi1tAffi9PrwFvsmOKmDTyng==}