Skip to content
8 changes: 3 additions & 5 deletions editor/app/(tools)/(playground)/playground/image/_page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {
ViewportRoot,
EditorSurface,
AutoInitialFitTransformer,
useDocument,
useCurrentEditor,
} from "@/grida-canvas-react";
import { FontFamilyListProvider } from "@/scaffolds/sidecontrol/controls/font-family";
import { useEditorHotKeys } from "@/grida-canvas-react/viewport/hotkeys";
Expand Down Expand Up @@ -124,15 +124,13 @@ export default function ImagePlayground() {
function CanvasConsumer() {
const { withAuth, session } = useContinueWithAuth();
const credits = useCredits();
const editor = useDocument();
const editor = useCurrentEditor();
const [prompt, setPrompt] = useState("");
const model = useImageModelConfig("black-forest-labs/flux-schnell");
const { generate, key, loading, image, start, end } = useGenerateImage();

const onCommit = (value: { text: string }) => {
const id = editor.createNodeId();
editor.insertNode({
_$id: id,
const id = editor.insertNode({
type: "image",
name: value.text,
width: model.width,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
AutoInitialFitTransformer,
StandaloneSceneBackground,
UserCustomTemplatesProvider,
useDocument,
useCurrentEditor,
} from "@/grida-canvas-react";
import { Zoom } from "@/scaffolds/sidecontrol/sidecontrol-node-selection";
import { WorkbenchUI } from "@/components/workbench";
Expand All @@ -21,7 +21,6 @@ import { PreviewProvider } from "@/grida-canvas-react-starter-kit/starterkit-pre
import { Platform } from "@/lib/platform";
import { TemplateData } from "@/theme/templates/west-referral/templates";
import { ReadonlyPropsEditorInstance } from "@/scaffolds/props-editor";
import { useTransform } from "@/grida-canvas-react/provider";
import MessageAppFrame from "@/components/frames/message-app-frame";
import { editor } from "@/grida-canvas";
import { useEditor } from "@/grida-canvas-react";
Expand Down Expand Up @@ -276,14 +275,13 @@ export function CampaignTemplateDuo001Viewer({

// will be removed after useEditor is ready
function EditorUXServer({ focus }: { focus: { node?: string } }) {
const { select } = useDocument();
const { fit } = useTransform();
const editor = useCurrentEditor();

useEffect(
() => {
if (focus.node) {
select([focus.node]);
fit([focus.node], { margin: 64, animate: true });
editor.select([focus.node]);
editor.fit([focus.node], { margin: 64, animate: true });
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ import {
StandaloneDocumentEditor,
ViewportRoot,
EditorSurface,
useDocument,
useRootTemplateInstanceNode,
} from "@/grida-canvas-react";
import { composeEditorDocumentAction } from "@/scaffolds/editor/action";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { useDocument } from "@/grida-canvas-react";
import { useCurrentEditor } from "@/grida-canvas-react";

type ArtboardData = {
name: string;
Expand All @@ -15,10 +15,10 @@ type ArtboardData = {
};

const ArtboardList = () => {
const { insertNode } = useDocument();
const editor = useCurrentEditor();

const onClickItem = (item: ArtboardData) => {
insertNode({
editor.insertNode({
type: "container",
position: "absolute",
name: item.name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import React, {
useCallback,
useRef,
} from "react";
import { useDocument } from "@/grida-canvas-react";
import { useCurrentEditor, useEditorState } from "@/grida-canvas-react";
import {
Tree,
TreeDragLine,
Expand Down Expand Up @@ -35,11 +35,7 @@ import {
EyeClosedIcon,
LockOpen1Icon,
} from "@radix-ui/react-icons";
import {
useCurrentScene,
useNodeAction,
useTransform,
} from "@/grida-canvas-react/provider";
import { useCurrentSceneState } from "@/grida-canvas-react/provider";
import { NodeTypeIcon } from "@/grida-canvas-react-starter-kit/starterkit-icons/node-type-icon";
import { cn } from "@/components/lib/utils";
import grida from "@grida/schema";
Expand All @@ -52,7 +48,7 @@ function SceneItemContextMenuWrapper({
scene_id: string;
onStartRenaming?: () => void;
}>) {
const { deleteScene, duplicateScene } = useDocument();
const editor = useCurrentEditor();

return (
<ContextMenu>
Expand All @@ -71,7 +67,7 @@ function SceneItemContextMenuWrapper({
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
duplicateScene(scene_id);
editor.duplicateScene(scene_id);
}}
className="text-xs"
>
Expand All @@ -80,7 +76,7 @@ function SceneItemContextMenuWrapper({
<ContextMenuSeparator />
<ContextMenuItem
onSelect={() => {
deleteScene(scene_id);
editor.deleteScene(scene_id);
}}
className="text-xs"
>
Expand All @@ -92,7 +88,9 @@ function SceneItemContextMenuWrapper({
}

export function ScenesList() {
const { scenes: scenesmap, scene_id, loadScene, renameScene } = useDocument();
const editor = useCurrentEditor();
const scenesmap = useEditorState(editor, (state) => state.document.scenes);
const scene_id = useEditorState(editor, (state) => state.scene_id);

const scenes = useMemo(() => {
return Object.values(scenesmap).sort(
Expand All @@ -110,7 +108,7 @@ export function ScenesList() {
selectedItems: scene_id ? [scene_id] : [],
},
setSelectedItems: (items) => {
loadScene((items as string[])[0]);
editor.loadScene((items as string[])[0]);
},
getItemName: (item) => {
if (item.getId() === "<document>") return "<document>";
Expand Down Expand Up @@ -174,7 +172,7 @@ export function ScenesList() {
isRenaming={isRenaming}
initialValue={scene.name}
onValueCommit={(name) => {
renameScene(scene.id, name);
editor.renameScene(scene.id, name);
tree.abortRenaming();
}}
className="font-normal h-8 text-xs! px-2! py-1.5!"
Expand All @@ -196,17 +194,15 @@ function NodeHierarchyItemContextMenuWrapper({
node_id: string;
onStartRenaming?: () => void;
}>) {
const { copy, deleteNode, order } = useDocument();
const { fit } = useTransform();
const change = useNodeAction(node_id)!;
const editor = useCurrentEditor();

return (
<ContextMenu>
<ContextMenuTrigger>{children}</ContextMenuTrigger>
<ContextMenuContent className="min-w-52">
<ContextMenuItem
onSelect={() => {
copy(node_id);
editor.copy(node_id);
}}
className="text-xs"
>
Expand All @@ -225,42 +221,48 @@ function NodeHierarchyItemContextMenuWrapper({
{/* <ContextMenuItem onSelect={() => {}}>Copy</ContextMenuItem> */}
{/* <ContextMenuItem>Paste here</ContextMenuItem> */}
<ContextMenuItem
onSelect={() => order(node_id, "front")}
onSelect={() => editor.order(node_id, "front")}
className="text-xs"
>
Bring to front
<ContextMenuShortcut>{"]"}</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem
onSelect={() => order(node_id, "back")}
onSelect={() => editor.order(node_id, "back")}
className="text-xs"
>
Send to back
<ContextMenuShortcut>{"["}</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuSeparator />
{/* <ContextMenuItem>Add Container</ContextMenuItem> */}
<ContextMenuItem onSelect={change.toggleActive} className="text-xs">
<ContextMenuItem
onSelect={() => editor.toggleNodeActive(node_id)}
className="text-xs"
>
Set Active/Inactive
<ContextMenuShortcut>{"⌘⇧H"}</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
fit([node_id], { margin: 64, animate: true });
editor.fit([node_id], { margin: 64, animate: true });
}}
className="text-xs"
>
Zoom to fit
<ContextMenuShortcut>{"⇧1"}</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem onSelect={change.toggleLocked} className="text-xs">
<ContextMenuItem
onSelect={() => editor.toggleNodeLocked(node_id)}
className="text-xs"
>
Lock/Unlock
<ContextMenuShortcut>{"⌘⇧L"}</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem
onSelect={() => {
deleteNode(node_id);
editor.deleteNode(node_id);
}}
className="text-xs"
>
Expand All @@ -273,37 +275,24 @@ function NodeHierarchyItemContextMenuWrapper({
}

export function NodeHierarchyList() {
const {
document,
mv,
select,
hoverNode,
toggleNodeLocked,
toggleNodeActive,
changeNodeName,
} = useDocument();

const { id, name, children, selection, hovered_node_id } = useCurrentScene();
const editor = useCurrentEditor();
const document_ctx = useEditorState(editor, (state) => state.document_ctx);

const expandedItems = useMemo(() => {
return children.filter(
(id) => (document.nodes[id] as grida.program.nodes.UnknwonNode).expanded
);
}, [id, children]);
const { id, name, children, selection, hovered_node_id } =
useCurrentSceneState();

// root item id must be "<root>"
const tree = useTree<grida.program.nodes.Node>({
rootItemId: "<root>",
canReorder: true,
initialState: {
expandedItems: expandedItems,
selectedItems: selection,
},
state: {
selectedItems: selection,
},
setSelectedItems: (items) => {
select(items as string[]);
editor.select(items as string[]);
},
getItemName: (item) => {
if (item.getId() === "<root>") {
Expand All @@ -320,21 +309,18 @@ export function NodeHierarchyList() {
const target_id = target.item.getId();
const index =
"insertionIndex" in target ? target.insertionIndex : undefined;
mv(ids, target_id, index);
editor.mv(ids, target_id, index);
},
indent: 6,
dataLoader: {
getItem(itemId) {
return document.nodes[itemId];
return editor.state.document.nodes[itemId];
},
getChildren: (itemId) => {
if (itemId === "<root>") {
return children;
}
const node = document.nodes[itemId];
return (
(node as grida.program.nodes.i.IChildrenReference)?.children || []
);
return editor.state.document_ctx.__ctx_nid_to_children_ids[itemId];
},
},
features: [
Expand All @@ -347,7 +333,7 @@ export function NodeHierarchyList() {

useEffect(() => {
tree.rebuildTree();
}, [document]);
}, [document_ctx]);

return (
<Tree tree={tree} indent={6}>
Expand All @@ -373,10 +359,10 @@ export function NodeHierarchyList() {
item={item}
className="w-full h-7 max-h-7 py-0.5"
onPointerEnter={() => {
hoverNode(node.id, "enter");
editor.hoverNode(node.id, "enter");
}}
onPointerLeave={() => {
hoverNode(node.id, "leave");
editor.hoverNode(node.id, "leave");
}}
>
<TreeItemLabel
Expand All @@ -397,7 +383,7 @@ export function NodeHierarchyList() {
isRenaming={isRenaming}
initialValue={node.name}
onValueCommit={(name) => {
changeNodeName(node.id, name);
editor.changeNodeName(node.id, name);
tree.abortRenaming();
}}
className="px-1 py-0.5 font-normal text-[11px]"
Expand All @@ -411,7 +397,7 @@ export function NodeHierarchyList() {
<button
onClick={(e) => {
e.stopPropagation();
toggleNodeLocked(node.id);
editor.toggleNodeLocked(node.id);
}}
>
{node.locked ? (
Expand All @@ -423,7 +409,7 @@ export function NodeHierarchyList() {
<button
onClick={(e) => {
e.stopPropagation();
toggleNodeActive(node.id);
editor.toggleNodeActive(node.id);
}}
>
{node.active ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import React, { useState } from "react";
import {
useDocument,
useDocumentState,
StandaloneRootNodeContent,
StandaloneSceneBackground,
type StandaloneDocumentContentProps,
Expand All @@ -22,7 +22,7 @@ import {
} from "@radix-ui/react-icons";
import { toast } from "sonner";
import { useHotkeys } from "react-hotkeys-hook";
import { useCurrentScene } from "@/grida-canvas-react/provider";
import { useCurrentSceneState } from "@/grida-canvas-react/provider";
import Resizable from "./resizable";
import ErrorBoundary from "@/scaffolds/playground-canvas/error-boundary";
import { Input } from "@/components/ui/input";
Expand All @@ -44,8 +44,8 @@ const Context = React.createContext<{
export function PreviewProvider({
children,
}: React.PropsWithChildren<StandaloneDocumentContentProps>) {
const { document, document_ctx } = useDocument();
const scene = useCurrentScene();
const { document, document_ctx } = useDocumentState();
const scene = useCurrentSceneState();
const [mode, setMode] = useState<"framed" | "fullscreen">("framed");
const [open, setOpen] = useState(false);
const [id, setId] = useState<string>();
Expand Down
Loading