diff --git a/.changeset/friendly-jobs-crash.md b/.changeset/friendly-jobs-crash.md new file mode 100644 index 0000000000..7c092c0f94 --- /dev/null +++ b/.changeset/friendly-jobs-crash.md @@ -0,0 +1,6 @@ +--- +"@quri/squiggle-lang": patch +"@quri/squiggle-components": patch +--- + +Added Tag.startOpen, Tag.startClosed, and Tag.getStartOpenState diff --git a/packages/components/src/components/SquiggleViewer/utils.ts b/packages/components/src/components/SquiggleViewer/utils.ts index ab9c1381f3..367b1434cc 100644 --- a/packages/components/src/components/SquiggleViewer/utils.ts +++ b/packages/components/src/components/SquiggleViewer/utils.ts @@ -160,6 +160,12 @@ export const shouldBeginCollapsed = ( value: SqValueWithContext, path: SqValuePath ): boolean => { + const startOpenState = value.tags.startOpenState(); + if (startOpenState === "open") { + return false; + } else if (startOpenState === "closed") { + return true; + } const childrenValues = getChildrenValues(value); if (path.isRoot()) { return childrenValues.length > 30; diff --git a/packages/components/src/stories/SquigglePlayground.stories.tsx b/packages/components/src/stories/SquigglePlayground.stories.tsx index 9bca523e9a..dcd6efc209 100644 --- a/packages/components/src/stories/SquigglePlayground.stories.tsx +++ b/packages/components/src/stories/SquigglePlayground.stories.tsx @@ -291,17 +291,26 @@ export const Tagged: Story = { args: { defaultCode: `z = 34 -> Tag.format(".1f") - @name("My favorite Dist") - @doc("This is a long description") - @format("$.2") - x = 5 to 10 - - @showAs(Plot.numericFn) - @name("My favorite Fn") - fn = {|e| e} +@name("My favorite Dist") +@doc("This is a long description") +@format("$.2") +x = 5 to 10 - bar = [x, fn] - - y = x -> Tag.getAll`, +@showAs(Plot.numericFn) +@name("My favorite Fn") +fn = {|e| e} + +@hide +bar = [x, fn] + +@startOpen +s = 4 to 10 + +@startClosed +@showAs(Plot.numericFn) +@name("My favorite Fn2") +fn2 = {|e| e} + +y = x -> Tag.getAll`, }, }; diff --git a/packages/squiggle-lang/__tests__/library/tag_test.ts b/packages/squiggle-lang/__tests__/library/tag_test.ts index e4640ca5ce..9f023f7212 100644 --- a/packages/squiggle-lang/__tests__/library/tag_test.ts +++ b/packages/squiggle-lang/__tests__/library/tag_test.ts @@ -29,6 +29,15 @@ describe("Tags", () => { testEvalToBe("3 -> Tag.hide -> Tag.getHide", "true"); }); + describe("startOpenToggle", () => { + testEvalToBe("3 -> Tag.startOpen -> Tag.getStartOpenState", '"open"'); + testEvalToBe("3 -> Tag.startClosed -> Tag.getStartOpenState", '"closed"'); + testEvalToBe( + "3 -> Tag.startClosed -> Tag.startOpen -> Tag.getStartOpenState", + '"open"' + ); + }); + describe("omit", () => { testEvalToBe( "123 -> Tag.name('myName') -> Tag.doc('myDoc') -> Tag.format('.2%') -> Tag.omit(['name', 'doc']) -> Tag.getAll", diff --git a/packages/squiggle-lang/src/fr/tag.ts b/packages/squiggle-lang/src/fr/tag.ts index 71896f3ef3..629eddabee 100644 --- a/packages/squiggle-lang/src/fr/tag.ts +++ b/packages/squiggle-lang/src/fr/tag.ts @@ -289,6 +289,50 @@ example2 = {|x| x + 1}`, }), ], }), + maker.make({ + name: "startOpen", + description: `When the value is first displayed, it will begin open in the viewer. Refresh the page to reset.`, + displaySection: "Tags", + definitions: [ + makeDefinition( + [frWithTags(frAny({ genericName: "A" }))], + frWithTags(frAny({ genericName: "A" })), + ([{ value, tags }]) => ({ + value, + tags: tags.merge({ startOpenState: "open" }), + }), + { isDecorator: true } + ), + ], + }), + maker.make({ + name: "startClosed", + description: `When the value is first displayed, it will begin collapsed in the viewer. Refresh the page to reset.`, + displaySection: "Tags", + definitions: [ + makeDefinition( + [frWithTags(frAny({ genericName: "A" }))], + frWithTags(frAny({ genericName: "A" })), + ([{ value, tags }]) => ({ + value, + tags: tags.merge({ startOpenState: "closed" }), + }), + { isDecorator: true } + ), + ], + }), + maker.make({ + name: "getStartOpenState", + displaySection: "Tags", + description: `Returns the startOpenState of a value, which can be "open", "closed", or "" if no startOpenState is set. Set using \`Tag.startOpen\` and \`Tag.startClosed\`.`, + definitions: [ + makeDefinition( + [frWithTags(frAny())], + frString, + ([{ tags }]) => tags?.value.startOpenState || "", + ), + ], + }), maker.make({ name: "notebook", description: `Displays the list of values as a notebook. This means that element indices are hidden, and the values are displayed in a vertical list. Useful for displaying combinations of text and values.`, diff --git a/packages/squiggle-lang/src/public/SqValue/SqTags.ts b/packages/squiggle-lang/src/public/SqValue/SqTags.ts index cd2798dd77..0d9a6f6937 100644 --- a/packages/squiggle-lang/src/public/SqValue/SqTags.ts +++ b/packages/squiggle-lang/src/public/SqValue/SqTags.ts @@ -36,4 +36,8 @@ export class SqTags { notebook(): boolean | undefined { return this.tags.notebook(); } + + startOpenState(): "open" | "closed" | undefined { + return this.tags.startOpenState(); + } } diff --git a/packages/squiggle-lang/src/value/valueTags.ts b/packages/squiggle-lang/src/value/valueTags.ts index 6ab122dfae..ef1ce8fe9a 100644 --- a/packages/squiggle-lang/src/value/valueTags.ts +++ b/packages/squiggle-lang/src/value/valueTags.ts @@ -11,6 +11,7 @@ export type ValueTagsType = { dateFormat?: string; hidden?: boolean; notebook?: boolean; + startOpenState?: "open" | "closed"; }; type ValueTagsTypeName = keyof ValueTagsType; @@ -23,6 +24,7 @@ const valueTagsTypeNames: ValueTagsTypeName[] = [ "dateFormat", "hidden", "notebook", + "startOpenState", ]; function convertToValueTagsTypeName( @@ -69,6 +71,9 @@ export class ValueTags { if (value.notebook) { result.push(["notebook", vBool(value.notebook)]); } + if (value.startOpenState) { + result.push(["startOpenState", vString(value.startOpenState)]); + } return result; } @@ -128,4 +133,8 @@ export class ValueTags { notebook() { return this.value.notebook; } + + startOpenState() { + return this.value.startOpenState; + } }