feat(layers): add layer management panel
This commit is contained in:
48
view/App.tsx
48
view/App.tsx
@@ -1,12 +1,12 @@
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import type { ImageStudioApp } from "@app/app";
|
||||
import { BottomControlsIsland } from "./BottomControlsIsland";
|
||||
import { CanvasViewport } from "./CanvasViewport";
|
||||
import { LayersSheet } from "./LayersSheet";
|
||||
import { ToolOverlay } from "./ToolOverlay";
|
||||
import { labelForTool } from "./toolLabels";
|
||||
import { resolveTransformTargetBounds } from "@editor/transform-targets";
|
||||
import { getSelectionSummary } from "./selectionSummary";
|
||||
import { resolveTransformTargetBounds, selectedTransformTarget } from "@editor/transform-targets";
|
||||
import { handleDeleteSelectionKey, keybindEventFromKeyboardEvent } from "@input/index";
|
||||
import { useAppState } from "./useAppState";
|
||||
import { useImageImport } from "./useImageImport";
|
||||
import { useViewportActivityIsland } from "./useViewportActivityIsland";
|
||||
@@ -22,10 +22,35 @@ export function App({ app }: AppProps) {
|
||||
const viewportActivityIsland = useViewportActivityIsland(state.editor.viewport);
|
||||
const imageImport = useImageImport(app.store);
|
||||
const [layersOpen, setLayersOpen] = useState(false);
|
||||
const selectionSummary = getSelectionSummary(state.document, state.editor.selection);
|
||||
const transformBounds = state.editor.transformSession
|
||||
? resolveTransformTargetBounds(state.document, state.editor.transformSession.target)
|
||||
: undefined;
|
||||
const transformTarget = state.editor.transformSession?.target ?? selectedTransformTarget(state.document, state.editor.selection);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
const target = event.target;
|
||||
const editableTarget =
|
||||
target instanceof HTMLElement &&
|
||||
(target.isContentEditable || target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement);
|
||||
|
||||
if (event.altKey || event.ctrlKey || event.metaKey || editableTarget) return;
|
||||
|
||||
if (event.key.toLowerCase() === "l") {
|
||||
setLayersOpen(true);
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
const consumed = handleDeleteSelectionKey({
|
||||
event: keybindEventFromKeyboardEvent(event),
|
||||
selection: app.store.getState().editor.selection,
|
||||
dispatch: app.store.dispatch,
|
||||
});
|
||||
if (consumed) event.preventDefault();
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||
}, [app.store]);
|
||||
const transformBounds = transformTarget ? resolveTransformTargetBounds(state.document, transformTarget) : undefined;
|
||||
|
||||
return (
|
||||
<main className="relative h-full overflow-hidden bg-background text-foreground">
|
||||
@@ -44,16 +69,15 @@ export function App({ app }: AppProps) {
|
||||
dispatch={app.store.dispatch}
|
||||
/>
|
||||
</div>
|
||||
<LayersSheet document={state.document} selection={state.editor.selection} open={layersOpen} onClose={() => setLayersOpen(false)} />
|
||||
<LayersSheet document={state.document} selection={state.editor.selection} open={layersOpen} dispatch={app.store.dispatch} onClose={() => setLayersOpen(false)} />
|
||||
<div className="absolute inset-x-0 bottom-4 z-10 flex justify-center">
|
||||
<BottomControlsIsland
|
||||
viewport={state.editor.viewport}
|
||||
visible={Boolean(transformBounds) || selectionSummary.type !== "none" || viewportActivityIsland.visible}
|
||||
visible={Boolean(transformBounds) || viewportActivityIsland.visible}
|
||||
action={viewportActivityIsland.action}
|
||||
selection={selectionSummary}
|
||||
transformBounds={transformBounds}
|
||||
transformBounds={viewportActivityIsland.visible ? undefined : transformBounds}
|
||||
transformTarget={viewportActivityIsland.visible ? undefined : transformTarget}
|
||||
dispatch={app.store.dispatch}
|
||||
onOpenLayers={() => setLayersOpen(true)}
|
||||
/>
|
||||
</div>
|
||||
<CanvasViewport store={app.store} />
|
||||
|
||||
Reference in New Issue
Block a user