Skip to content

Commit

Permalink
refactor: use settings component for oscillator
Browse files Browse the repository at this point in the history
  • Loading branch information
heypoom committed Dec 17, 2023
1 parent ad11f43 commit 9e42a3f
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 69 deletions.
7 changes: 5 additions & 2 deletions canvas/src/blocks/components/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Props<T extends BlockTypes, F extends Field<T, BlockKeys<T>>> = {
schema: SchemaOf<T, F>
className?: string
onUpdate?: () => void
children?: ReactNode
}

export const Settings = <
Expand Down Expand Up @@ -73,7 +74,7 @@ export const Settings = <
if (type === "select") {
const options = field.options.map((f) => ({
value: f.key as string,
label: f.title,
label: f.title ?? (f.key as string),
}))

const vt = value as { type: string }
Expand Down Expand Up @@ -125,11 +126,13 @@ export const Settings = <

return null
})}

{props.children}
</div>
)
}

const FieldGroup = (props: { name: string; children: ReactNode }) => (
export const FieldGroup = (props: { name: string; children: ReactNode }) => (
<div className="grid grid-cols-2 gap-x-3">
<div className="flex items-center capitalize">{props.name}</div>

Expand Down
103 changes: 38 additions & 65 deletions canvas/src/blocks/osc.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
import { TextField } from "@radix-ui/themes"
import { Waveform } from "machine-wasm"
import { useState } from "react"

import { BaseBlock } from "@/blocks/components"
import { FieldGroup, Settings } from "@/blocks/components/Settings"
import { createSchema } from "@/blocks/types/schema"
import { engine } from "@/engine"
import { BlockPropsOf } from "@/types/Node"
import { RadixSelect } from "@/ui"

export type WaveformKey = Waveform["type"]

const waveforms: WaveformKey[] = [
"Sine",
"Cosine",
"Tangent",
"Square",
"Sawtooth",
"Triangle",
]

const waveformOptions = waveforms.map((value) => ({
value,
label: value,
}))
const schema = createSchema({
type: "Osc",
fields: [
{
key: "waveform",
type: "select",
options: [
{ key: "Sine" },
{ key: "Cosine" },
{ key: "Tangent" },
{ key: "Square", defaults: { duty_cycle: 50 } },
{ key: "Sawtooth" },
{ key: "Triangle" },
],
},
],
})

type OscProps = BlockPropsOf<"Osc">

Expand All @@ -32,26 +34,6 @@ export const OscBlock = (props: OscProps) => {
const [cycleText, setCycleText] = useState("")
const [cycleError, setCycleError] = useState(false)

const setWaveform = (waveform: Waveform) =>
engine.setBlock(id, "Osc", { waveform })

function handleWaveChange(key: string) {
let w = { type: key } as Waveform

// Update duty cycle
if (w.type === "Square") {
if (cycleText) {
const cycle = parseInt(cycleText)

if (!isNaN(cycle)) w = { ...w, duty_cycle: cycle }
} else {
setCycleText(w.duty_cycle.toString())
}
}

setWaveform(w)
}

function getOscLog() {
let argsText = ""

Expand All @@ -64,54 +46,45 @@ export const OscBlock = (props: OscProps) => {
return `${wave?.toLowerCase()}(${argsText})`
}

const Settings = () => (
<section className="flex flex-col space-y-2 w-full">
<div className="flex items-center gap-4 w-full">
<p className="text-1">Fn</p>
function setDutyCycle(input: string) {
setCycleText(input)

<RadixSelect
value={wave.toString()}
onChange={handleWaveChange}
options={waveformOptions}
/>
</div>
const cycle = parseInt(input)
const valid = !isNaN(cycle) && cycle >= 0 && cycle <= 255
setCycleError(!valid)

{wave === "Square" && (
<div className="flex items-center gap-4 w-full">
<p className="text-1">Cycle</p>
if (!valid) return

engine.setBlock(id, "Osc", {
waveform: { type: "Square", duty_cycle: cycle },
})
}

const renderSettings = () => (
<Settings id={id} schema={schema}>
{wave === "Square" && (
<FieldGroup name="Duty Cycle">
<TextField.Input
className="max-w-[70px]"
size="1"
type="number"
min={0}
max={255}
value={cycleText}
onChange={(k) => {
const str = k.target.value
setCycleText(str)

const cycle = parseInt(str)
const valid = !isNaN(cycle) && cycle >= 0 && cycle <= 255
setCycleError(!valid)

if (valid) {
setWaveform({ type: "Square", duty_cycle: cycle })
}
}}
onChange={(k) => setDutyCycle(k.target.value)}
{...(cycleError && { color: "tomato" })}
/>
</div>
</FieldGroup>
)}
</section>
</Settings>
)

return (
<BaseBlock
node={props}
targets={1}
sources={1}
settings={Settings}
settings={renderSettings}
className="px-4 py-2 font-mono text-center"
>
{getOscLog()}
Expand Down
2 changes: 1 addition & 1 deletion canvas/src/blocks/types/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type CheckboxField = { type: "checkbox" }

type SelectField<T extends BlockTypes, K extends BlockKeys<T>> = {
type: "select"
options: { key: BlockValue<T, K>; title: string; defaults?: object }[]
options: { key: BlockValue<T, K>; title?: string; defaults?: object }[]
}

export type Field<T extends BlockTypes, K extends BlockKeys<T>> = {
Expand Down
2 changes: 1 addition & 1 deletion canvas/src/blocks/value-view/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const schema = createSchema({
{ key: "Bytes", title: "Byte View" },
{ key: "Switches", title: "Switch", defaults: { bits: [] } },
{ key: "ColorGrid", title: "Binary Grid" },
{ key: "String", title: "String" },
{ key: "String" },
],
},
{ key: "target", type: "number", min: 0 },
Expand Down

0 comments on commit 9e42a3f

Please sign in to comment.