From c635acc630a2df88a197636dfa24d692e68b8de6 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sun, 22 Oct 2023 13:13:19 -0700 Subject: [PATCH] Added Calculator Inputs to documentation, changed 'fields' to 'inputs' for consisency --- .changeset/curvy-monkeys-deliver.md | 6 ++ .../src/components/Calculator/asyncActions.ts | 12 ++-- .../Calculator/calculatorReducer.ts | 28 ++++----- .../components/Calculator/calculatorUI.tsx | 12 ++-- .../SquiggleChart/Calculator.stories.tsx | 4 +- .../stories/SquigglePlayground.stories.tsx | 23 +++---- packages/squiggle-lang/src/fr/calculator.ts | 6 +- .../src/public/SqValue/SqCalculator.ts | 6 +- packages/squiggle-lang/src/value/index.ts | 10 +-- .../website/src/pages/docs/Api/Calculator.mdx | 63 ++++++++++++++----- 10 files changed, 102 insertions(+), 68 deletions(-) create mode 100644 .changeset/curvy-monkeys-deliver.md diff --git a/.changeset/curvy-monkeys-deliver.md b/.changeset/curvy-monkeys-deliver.md new file mode 100644 index 0000000000..47c0833c06 --- /dev/null +++ b/.changeset/curvy-monkeys-deliver.md @@ -0,0 +1,6 @@ +--- +"@quri/squiggle-lang": patch +"@quri/squiggle-components": patch +--- + +Breaking: Changed Calculator fields attribute, to inputs, which now requires Input objects. These allow for multiple types of inputs diff --git a/packages/components/src/components/Calculator/asyncActions.ts b/packages/components/src/components/Calculator/asyncActions.ts index 2a20a36acc..03f992d084 100644 --- a/packages/components/src/components/Calculator/asyncActions.ts +++ b/packages/components/src/components/Calculator/asyncActions.ts @@ -72,13 +72,13 @@ function modifyCode( calculator: SqCalculator, code: string ): string { - const input = calculator.fields.find((row) => row.name === name); + const input = calculator.inputs.find((row) => row.name === name); if (!input) { throw new Error("Invalid input name."); } return alterCodeForSquiggleRun(input, code); } -// Gets all field codes in the State. Runs them all, runs the function, and updates all these values in the state. +// Gets all input codes in the State. Runs them all, runs the function, and updates all these values in the state. export async function processAllFieldCodes({ dispatch, path, @@ -93,10 +93,10 @@ export async function processAllFieldCodes({ environment: Env; }) { let _state = state; - for (const name of state.fieldNames) { - const field = state.fields[name]; + for (const name of state.inputNames) { + const input = state.inputs[name]; const valueResult = await runSquiggleCode( - modifyCode(name, calculator, field.code), + modifyCode(name, calculator, input.code), environment ); const _action: CalculatorAction = { @@ -109,7 +109,7 @@ export async function processAllFieldCodes({ updateFnValue({ path, state: _state, calculator, environment, dispatch }); } -// Takes an updated field code, runs it, and runs the function. +// Takes an updated input code, runs it, and runs the function. export async function updateAndProcessFieldCode({ dispatch, path, diff --git a/packages/components/src/components/Calculator/calculatorReducer.ts b/packages/components/src/components/Calculator/calculatorReducer.ts index 232e772efd..bf6d23e7c0 100644 --- a/packages/components/src/components/Calculator/calculatorReducer.ts +++ b/packages/components/src/components/Calculator/calculatorReducer.ts @@ -20,8 +20,8 @@ export type ResultValue = { }; export type CalculatorState = { - fieldNames: string[]; - fields: Record; + inputNames: string[]; + inputs: Record; fn: ResultValue; hash: string; }; @@ -31,7 +31,7 @@ export function hasSameCalculator(state: CalculatorState, calc: SqCalculator) { } export function allFields(state: CalculatorState): FieldValue[] { - return state.fieldNames.map((name) => state.fields[name]); + return state.inputNames.map((name) => state.inputs[name]); } export function allFieldResults( @@ -47,16 +47,16 @@ export function allFieldValuesAreValid(state: CalculatorState): boolean { export function initialCalculatorState( calculator: SqCalculator ): CalculatorState { - const fields: Record = {}; - calculator.fields.forEach((row) => { - fields[row.name] = { + const inputs: Record = {}; + calculator.inputs.forEach((row) => { + inputs[row.name] = { name: row.name, code: defaultAsString(row), }; }); return { - fieldNames: calculator.fields.map((row) => row.name), - fields, + inputNames: calculator.inputs.map((row) => row.name), + inputs, fn: {}, hash: calculator.hashString, }; @@ -89,8 +89,8 @@ export const calculatorReducer = ( action: CalculatorAction ): CalculatorState => { const modifyField = (name: string, newField: FieldValue) => { - const newFields = { ...state.fields, [name]: newField }; - return { ...state, fields: newFields }; + const newFields = { ...state.inputs, [name]: newField }; + return { ...state, inputs: newFields }; }; switch (action.type) { case "RESET": { @@ -98,14 +98,14 @@ export const calculatorReducer = ( } case "SET_FIELD_CODE": { const { name, code } = action.payload; - const field = state.fields[name]; - const newField = { ...field, code, value: undefined }; + const input = state.inputs[name]; + const newField = { ...input, code, value: undefined }; return modifyField(name, newField); } case "SET_FIELD_VALUE": { const { name, value } = action.payload; - const field = state.fields[name]; - const newField = { ...field, value }; + const input = state.inputs[name]; + const newField = { ...input, value }; return modifyField(name, newField); } case "SET_FUNCTION_VALUE": { diff --git a/packages/components/src/components/Calculator/calculatorUI.tsx b/packages/components/src/components/Calculator/calculatorUI.tsx index 23600fbff6..57b9a09e5e 100644 --- a/packages/components/src/components/Calculator/calculatorUI.tsx +++ b/packages/components/src/components/Calculator/calculatorUI.tsx @@ -52,7 +52,7 @@ export const CalculatorUI: FC = ({ calculatorState, onChange, }) => { - const fieldShowSettings: PlaygroundSettings = { + const inputShowSettings: PlaygroundSettings = { ...settings, distributionChartSettings: { ...settings.distributionChartSettings, @@ -85,11 +85,11 @@ export const CalculatorUI: FC = ({ )}
- {calculator.fields.map((row) => { + {calculator.inputs.map((row) => { const { name, description } = row; - const field = calculatorState.fields[name]; - if (field) { - const { value, code } = field; + const input = calculatorState.inputs[name]; + if (input) { + const { value, code } = input; const result = value; const resultHasInterestingError = result && !result.ok && code !== ""; @@ -176,7 +176,7 @@ export const CalculatorUI: FC = ({
{result && resultHasInterestingError && - showSqValue(renderValue, result, fieldShowSettings)} + showSqValue(renderValue, result, inputShowSettings)} {!result && (
No result
)} diff --git a/packages/components/src/stories/SquiggleChart/Calculator.stories.tsx b/packages/components/src/stories/SquiggleChart/Calculator.stories.tsx index 555bfe3805..b04647d00d 100644 --- a/packages/components/src/stories/SquiggleChart/Calculator.stories.tsx +++ b/packages/components/src/stories/SquiggleChart/Calculator.stories.tsx @@ -20,8 +20,8 @@ export const Basic: Story = { fn: f, title: "My Calculator", description: a, - fields: [ - Input.checkbox({name: "VariableCheckbox", description: "This is a long name", default: true}), + inputs: [ + Input.checkbox({name: "VariableCheckbox", description: "This is a long name", default: false}), Input.textArea({name: "Variable2", description: "This is a long name", default: "2 to 40"}), Input.text({name: "Variable1", description: "This is a very long description This is a very long description This is a very long description This is a very long description This is a very long description", default: 1}), Input.select({name: "Variable3", default: "alice", options: ["alice", "charles", "bob", "bill", "maven", "billy", "samantha", "becky"]}) diff --git a/packages/components/src/stories/SquigglePlayground.stories.tsx b/packages/components/src/stories/SquigglePlayground.stories.tsx index 0b490ea773..e57d3bc5b2 100644 --- a/packages/components/src/stories/SquigglePlayground.stories.tsx +++ b/packages/components/src/stories/SquigglePlayground.stories.tsx @@ -234,25 +234,22 @@ bar = 123 export const Calculator: Story = { name: "Calculator", args: { - defaultCode: `f(a, b, c) = [a + b, a, c] - -a = "## My favorite calculator\nA longer description of the calculator goes here...\n" - + defaultCode: `f(a, b, c, d) = [a,b,c,d] +a = "A longer description of the calculator goes here...\n" Calculator.make( { fn: f, + title: "My Calculator", description: a, - fields: [ - { - name: "Variable 1", - default: "1", - description: "This is a short description of the first variable input", - }, - { name: "Variable2", default: "2 to 40" }, - { name: "Some array", default: "[3,3,5,2,2]" }, + inputs: [ + Input.checkbox({name: "VariableCheckbox", description: "This is a long name", default: false}), + Input.textArea({name: "Variable2", description: "This is a long name", default: "2 to 40"}), + Input.text({name: "Variable1", description: "This is a very long description This is a very long description This is a very long description This is a very long description This is a very long description", default: 1}), + Input.select({name: "Variable3", default: "alice", options: ["alice", "charles", "bob", "bill", "maven", "billy", "samantha", "becky"]}) ], } -) `, +) + `, height: 800, }, }; diff --git a/packages/squiggle-lang/src/fr/calculator.ts b/packages/squiggle-lang/src/fr/calculator.ts index bfdd14ceaa..4e751caba6 100644 --- a/packages/squiggle-lang/src/fr/calculator.ts +++ b/packages/squiggle-lang/src/fr/calculator.ts @@ -27,15 +27,15 @@ export const library = [ ["fn", frLambda], ["title", frOptional(frString)], ["description", frOptional(frString)], - ["fields", frArray(frInput)] + ["inputs", frArray(frInput)] ), ], - ([{ fn, title, description, fields }]) => { + ([{ fn, title, description, inputs }]) => { const calc = vCalculator({ fn, title: title || undefined, description: description || undefined, - fields: fields, + inputs: inputs, }); const error = calc.getError(); if (error) { diff --git a/packages/squiggle-lang/src/public/SqValue/SqCalculator.ts b/packages/squiggle-lang/src/public/SqValue/SqCalculator.ts index 7340b9c2ec..2674f7e098 100644 --- a/packages/squiggle-lang/src/public/SqValue/SqCalculator.ts +++ b/packages/squiggle-lang/src/public/SqValue/SqCalculator.ts @@ -43,12 +43,12 @@ export class SqCalculator { // It's obviously not perfect - it doesn't capture changes within the calculator function, but this would be much more complicated. get hashString(): string { - const rowData = JSON.stringify(this._value.fields); + const rowData = JSON.stringify(this._value.inputs); const paramData = this._value.fn.toString() || ""; return rowData + paramData + this._value.description; } - get fields(): SqInput[] { - return this._value.fields.map(wrapInput); + get inputs(): SqInput[] { + return this._value.inputs.map(wrapInput); } } diff --git a/packages/squiggle-lang/src/value/index.ts b/packages/squiggle-lang/src/value/index.ts index c158eb2463..8614432f3f 100644 --- a/packages/squiggle-lang/src/value/index.ts +++ b/packages/squiggle-lang/src/value/index.ts @@ -491,7 +491,7 @@ export const vTableChart = (v: TableChart) => new VTableChart(v); export type Calculator = { fn: Lambda; - fields: Input[]; + inputs: Input[]; description?: string; title?: string; }; @@ -504,19 +504,19 @@ class VCalculator extends BaseValue { constructor(public value: Calculator) { super(); - if (!value.fn.parameterCounts().includes(value.fields.length)) { + if (!value.fn.parameterCounts().includes(value.inputs.length)) { this.setError( `Calculator function needs ${value.fn.parameterCountString()} parameters, but ${ - value.fields.length + value.inputs.length } fields were provided.` ); } - if (value.fields.some((x) => x.name === "")) { + if (value.inputs.some((x) => x.name === "")) { this.setError(`Calculator field names can't be empty.`); } - const fieldNames = value.fields.map((f) => f.name); + const fieldNames = value.inputs.map((f) => f.name); const uniqueNames = new Set(fieldNames); if (fieldNames.length !== uniqueNames.size) { this.setError(`Duplicate calculator field names found.`); diff --git a/packages/website/src/pages/docs/Api/Calculator.mdx b/packages/website/src/pages/docs/Api/Calculator.mdx index c464066eea..be1ab938ef 100644 --- a/packages/website/src/pages/docs/Api/Calculator.mdx +++ b/packages/website/src/pages/docs/Api/Calculator.mdx @@ -17,32 +17,63 @@ Calculator.make: ({ fn: ...arguments => any, title?: string, description?: string, - fields: list<{ - name: string, - default?: string | number, - description?: string - }> + fields: list }) => calculator ``` ``Calculator.make`` takes in a function, a description, and a list of fields. The function should take in the same number of arguments as the number of fields, and the arguments should be of the same type as the default value of the field. -Examples: +Calculators require a list of Inputs to be passed in. Inputs are created using the ``Input`` module. The ``Input`` module has a few different functions for creating different types of inputs. + +Example: \ No newline at end of file +/> + +## Inputs + +Inputs are now only used for creating calculators, as shown above. They are created using the ``Input`` module. + +``` +Input.text: ({ + name: string, + description?: string, + default?: string, +}) => input + +Input.textArea: ({ + name: string, + description?: string, + default?: string, +}) => input + +Input.checkbox: ({ + name: string, + description?: string, + default?: boolean, +}) => input + +Input.select: ({ + name: string, + description?: string, + default?: string, + options: string[] +}) => input +``` \ No newline at end of file