Skip to content

Commit

Permalink
Merge pull request #2335 from quantified-uncertainty/imports
Browse files Browse the repository at this point in the history
Imports in Hub
  • Loading branch information
OAGr authored Nov 1, 2023
2 parents b1488cd + 883a55f commit 7d705c1
Show file tree
Hide file tree
Showing 63 changed files with 1,454 additions and 1,168 deletions.
1 change: 1 addition & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"d3": "^7.8.5",
"framer-motion": "^10.16.4",
"lodash": "^4.17.21",
"mermaid": "^10.5.0",
"prettier": "^3.0.3",
"react": "^18.2.0",
"react-error-boundary": "^4.0.11",
Expand Down
37 changes: 18 additions & 19 deletions packages/components/src/components/CodeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ interface CodeEditorProps {
export type CodeEditorHandle = {
format(): void;
scrollTo(position: number): void;
viewCurrentPosition(): void;
};

const compTheme = new Compartment();
Expand Down Expand Up @@ -183,7 +184,21 @@ export const CodeEditor = forwardRef<CodeEditorHandle, CodeEditorProps>(
view?.focus();
};

useImperativeHandle(ref, () => ({ format, scrollTo }));
const viewCurrentPosition = useCallback(() => {
if (!onViewValuePath || !view || !sourceId) {
return;
}
const offset = view.state.selection.main.to;
if (offset === undefined) {
return;
}
const valuePathResult = project.findValuePathByOffset(sourceId, offset);
if (valuePathResult.ok) {
onViewValuePath(valuePathResult.value);
}
}, [onViewValuePath, project, sourceId, view]);

useImperativeHandle(ref, () => ({ format, scrollTo, viewCurrentPosition }));

useEffect(() => {
view?.dispatch({
Expand Down Expand Up @@ -284,30 +299,14 @@ export const CodeEditor = forwardRef<CodeEditorHandle, CodeEditorProps>(
{
key: "Alt-Shift-v",
run: () => {
if (!onViewValuePath) {
return true;
}
const offset = view.state.selection.main.to;
if (offset === undefined) {
return true;
}
if (sourceId === undefined) {
return true;
}
const valuePathResult = project.findValuePathByOffset(
sourceId,
offset
);
if (valuePathResult.ok) {
onViewValuePath(valuePathResult.value);
}
viewCurrentPosition();
return true;
},
},
])
),
});
}, [onViewValuePath, project, sourceId, view]);
}, [view, viewCurrentPosition]);

