diff options
Diffstat (limited to 'src/features/surface-host/ui')
| -rw-r--r-- | src/features/surface-host/ui/Button.svelte | 21 | ||||
| -rw-r--r-- | src/features/surface-host/ui/Progress.svelte | 13 | ||||
| -rw-r--r-- | src/features/surface-host/ui/Selector.svelte | 32 | ||||
| -rw-r--r-- | src/features/surface-host/ui/Stat.svelte | 10 | ||||
| -rw-r--r-- | src/features/surface-host/ui/SurfaceView.svelte | 33 | ||||
| -rw-r--r-- | src/features/surface-host/ui/Toggle.svelte | 25 |
6 files changed, 134 insertions, 0 deletions
diff --git a/src/features/surface-host/ui/Button.svelte b/src/features/surface-host/ui/Button.svelte new file mode 100644 index 0000000..62d7acf --- /dev/null +++ b/src/features/surface-host/ui/Button.svelte @@ -0,0 +1,21 @@ +<script lang="ts"> + import type { InvokeMessage } from "@dispatch/ui-contract"; + import type { ButtonFieldView } from "../logic/types"; + + let { + field, + surfaceId, + onInvoke, + }: { field: ButtonFieldView; surfaceId: string; onInvoke: (msg: InvokeMessage) => void } = + $props(); + + function handleClick() { + onInvoke({ + type: "invoke", + surfaceId, + actionId: field.action.actionId, + }); + } +</script> + +<button onclick={handleClick}>{field.label}</button> diff --git a/src/features/surface-host/ui/Progress.svelte b/src/features/surface-host/ui/Progress.svelte new file mode 100644 index 0000000..cba9e0f --- /dev/null +++ b/src/features/surface-host/ui/Progress.svelte @@ -0,0 +1,13 @@ +<script lang="ts"> + import type { ProgressFieldView } from "../logic/types"; + + let { field }: { field: ProgressFieldView } = $props(); + + const percent = $derived(Math.round(field.value * 100)); +</script> + +<div> + <span>{field.label}</span> + <progress max="100" value={percent}>{percent}%</progress> + <span>{percent}%</span> +</div> diff --git a/src/features/surface-host/ui/Selector.svelte b/src/features/surface-host/ui/Selector.svelte new file mode 100644 index 0000000..2da104f --- /dev/null +++ b/src/features/surface-host/ui/Selector.svelte @@ -0,0 +1,32 @@ +<script lang="ts"> + import type { InvokeMessage } from "@dispatch/ui-contract"; + import type { SelectorFieldView } from "../logic/types"; + + let { + field, + surfaceId, + onInvoke, + }: { field: SelectorFieldView; surfaceId: string; onInvoke: (msg: InvokeMessage) => void } = + $props(); + + function handleChange(event: Event) { + const target = event.target as HTMLSelectElement; + onInvoke({ + type: "invoke", + surfaceId, + actionId: field.action.actionId, + payload: target.value, + }); + } +</script> + +<label> + {field.label} + <select onchange={handleChange}> + {#each field.options as option (option.value)} + <option value={option.value} selected={option.value === field.value}> + {option.label} + </option> + {/each} + </select> +</label> diff --git a/src/features/surface-host/ui/Stat.svelte b/src/features/surface-host/ui/Stat.svelte new file mode 100644 index 0000000..e184dab --- /dev/null +++ b/src/features/surface-host/ui/Stat.svelte @@ -0,0 +1,10 @@ +<script lang="ts"> + import type { StatFieldView } from "../logic/types"; + + let { field }: { field: StatFieldView } = $props(); +</script> + +<dl> + <dt>{field.label}</dt> + <dd>{field.value}</dd> +</dl> diff --git a/src/features/surface-host/ui/SurfaceView.svelte b/src/features/surface-host/ui/SurfaceView.svelte new file mode 100644 index 0000000..4207913 --- /dev/null +++ b/src/features/surface-host/ui/SurfaceView.svelte @@ -0,0 +1,33 @@ +<script lang="ts"> + import type { InvokeMessage, SurfaceSpec } from "@dispatch/ui-contract"; + import { planSurface } from "../logic/plan"; + import Button from "./Button.svelte"; + import Progress from "./Progress.svelte"; + import Selector from "./Selector.svelte"; + import Stat from "./Stat.svelte"; + import Toggle from "./Toggle.svelte"; + + let { + spec, + onInvoke, + }: { spec: SurfaceSpec; onInvoke: (msg: InvokeMessage) => void } = $props(); + + const plan = $derived(planSurface(spec)); +</script> + +<article> + <h2>{spec.title}</h2> + {#each plan.fields as field (field)} + {#if field.kind === "toggle"} + <Toggle {field} surfaceId={spec.id} {onInvoke} /> + {:else if field.kind === "progress"} + <Progress {field} /> + {:else if field.kind === "selector"} + <Selector {field} surfaceId={spec.id} {onInvoke} /> + {:else if field.kind === "stat"} + <Stat {field} /> + {:else if field.kind === "button"} + <Button {field} surfaceId={spec.id} {onInvoke} /> + {/if} + {/each} +</article> diff --git a/src/features/surface-host/ui/Toggle.svelte b/src/features/surface-host/ui/Toggle.svelte new file mode 100644 index 0000000..aec8f4e --- /dev/null +++ b/src/features/surface-host/ui/Toggle.svelte @@ -0,0 +1,25 @@ +<script lang="ts"> + import type { InvokeMessage } from "@dispatch/ui-contract"; + import type { ToggleFieldView } from "../logic/types"; + + let { + field, + surfaceId, + onInvoke, + }: { field: ToggleFieldView; surfaceId: string; onInvoke: (msg: InvokeMessage) => void } = + $props(); + + function handleChange() { + onInvoke({ + type: "invoke", + surfaceId, + actionId: field.action.actionId, + payload: !field.value, + }); + } +</script> + +<label> + <input type="checkbox" checked={field.value} onchange={handleChange} /> + {field.label} +</label> |
