Add transformer to note
This commit is contained in:
parent
59d46e1d27
commit
d1e62e850a
@ -20,10 +20,13 @@ import { Note as NoteType } from "../../types/Note";
|
|||||||
import {
|
import {
|
||||||
NoteChangeEventHandler,
|
NoteChangeEventHandler,
|
||||||
NoteDragEventHandler,
|
NoteDragEventHandler,
|
||||||
|
NoteMenuCloseEventHandler,
|
||||||
NoteMenuOpenEventHandler,
|
NoteMenuOpenEventHandler,
|
||||||
} from "../../types/Events";
|
} from "../../types/Events";
|
||||||
import { Map } from "../../types/Map";
|
import { Map } from "../../types/Map";
|
||||||
|
|
||||||
|
import Transformer from "./Transformer";
|
||||||
|
|
||||||
const defaultFontSize = 16;
|
const defaultFontSize = 16;
|
||||||
|
|
||||||
type NoteProps = {
|
type NoteProps = {
|
||||||
@ -31,10 +34,12 @@ type NoteProps = {
|
|||||||
map: Map | null;
|
map: Map | null;
|
||||||
onNoteChange?: NoteChangeEventHandler;
|
onNoteChange?: NoteChangeEventHandler;
|
||||||
onNoteMenuOpen?: NoteMenuOpenEventHandler;
|
onNoteMenuOpen?: NoteMenuOpenEventHandler;
|
||||||
|
onNoteMenuClose?: NoteMenuCloseEventHandler;
|
||||||
draggable: boolean;
|
draggable: boolean;
|
||||||
onNoteDragStart?: NoteDragEventHandler;
|
onNoteDragStart?: NoteDragEventHandler;
|
||||||
onNoteDragEnd?: NoteDragEventHandler;
|
onNoteDragEnd?: NoteDragEventHandler;
|
||||||
fadeOnHover: boolean;
|
fadeOnHover: boolean;
|
||||||
|
selected: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
function Note({
|
function Note({
|
||||||
@ -42,10 +47,12 @@ function Note({
|
|||||||
map,
|
map,
|
||||||
onNoteChange,
|
onNoteChange,
|
||||||
onNoteMenuOpen,
|
onNoteMenuOpen,
|
||||||
|
onNoteMenuClose,
|
||||||
draggable,
|
draggable,
|
||||||
onNoteDragStart,
|
onNoteDragStart,
|
||||||
onNoteDragEnd,
|
onNoteDragEnd,
|
||||||
fadeOnHover,
|
fadeOnHover,
|
||||||
|
selected,
|
||||||
}: NoteProps) {
|
}: NoteProps) {
|
||||||
const userId = useUserId();
|
const userId = useUserId();
|
||||||
|
|
||||||
@ -173,6 +180,30 @@ function Note({
|
|||||||
|
|
||||||
const textRef = useRef<Konva.Text>(null);
|
const textRef = useRef<Konva.Text>(null);
|
||||||
|
|
||||||
|
const noteRef = useRef<Konva.Group>(null);
|
||||||
|
const [isTransforming, setIsTransforming] = useState(false);
|
||||||
|
function handleTransformStart() {
|
||||||
|
setIsTransforming(true);
|
||||||
|
onNoteMenuClose?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTransformEnd(event: Konva.KonvaEventObject<Event>) {
|
||||||
|
if (noteRef.current) {
|
||||||
|
const sizeChange = event.target.scaleX();
|
||||||
|
const rotation = event.target.rotation();
|
||||||
|
onNoteChange?.({
|
||||||
|
[note.id]: {
|
||||||
|
size: note.size * sizeChange,
|
||||||
|
rotation: rotation,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
onNoteMenuOpen?.(note.id, noteRef.current);
|
||||||
|
noteRef.current.scaleX(1);
|
||||||
|
noteRef.current.scaleY(1);
|
||||||
|
}
|
||||||
|
setIsTransforming(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Animate to new note positions if edited by others
|
// Animate to new note positions if edited by others
|
||||||
const noteX = note.x * mapWidth;
|
const noteX = note.x * mapWidth;
|
||||||
const noteY = note.y * mapHeight;
|
const noteY = note.y * mapHeight;
|
||||||
@ -194,6 +225,7 @@ function Note({
|
|||||||
const noteName = `note${note.locked ? "-locked" : ""}`;
|
const noteName = `note${note.locked ? "-locked" : ""}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<animated.Group
|
<animated.Group
|
||||||
{...props}
|
{...props}
|
||||||
id={note.id}
|
id={note.id}
|
||||||
@ -201,6 +233,7 @@ function Note({
|
|||||||
onTap={handleClick}
|
onTap={handleClick}
|
||||||
width={noteWidth}
|
width={noteWidth}
|
||||||
height={note.textOnly ? undefined : noteHeight}
|
height={note.textOnly ? undefined : noteHeight}
|
||||||
|
rotation={note.rotation}
|
||||||
offsetX={noteWidth / 2}
|
offsetX={noteWidth / 2}
|
||||||
offsetY={noteHeight / 2}
|
offsetY={noteHeight / 2}
|
||||||
draggable={draggable}
|
draggable={draggable}
|
||||||
@ -215,6 +248,7 @@ function Note({
|
|||||||
onMouseLeave={handlePointerLeave}
|
onMouseLeave={handlePointerLeave}
|
||||||
opacity={note.visible ? noteOpacity : 0.5}
|
opacity={note.visible ? noteOpacity : 0.5}
|
||||||
name={noteName}
|
name={noteName}
|
||||||
|
ref={noteRef}
|
||||||
>
|
>
|
||||||
{!note.textOnly && (
|
{!note.textOnly && (
|
||||||
<Rect
|
<Rect
|
||||||
@ -250,6 +284,14 @@ function Note({
|
|||||||
{/* Use an invisible text block to work out text sizing */}
|
{/* Use an invisible text block to work out text sizing */}
|
||||||
<Text visible={false} ref={textRef} text={note.text} wrap="none" />
|
<Text visible={false} ref={textRef} text={note.text} wrap="none" />
|
||||||
</animated.Group>
|
</animated.Group>
|
||||||
|
<Transformer
|
||||||
|
active={(!note.locked && selected) || isTransforming}
|
||||||
|
nodeRef={noteRef}
|
||||||
|
onTransformEnd={handleTransformEnd}
|
||||||
|
onTransformStart={handleTransformStart}
|
||||||
|
gridScale={map?.grid.measurement.scale || ""}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ function Transformer({
|
|||||||
if (movingAnchor === "rotater") {
|
if (movingAnchor === "rotater") {
|
||||||
text.text(`${node.rotation().toFixed(0)}°`);
|
text.text(`${node.rotation().toFixed(0)}°`);
|
||||||
} else {
|
} else {
|
||||||
const nodeRect = node.getClientRect();
|
const nodeRect = node.getClientRect({ skipShadow: true });
|
||||||
const nodeScale = Vector2.divide(
|
const nodeScale = Vector2.divide(
|
||||||
{ x: nodeRect.width, y: nodeRect.height },
|
{ x: nodeRect.width, y: nodeRect.height },
|
||||||
gridCellAbsoluteSize
|
gridCellAbsoluteSize
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Box, Flex, Text, IconButton } from "theme-ui";
|
import { Box, Flex, IconButton } from "theme-ui";
|
||||||
import Konva from "konva";
|
import Konva from "konva";
|
||||||
|
|
||||||
import Slider from "../Slider";
|
|
||||||
import TextareaAutosize from "../TextareaAutoSize";
|
import TextareaAutosize from "../TextareaAutoSize";
|
||||||
|
|
||||||
import MapMenu from "../map/MapMenu";
|
import MapMenu from "../map/MapMenu";
|
||||||
@ -27,8 +26,6 @@ import {
|
|||||||
import { Note } from "../../types/Note";
|
import { Note } from "../../types/Note";
|
||||||
import { Map } from "../../types/Map";
|
import { Map } from "../../types/Map";
|
||||||
|
|
||||||
const defaultNoteMaxSize = 6;
|
|
||||||
|
|
||||||
type NoteMenuProps = {
|
type NoteMenuProps = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onRequestClose: RequestCloseEventHandler;
|
onRequestClose: RequestCloseEventHandler;
|
||||||
@ -50,12 +47,10 @@ function NoteMenu({
|
|||||||
|
|
||||||
const wasOpen = usePrevious(isOpen);
|
const wasOpen = usePrevious(isOpen);
|
||||||
|
|
||||||
const [noteMaxSize, setNoteMaxSize] = useState(defaultNoteMaxSize);
|
|
||||||
const [menuLeft, setMenuLeft] = useState(0);
|
const [menuLeft, setMenuLeft] = useState(0);
|
||||||
const [menuTop, setMenuTop] = useState(0);
|
const [menuTop, setMenuTop] = useState(0);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen && !wasOpen && note) {
|
if (isOpen && !wasOpen && note) {
|
||||||
setNoteMaxSize(Math.max(note.size, defaultNoteMaxSize));
|
|
||||||
// Update menu position
|
// Update menu position
|
||||||
if (noteNode) {
|
if (noteNode) {
|
||||||
const nodeRect = noteNode.getClientRect();
|
const nodeRect = noteNode.getClientRect();
|
||||||
@ -64,8 +59,8 @@ function NoteMenu({
|
|||||||
const mapRect = mapElement.getBoundingClientRect();
|
const mapRect = mapElement.getBoundingClientRect();
|
||||||
// Center X for the menu which is 156px wide
|
// Center X for the menu which is 156px wide
|
||||||
setMenuLeft(mapRect.left + nodeRect.x + nodeRect.width / 2 - 156 / 2);
|
setMenuLeft(mapRect.left + nodeRect.x + nodeRect.width / 2 - 156 / 2);
|
||||||
// Y 12px from the bottom
|
// Y 20px from the bottom
|
||||||
setMenuTop(mapRect.top + nodeRect.y + nodeRect.height + 12);
|
setMenuTop(mapRect.top + nodeRect.y + nodeRect.height + 20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,11 +78,6 @@ function NoteMenu({
|
|||||||
onNoteChange({ [note.id]: { color: color } });
|
onNoteChange({ [note.id]: { color: color } });
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSizeChange(event: React.ChangeEvent<HTMLInputElement>) {
|
|
||||||
const newSize = parseFloat(event.target.value);
|
|
||||||
note && onNoteChange({ [note.id]: { size: newSize } });
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleVisibleChange() {
|
function handleVisibleChange() {
|
||||||
note && onNoteChange({ [note.id]: { visible: !note.visible } });
|
note && onNoteChange({ [note.id]: { visible: !note.visible } });
|
||||||
}
|
}
|
||||||
@ -198,24 +188,6 @@ function NoteMenu({
|
|||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
<Flex sx={{ alignItems: "center" }}>
|
|
||||||
<Text
|
|
||||||
as="label"
|
|
||||||
variant="body2"
|
|
||||||
sx={{ width: "40%", fontSize: "16px" }}
|
|
||||||
p={1}
|
|
||||||
>
|
|
||||||
Size:
|
|
||||||
</Text>
|
|
||||||
<Slider
|
|
||||||
value={(note && note.size) || 1}
|
|
||||||
onChange={handleSizeChange}
|
|
||||||
step={0.5}
|
|
||||||
min={0.5}
|
|
||||||
max={noteMaxSize}
|
|
||||||
mr={1}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
{/* Only show hide and lock token actions to map owners */}
|
{/* Only show hide and lock token actions to map owners */}
|
||||||
{map && map.owner === userId && (
|
{map && map.owner === userId && (
|
||||||
<Flex sx={{ alignItems: "center", justifyContent: "space-around" }}>
|
<Flex sx={{ alignItems: "center", justifyContent: "space-around" }}>
|
||||||
|
@ -18,8 +18,6 @@ import { Map } from "../../types/Map";
|
|||||||
import { Note as NoteType } from "../../types/Note";
|
import { Note as NoteType } from "../../types/Note";
|
||||||
import {
|
import {
|
||||||
NoteCreateEventHander,
|
NoteCreateEventHander,
|
||||||
NoteChangeEventHandler,
|
|
||||||
NoteDragEventHandler,
|
|
||||||
NoteMenuOpenEventHandler,
|
NoteMenuOpenEventHandler,
|
||||||
} from "../../types/Events";
|
} from "../../types/Events";
|
||||||
|
|
||||||
@ -29,26 +27,16 @@ type MapNoteProps = {
|
|||||||
map: Map | null;
|
map: Map | null;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
onNoteCreate: NoteCreateEventHander;
|
onNoteCreate: NoteCreateEventHander;
|
||||||
onNoteChange: NoteChangeEventHandler;
|
|
||||||
notes: NoteType[];
|
|
||||||
onNoteMenuOpen: NoteMenuOpenEventHandler;
|
onNoteMenuOpen: NoteMenuOpenEventHandler;
|
||||||
draggable: boolean;
|
children: React.ReactNode;
|
||||||
onNoteDragStart: NoteDragEventHandler;
|
|
||||||
onNoteDragEnd: NoteDragEventHandler;
|
|
||||||
fadeOnHover: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function NoteTool({
|
function NoteTool({
|
||||||
map,
|
map,
|
||||||
active,
|
active,
|
||||||
onNoteCreate,
|
onNoteCreate,
|
||||||
onNoteChange,
|
|
||||||
notes,
|
|
||||||
onNoteMenuOpen,
|
onNoteMenuOpen,
|
||||||
draggable,
|
children,
|
||||||
onNoteDragStart,
|
|
||||||
onNoteDragEnd,
|
|
||||||
fadeOnHover,
|
|
||||||
}: MapNoteProps) {
|
}: MapNoteProps) {
|
||||||
const interactionEmitter = useInteractionEmitter();
|
const interactionEmitter = useInteractionEmitter();
|
||||||
const userId = useUserId();
|
const userId = useUserId();
|
||||||
@ -101,6 +89,7 @@ function NoteTool({
|
|||||||
locked: false,
|
locked: false,
|
||||||
color: "yellow",
|
color: "yellow",
|
||||||
textOnly: false,
|
textOnly: false,
|
||||||
|
rotation: 0,
|
||||||
});
|
});
|
||||||
setIsBrushDown(true);
|
setIsBrushDown(true);
|
||||||
}
|
}
|
||||||
@ -147,21 +136,11 @@ function NoteTool({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Group id="notes">
|
<Group id="notes">
|
||||||
{notes.map((note) => (
|
{children}
|
||||||
<Note
|
|
||||||
note={note}
|
|
||||||
map={map}
|
|
||||||
key={note.id}
|
|
||||||
onNoteMenuOpen={onNoteMenuOpen}
|
|
||||||
draggable={draggable && !note.locked}
|
|
||||||
onNoteChange={onNoteChange}
|
|
||||||
onNoteDragStart={onNoteDragStart}
|
|
||||||
onNoteDragEnd={onNoteDragEnd}
|
|
||||||
fadeOnHover={fadeOnHover}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
<Group ref={creatingNoteRef}>
|
<Group ref={creatingNoteRef}>
|
||||||
{isBrushDown && noteData && <Note note={noteData} map={map} />}
|
{isBrushDown && noteData && (
|
||||||
|
<Note note={noteData} map={map} selected={false} />
|
||||||
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import Konva from "konva";
|
import Konva from "konva";
|
||||||
import { KonvaEventObject } from "konva/lib/Node";
|
import { KonvaEventObject } from "konva/lib/Node";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import Note from "../components/konva/Note";
|
||||||
import NoteDragOverlay from "../components/note/NoteDragOverlay";
|
import NoteDragOverlay from "../components/note/NoteDragOverlay";
|
||||||
import NoteMenu from "../components/note/NoteMenu";
|
import NoteMenu from "../components/note/NoteMenu";
|
||||||
import NoteTool from "../components/tools/NoteTool";
|
import NoteTool from "../components/tools/NoteTool";
|
||||||
@ -12,7 +13,11 @@ import {
|
|||||||
} from "../types/Events";
|
} from "../types/Events";
|
||||||
import { Map, MapToolId } from "../types/Map";
|
import { Map, MapToolId } from "../types/Map";
|
||||||
import { MapState } from "../types/MapState";
|
import { MapState } from "../types/MapState";
|
||||||
import { Note, NoteDraggingOptions, NoteMenuOptions } from "../types/Note";
|
import {
|
||||||
|
Note as NoteType,
|
||||||
|
NoteDraggingOptions,
|
||||||
|
NoteMenuOptions,
|
||||||
|
} from "../types/Note";
|
||||||
|
|
||||||
function useMapNotes(
|
function useMapNotes(
|
||||||
map: Map | null,
|
map: Map | null,
|
||||||
@ -37,6 +42,10 @@ function useMapNotes(
|
|||||||
setIsNoteMenuOpen(true);
|
setIsNoteMenuOpen(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleNoteMenuClose() {
|
||||||
|
setIsNoteMenuOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
function handleNoteDragStart(_: KonvaEventObject<DragEvent>, noteId: string) {
|
function handleNoteDragStart(_: KonvaEventObject<DragEvent>, noteId: string) {
|
||||||
setNoteDraggingOptions({ dragging: true, noteId });
|
setNoteDraggingOptions({ dragging: true, noteId });
|
||||||
}
|
}
|
||||||
@ -56,29 +65,43 @@ function useMapNotes(
|
|||||||
map={map}
|
map={map}
|
||||||
active={selectedToolId === "note"}
|
active={selectedToolId === "note"}
|
||||||
onNoteCreate={onNoteCreate}
|
onNoteCreate={onNoteCreate}
|
||||||
onNoteChange={onNoteChange}
|
onNoteMenuOpen={handleNoteMenuOpen}
|
||||||
notes={
|
>
|
||||||
mapState
|
{(mapState
|
||||||
? Object.values(mapState.notes).sort((a, b) =>
|
? Object.values(mapState.notes).sort((a, b) =>
|
||||||
sortNotes(a, b, noteDraggingOptions)
|
sortNotes(a, b, noteDraggingOptions)
|
||||||
)
|
)
|
||||||
: []
|
: []
|
||||||
}
|
).map((note) => (
|
||||||
|
<Note
|
||||||
|
note={note}
|
||||||
|
map={map}
|
||||||
|
key={note.id}
|
||||||
onNoteMenuOpen={handleNoteMenuOpen}
|
onNoteMenuOpen={handleNoteMenuOpen}
|
||||||
|
onNoteMenuClose={handleNoteMenuClose}
|
||||||
draggable={
|
draggable={
|
||||||
allowNoteEditing &&
|
allowNoteEditing &&
|
||||||
(selectedToolId === "note" || selectedToolId === "move")
|
(selectedToolId === "note" || selectedToolId === "move") &&
|
||||||
|
!note.locked
|
||||||
}
|
}
|
||||||
|
onNoteChange={onNoteChange}
|
||||||
onNoteDragStart={handleNoteDragStart}
|
onNoteDragStart={handleNoteDragStart}
|
||||||
onNoteDragEnd={handleNoteDragEnd}
|
onNoteDragEnd={handleNoteDragEnd}
|
||||||
fadeOnHover={selectedToolId === "drawing"}
|
fadeOnHover={selectedToolId === "drawing"}
|
||||||
|
selected={
|
||||||
|
!!noteMenuOptions &&
|
||||||
|
isNoteMenuOpen &&
|
||||||
|
noteMenuOptions.noteId === note.id
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
))}
|
||||||
|
</NoteTool>
|
||||||
);
|
);
|
||||||
|
|
||||||
const noteMenu = (
|
const noteMenu = (
|
||||||
<NoteMenu
|
<NoteMenu
|
||||||
isOpen={isNoteMenuOpen}
|
isOpen={isNoteMenuOpen}
|
||||||
onRequestClose={() => setIsNoteMenuOpen(false)}
|
onRequestClose={handleNoteMenuClose}
|
||||||
onNoteChange={onNoteChange}
|
onNoteChange={onNoteChange}
|
||||||
note={noteMenuOptions && mapState?.notes[noteMenuOptions.noteId]}
|
note={noteMenuOptions && mapState?.notes[noteMenuOptions.noteId]}
|
||||||
noteNode={noteMenuOptions?.noteNode}
|
noteNode={noteMenuOptions?.noteNode}
|
||||||
@ -100,8 +123,8 @@ function useMapNotes(
|
|||||||
export default useMapNotes;
|
export default useMapNotes;
|
||||||
|
|
||||||
function sortNotes(
|
function sortNotes(
|
||||||
a: Note,
|
a: NoteType,
|
||||||
b: Note,
|
b: NoteType,
|
||||||
noteDraggingOptions?: NoteDraggingOptions
|
noteDraggingOptions?: NoteDraggingOptions
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
|
@ -46,6 +46,7 @@ export type NoteMenuOpenEventHandler = (
|
|||||||
noteId: string,
|
noteId: string,
|
||||||
noteNode: Konva.Node
|
noteNode: Konva.Node
|
||||||
) => void;
|
) => void;
|
||||||
|
export type NoteMenuCloseEventHandler = () => void;
|
||||||
export type NoteDragEventHandler = (
|
export type NoteDragEventHandler = (
|
||||||
event: Konva.KonvaEventObject<DragEvent>,
|
event: Konva.KonvaEventObject<DragEvent>,
|
||||||
noteId: string
|
noteId: string
|
||||||
|
@ -13,6 +13,7 @@ export type Note = {
|
|||||||
visible: boolean;
|
visible: boolean;
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
rotation: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NoteMenuOptions = {
|
export type NoteMenuOptions = {
|
||||||
|
@ -834,9 +834,22 @@ export const versions: Record<number, VersionCallback> = {
|
|||||||
_uncommittedChanges: null,
|
_uncommittedChanges: null,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// v1.10.0 - Add rotation to notes
|
||||||
|
37(v, onUpgrade) {
|
||||||
|
v.stores({}).upgrade((tx) => {
|
||||||
|
onUpgrade?.(37);
|
||||||
|
tx.table("states")
|
||||||
|
.toCollection()
|
||||||
|
.modify((state) => {
|
||||||
|
for (let id in state.notes) {
|
||||||
|
state.notes[id].rotation = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const latestVersion = 36;
|
export const latestVersion = 37;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load versions onto a database up to a specific version number
|
* Load versions onto a database up to a specific version number
|
||||||
|
@ -40,6 +40,9 @@ export const NoteSchema: JSONSchemaType<Note> = {
|
|||||||
y: {
|
y: {
|
||||||
type: "number",
|
type: "number",
|
||||||
},
|
},
|
||||||
|
rotation: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
required: [
|
required: [
|
||||||
"color",
|
"color",
|
||||||
@ -53,6 +56,7 @@ export const NoteSchema: JSONSchemaType<Note> = {
|
|||||||
"visible",
|
"visible",
|
||||||
"x",
|
"x",
|
||||||
"y",
|
"y",
|
||||||
|
"rotation",
|
||||||
],
|
],
|
||||||
type: "object",
|
type: "object",
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user