useEffect(() => {
if (!view) return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import clsx from "clsx";

import { BoltIcon, PauseIcon } from "@quri/ui";

Expand All @@ -15,10 +16,10 @@ export const AutorunnerMenuItem: React.FC<RunnerState> = ({
aria-checked={autorunMode}
>
<ToolbarItem
tooltipText={"Triggers runs on code changes"}
tooltipText="Triggers runs on code changes"
icon={autorunMode ? BoltIcon : PauseIcon}
className={clsx(!autorunMode && "opacity-60")}
onClick={() => setAutorunMode(!autorunMode)}
className={!autorunMode ? "opacity-60" : ""}
>
Autorun
</ToolbarItem>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { FC, lazy } from "react";

import { SqProject } from "@quri/squiggle-lang";

const Mermaid = lazy(() => import("../../ui/Mermaid.js"));

export const DependencyGraphModal: FC<{
project: SqProject;
}> = ({ project }) => {
const sourceIds = project.getSourceIds();

let diagram = "graph TD\n";
for (const sourceId of sourceIds) {
diagram += `${sourceId}\n`; // for sources that don't have any dependencies
for (const dependencyId of project.getDependencies(sourceId)) {
diagram += `${sourceId} --> ${dependencyId}\n`;
}
}

return (
<div className="flex flex-col items-center">
<Mermaid>{diagram}</Mermaid>
</div>
);
};

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@ import {
useRef,
} from "react";

import { SqValuePath } from "@quri/squiggle-lang";
import { Bars3CenterLeftIcon } from "@quri/ui";
import { SqProject, SqValuePath } from "@quri/squiggle-lang";
import {
AdjustmentsVerticalIcon,
Bars3CenterLeftIcon,
Dropdown,
DropdownMenu,
DropdownMenuActionItem,
PuzzleIcon,
TriangleIcon,
} from "@quri/ui";

import {
SquiggleOutput,
Expand All @@ -22,16 +30,18 @@ import { PlaygroundSettings } from "../../PlaygroundSettings.js";
import { ToolbarItem } from "../../ui/PanelWithToolbar/ToolbarItem.js";
import { PanelWithToolbar } from "../../ui/PanelWithToolbar/index.js";
import { AutorunnerMenuItem } from "./AutorunnerMenuItem.js";
import { DependencyGraphModal } from "./DependencyGraphModal.js";
import { GlobalSettingsModal } from "./GlobalSettingsModal.js";
import { RunMenuItem } from "./RunMenuItem.js";
import { SetttingsMenuItem } from "./SettingsMenuItem.js";

export type RenderExtraControls = (props: {
openModal: (name: string) => void;
}) => ReactNode;

type Props = {
project: SqProject;
defaultCode?: string;
sourceId?: string;
onCodeChange?(code: string): void;
settings: PlaygroundSettings;
onSettingsChange(settings: PlaygroundSettings): void;
Expand All @@ -41,6 +51,8 @@ type Props = {
}): void;
/* Allows to inject extra buttons to the left panel's menu, e.g. share button on the website, or save button in Squiggle Hub. */
renderExtraControls?: RenderExtraControls;
/* Allows to inject extra items to the left panel's dropdown menu. */
renderExtraDropdownItems?: RenderExtraControls;
renderExtraModal?: Parameters<typeof PanelWithToolbar>[0]["renderModal"];
onViewValuePath?: (path: SqValuePath) => void;
};
Expand All @@ -49,6 +61,8 @@ type Props = {
export type LeftPlaygroundPanelHandle = {
getEditor(): CodeEditorHandle | null; // used by "find in editor" feature
getLeftPanelElement(): HTMLDivElement | null; // used by local settings modal window positioning
run(): void; // force re-run
invalidate(): void; // mark output as stale but don't re-run if autorun is disabled; useful on environment changes, triggered in <SquigglePlayground> code
};

export const LeftPlaygroundPanel = forwardRef<LeftPlaygroundPanelHandle, Props>(
Expand All @@ -62,8 +76,9 @@ export const LeftPlaygroundPanel = forwardRef<LeftPlaygroundPanelHandle, Props>(

const [squiggleOutput, { project, isRunning, sourceId }] = useSquiggle({
code: runnerState.renderedCode,
project: props.project,
sourceId: props.sourceId,
executionId: runnerState.executionId,
environment: props.settings.environment,
});

const { onOutputChange } = props;
Expand All @@ -87,6 +102,12 @@ export const LeftPlaygroundPanel = forwardRef<LeftPlaygroundPanelHandle, Props>(
useImperativeHandle(ref, () => ({
getEditor: () => editorRef.current,
getLeftPanelElement: () => containerRef.current,
run: () => runnerState.run(),
invalidate: () => {
if (runnerState.autorunMode) {
runnerState.run();
}
},
}));

const renderToolbar = ({
Expand All @@ -102,7 +123,36 @@ export const LeftPlaygroundPanel = forwardRef<LeftPlaygroundPanelHandle, Props>(
icon={Bars3CenterLeftIcon}
onClick={editorRef.current?.format}
/>
<SetttingsMenuItem onClick={() => openModal("settings")} />
<Dropdown
render={() => (
<DropdownMenu>
<DropdownMenuActionItem
title="Configuration"
icon={AdjustmentsVerticalIcon}
onClick={() => openModal("settings")}
/>

{
// experimental, won't always work, so disabled for now
/* <DropdownMenuActionItem
title="Find in Viewer"
icon={AdjustmentsVerticalIcon}
onClick={() => editorRef.current?.viewCurrentPosition()}
/> */
}
<DropdownMenuActionItem
title="Dependency Graph"
icon={PuzzleIcon}
onClick={() => openModal("dependency-graph")}
/>
{props.renderExtraDropdownItems?.({ openModal })}
</DropdownMenu>
)}
>
<ToolbarItem icon={TriangleIcon} iconClasses="rotate-180">
Menu
</ToolbarItem>
</Dropdown>
<div className="flex-1">
{props.renderExtraControls?.({ openModal })}
</div>
Expand All @@ -117,7 +167,7 @@ export const LeftPlaygroundPanel = forwardRef<LeftPlaygroundPanelHandle, Props>(
// see https://github.com/quantified-uncertainty/squiggle/issues/1952
defaultValue={code}
errors={errors}
height={"100%"}
height="100%"
project={project}
sourceId={sourceId}
showGutter={true}
Expand All @@ -130,18 +180,25 @@ export const LeftPlaygroundPanel = forwardRef<LeftPlaygroundPanelHandle, Props>(
);

const renderModal = (modalName: string) => {
if (modalName === "settings") {
return {
title: "Configuration",
body: (
<GlobalSettingsModal
settings={props.settings}
onSettingsChange={props.onSettingsChange}
/>
),
};
switch (modalName) {
case "settings":
return {
title: "Configuration",
body: (
<GlobalSettingsModal
settings={props.settings}
onSettingsChange={props.onSettingsChange}
/>
),
};
case "dependency-graph":
return {
title: "Dependency Graph",
body: <DependencyGraphModal project={project} />,
};
default:
return props.renderExtraModal?.(modalName);
}
return props.renderExtraModal?.(modalName);
};

return (
Expand Down
Loading

0 comments on commit 7d705c1

Please sign in to comment.