-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cbcd3c3
commit 8cb0613
Showing
8 changed files
with
365 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,6 @@ | ||
<script lang="ts"> | ||
import { color } from "../ui"; | ||
import PrimaryButton from "./PrimaryButton.svelte"; | ||
export let disabled: boolean = false; | ||
const text = color.ui.white; | ||
const solid = color.motion.primary; | ||
</script> | ||
|
||
<style> | ||
button:disabled { | ||
background: var(--drop-highlight); | ||
border: var(--drop-highlight); | ||
} | ||
button { | ||
padding: 0.75rem 1rem; | ||
border-radius: 0.25rem; | ||
border-width: 1px; | ||
border-style: solid; | ||
font-weight: 600; | ||
font-size: 0.85rem; | ||
transition: background-color 0.25s, border-color 0.25s; | ||
} | ||
</style> | ||
|
||
<button on:click {disabled} style:border-color={solid} style:background-color={solid} style:color={text} data-testid="ok"> | ||
OK | ||
</button> | ||
<PrimaryButton on:click {disabled} dataTestID={"ok"}>Ok</PrimaryButton> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<script lang="ts"> | ||
import { color } from "../ui"; | ||
export let disabled: boolean = false; | ||
export let dataTestID: string = null; | ||
export let paddingVertical: string = "0.75rem"; | ||
export let paddingHorizontal: string = "1rem"; | ||
export let borderRadius: string = "0.25rem"; | ||
const text = color.ui.white; | ||
const solid = color.motion.primary; | ||
</script> | ||
|
||
<button | ||
on:click | ||
on:mousedown | ||
on:mouseup | ||
{disabled} | ||
style:border-color={solid} | ||
style:background-color={solid} | ||
style:color={text} | ||
data-testid={dataTestID} | ||
style:padding={`${paddingVertical} ${paddingHorizontal}`} | ||
style:border-radius={borderRadius} | ||
> | ||
<slot /> | ||
</button> | ||
|
||
<style> | ||
button:disabled { | ||
background: var(--drop-highlight) !important; | ||
border: var(--drop-highlight) !important; | ||
} | ||
button { | ||
border-width: 1px; | ||
border-style: solid; | ||
font-weight: 600; | ||
font-size: 0.85rem; | ||
transition: background-color 0.25s, border-color 0.25s; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
<script lang="ts"> | ||
export let size: number = 12; | ||
export let fill: string = "#f44"; | ||
export let stroke: string = "#fff"; | ||
export let strokeWidth: number = 1; | ||
const dimension = size / 2; | ||
const half = dimension / 2; | ||
const quarter = dimension / 4; | ||
const threeQuarters = (dimension * 3) / 4; | ||
</script> | ||
|
||
<!-- svelte-ignore a11y-click-events-have-key-events --> | ||
<div style:width="{size}px" style:height="{size}px"> | ||
<svg | ||
style:top="{-dimension}px" | ||
style:right="{-dimension}px" | ||
style:width="{size}px" | ||
style:height="{size}px" | ||
viewBox="0 0 {dimension} {dimension}" | ||
style:fill | ||
on:click | ||
> | ||
<circle cx={half} cy={half} r={half} /> | ||
<line | ||
style:stroke | ||
x1={quarter} | ||
y1={quarter} | ||
x2={threeQuarters} | ||
y2={threeQuarters} | ||
style:stroke-width={strokeWidth} | ||
/> | ||
<line | ||
style:stroke | ||
x1={threeQuarters} | ||
y1={quarter} | ||
x2={quarter} | ||
y2={threeQuarters} | ||
style:stroke-width={strokeWidth} | ||
/> | ||
</svg> | ||
</div> | ||
|
||
<style> | ||
div { | ||
position: relative; | ||
} | ||
svg { | ||
position: absolute; | ||
cursor: pointer; | ||
transition: transform 0.3s; | ||
} | ||
svg:hover { | ||
transform: scale(1.2); | ||
} | ||
line { | ||
stroke-linecap: round; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,76 @@ | ||
<script lang="ts"> | ||
import type Extension from "."; | ||
import { ReactiveInvoke, reactiveInvoke } from "$common"; | ||
import { ReactiveInvoke, color, reactiveInvoke } from "$common"; | ||
import Class from "./components/Class.svelte"; | ||
import PrimaryButton from "$common/components/PrimaryButton.svelte"; | ||
export let extension: Extension; | ||
export let close: () => void; | ||
const invoke: ReactiveInvoke<Extension> = (functionName, ...args) => | ||
reactiveInvoke((extension = extension), functionName, args); | ||
let activeIndex = 0; | ||
const getNextLabel = () => { | ||
let label: string; | ||
let count = extension.labels.length + 1; | ||
do { | ||
label = `Class ${count++}`; | ||
} while (extension.labels.includes(label)); | ||
return label; | ||
}; | ||
const add = () => { | ||
invoke("addLabel", getNextLabel()); | ||
activeIndex = extension.labels.length - 1; | ||
}; | ||
const drop = () => { | ||
invoke("deleteLabel", extension.labels[activeIndex], activeIndex); | ||
activeIndex = -1; | ||
}; | ||
</script> | ||
|
||
{#each extension.labels as label, index} | ||
<Class | ||
{label} | ||
setActive={() => (activeIndex = index)} | ||
isActive={activeIndex === index} | ||
examples={extension.modelData.get(label)} | ||
/> | ||
{/each} | ||
|
||
<button | ||
on:click={() => invoke("addLabel", `Class ${extension.labels.length + 1}`)} | ||
> | ||
Add Label</button | ||
> | ||
<button>Clear all</button> | ||
<div class="container"> | ||
<div class="pane" style:background-color={color.ui.secondary}> | ||
{#each extension.labels as label, index} | ||
{@const examples = extension.modelData.get(label)} | ||
{#if examples} | ||
<Class | ||
{label} | ||
{examples} | ||
setActive={() => (activeIndex = index)} | ||
isActive={activeIndex === index} | ||
deactivate={() => (activeIndex = -1)} | ||
deleteSelf={drop} | ||
rename={(newLabel) => invoke("renameLabel", label, newLabel, index)} | ||
/> | ||
{/if} | ||
{/each} | ||
</div> | ||
<div class="footer"> | ||
<PrimaryButton on:click={add}>Add a Label</PrimaryButton> | ||
<PrimaryButton on:click={() => invoke("clearLabels")} | ||
>Clear All | ||
</PrimaryButton> | ||
<PrimaryButton on:click={close}>Done</PrimaryButton> | ||
</div> | ||
</div> | ||
|
||
<style> | ||
.container { | ||
text-align: center; | ||
padding: 30px; | ||
width: 600px; | ||
background-color: white; | ||
} | ||
.pane { | ||
height: 300px; | ||
text-align: left; | ||
overflow-y: scroll; | ||
} | ||
.footer { | ||
padding: 1rem 0; | ||
} | ||
</style> |
158 changes: 149 additions & 9 deletions
158
extensions/src/textClassification/components/Class.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,157 @@ | ||
<script lang="ts"> | ||
import PrimaryButton from "$common/components/PrimaryButton.svelte"; | ||
import Example from "./Example.svelte"; | ||
export let isActive: boolean; | ||
export let label: string; | ||
export let examples: string[]; | ||
export let setActive: () => void; | ||
export let deactivate: () => void; | ||
export let deleteSelf: () => void; | ||
export let rename: (newLabel: string) => void; | ||
const paddingVertical = "0.3rem"; | ||
const paddingHorizontal = "0.5rem"; | ||
let input: HTMLInputElement; | ||
const set = () => (label !== input?.value ? rename(input.value) : void 0); | ||
let candidate: string = ""; | ||
$: valid = candidate !== "" && !examples.includes(candidate); | ||
const addCandidate = () => { | ||
examples.push(candidate); | ||
examples = examples; | ||
candidate = ""; | ||
}; | ||
const deleteExample = (index: number) => { | ||
examples.splice(index, 1); | ||
examples = examples; | ||
}; | ||
const onEnter = | ||
(...callbacks: (() => void)[]) => | ||
(event: KeyboardEvent) => { | ||
if (event.key !== "Enter") return; | ||
event.preventDefault(); | ||
callbacks.forEach((callback) => callback()); | ||
}; | ||
</script> | ||
|
||
{#if isActive} | ||
<span>{label}</span> | ||
<span>({examples.length} example{examples.length === 1 ? "s" : ""})</span> | ||
<button on:click={setActive}>Edit Label</button> | ||
{:else} | ||
{#each examples as example} | ||
<div>{example}</div> | ||
{/each} | ||
{/if} | ||
<div class="row"> | ||
{#if isActive} | ||
<div> | ||
<input | ||
type="text" | ||
value={label} | ||
bind:this={input} | ||
id="label" | ||
name="label" | ||
on:blur={set} | ||
on:keypress={onEnter(set, deactivate)} | ||
/> | ||
<span> | ||
({examples.length} example{examples.length !== 1 ? "s" : ""}) | ||
</span> | ||
|
||
<PrimaryButton | ||
{paddingVertical} | ||
{paddingHorizontal} | ||
on:click={deactivate} | ||
> | ||
Done Editing | ||
</PrimaryButton> | ||
|
||
<PrimaryButton | ||
{paddingVertical} | ||
{paddingHorizontal} | ||
on:click={deleteSelf} | ||
> | ||
Delete Label | ||
</PrimaryButton> | ||
</div> | ||
<div class="examples"> | ||
{#each examples as example, index} | ||
<Example text={example} xOut={() => deleteExample(index)} /> | ||
{/each} | ||
</div> | ||
<center> | ||
<div style:margin-top="1rem"> | ||
<input | ||
bind:value={candidate} | ||
on:keypress={onEnter(() => | ||
valid ? addCandidate() : void 0 | ||
)} | ||
/> | ||
<PrimaryButton | ||
{paddingVertical} | ||
{paddingHorizontal} | ||
disabled={!valid} | ||
on:click={addCandidate} | ||
> | ||
Add Example | ||
</PrimaryButton> | ||
</div> | ||
</center> | ||
{:else} | ||
<div> | ||
<span>{label}</span> | ||
<span> | ||
({examples.length} example{examples.length !== 1 ? "s" : ""}) | ||
</span> | ||
<PrimaryButton | ||
{paddingVertical} | ||
{paddingHorizontal} | ||
on:click={setActive} | ||
> | ||
Edit Label | ||
</PrimaryButton> | ||
</div> | ||
<div class="examples"> | ||
{#each examples as example} | ||
<Example text={example} /> | ||
{/each} | ||
</div> | ||
{/if} | ||
</div> | ||
|
||
<style> | ||
.row { | ||
margin: 0.5rem 0.5rem; | ||
border-radius: 0.25rem; | ||
background-color: white; | ||
padding: 0.5rem; | ||
} | ||
input { | ||
height: 1.3rem; | ||
padding: 0 0.75rem; | ||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||
font-size: 0.875rem; | ||
font-weight: bold; | ||
color: hsla(225, 15%, 40%, 1); | ||
border-width: 1px; | ||
border-style: solid; | ||
border-color: hsla(0, 0%, 0%, 0.15); | ||
border-radius: 0.25rem; | ||
outline: none; | ||
cursor: text; | ||
transition: 0.25s ease-out; | ||
box-shadow: none; | ||
overflow: hidden; | ||
text-overflow: ellipsis; | ||
white-space: nowrap; | ||
min-width: 0; | ||
} | ||
.examples { | ||
display: flex; | ||
width: 90%; | ||
margin: auto; | ||
overflow-y: auto; | ||
flex-wrap: wrap; | ||
} | ||
</style> |
Oops, something went wrong.