diff --git a/apps/docs/.storybook/manager.ts b/apps/docs/.storybook/manager.ts index 0e27bf0..d8f1774 100644 --- a/apps/docs/.storybook/manager.ts +++ b/apps/docs/.storybook/manager.ts @@ -6,6 +6,7 @@ addons.setConfig({ base: "dark", brandTitle: "@noowah/content-builder", brandImage: "https://noowah.vercel.app/favicon-32x32.png", - brandTarget: "_self", + brandUrl: "https://github.com/henrynoowah/content-builder", + brandTarget: "_blank", }), }); diff --git a/apps/docs/data/test-data.ts b/apps/docs/data/test-data.ts index d2307d0..df7e5f5 100644 --- a/apps/docs/data/test-data.ts +++ b/apps/docs/data/test-data.ts @@ -99,6 +99,7 @@ export const data: Page = { display: "grid", position: "relative", gridTemplateColumns: "1fr 1fr", + gridTemplateRows: "1fr 1fr 1fr", }, style_mobile: { display: "grid", @@ -112,7 +113,7 @@ export const data: Page = { position: "relative", display: "block", width: "100%", - height: "420px", + height: "100%", }, style_mobile: { width: "100%", diff --git a/apps/docs/stories/editor.stories.tsx b/apps/docs/stories/editor.stories.tsx index 4a93ad9..639d6d9 100644 --- a/apps/docs/stories/editor.stories.tsx +++ b/apps/docs/stories/editor.stories.tsx @@ -5,7 +5,6 @@ import { data } from "../data/test-data"; const meta: Meta = { title: "UI/Editor", component: Editor, - decorators: [(Story) => ], tags: ["autodocs"], parameters: { layout: "full" }, }; diff --git a/apps/docs/stories/renderer.stories.tsx b/apps/docs/stories/renderer.stories.tsx index 8e1d4e4..911de2b 100644 --- a/apps/docs/stories/renderer.stories.tsx +++ b/apps/docs/stories/renderer.stories.tsx @@ -1,13 +1,10 @@ import type { Meta, StoryObj } from "@storybook/react"; import Renderer from "@noowah/content-builder/renderer"; +import { data } from "../data/test-data"; const meta: Meta = { title: "UI/Renderer", - component: (props) => ( -
- , -
- ), + component: Renderer, tags: ["autodocs"], parameters: { layout: "full" }, // parameters: { layout: "centered" }, @@ -19,297 +16,6 @@ type Story = StoryObj; export const Default: Story = { args: { - // children: (props) => , - data: { - id: "page_1", - title: "About Us", - slug: "template", - created_at: "2023-08-10T14:22:33.000Z", - updated_at: "2024-07-11T12:11:22.000Z", - url: "/template", - seo: { - title: "About Our Company", - description: "Learn more about our company, mission, and values.", - keywords: ["company", "mission", "values"], - }, - style: { - width: "100%", - maxWidth: "100%", - display: "flex", - flexDirection: "column", - gap: "24px", - }, - sections: [ - { - id: "section-1", - order: 1, - style: { - width: "100%", - maxWidth: "100%", - display: "block", - position: "relative", - height: "420px", - overflow: "hidden", - }, - style_mobile: { - width: "100%", - maxWidth: "100%", - display: "block", - position: "relative", - height: "420px", - overflow: "hidden", - }, - blocks: [ - { - type: "image", - id: "section-1-block-1", - image: { - src: "https://images.pexels.com/photos/3381115/pexels-photo-3381115.jpeg", - width: 1920, - height: 748, - style: { - width: "100%", - height: "100%", - objectFit: "cover", - backgroundColor: "magenta", - }, - }, - style: { - width: "100%", - height: "100%", - backgroundColor: "gray", - position: "absolute", - }, - style_mobile: { - width: "100%", - height: "100%", - backgroundColor: "gray", - position: "absolute", - overflow: "hidden", - }, - }, - { - id: "section-1-block-2", - type: "html", - style: { - position: "absolute", - display: "block", - width: "80%", - height: "fit-content", - maxHeight: "100%", - top: "10%", - left: "10%", - padding: "24px", - backgroundColor: "gray", - }, - content: - "

Heading 1

Lorem ipsum odor amet, consectetuer adipiscing elit. Phasellus etiam praesent lacus, commodo sollicitudin iaculis. Nostra torquent odio lacinia massa hac. Dignissim consequat maecenas scelerisque sem laoreet felis maecenas efficitur. Malesuada mi bibendum a sem himenaeos dui in faucibus finibus. Tristique enim lacinia vel dignissim torquent condimentum dis curae pellentesque. Egestas ridiculus maecenas phasellus ornare gravida, viverra ultrices nisl accumsan. Nunc odio mus pulvinar nam conubia dolor


", - images: [], - }, - ], - }, - { - id: "section-2", - order: 1, - style: { - width: "1280px", - maxWidth: "100%", - paddingTop: "24px", - margin: "auto", - display: "grid", - position: "relative", - gridTemplateColumns: "1fr 1fr", - }, - style_mobile: { - display: "grid", - gridTemplateColumns: "1fr", - }, - blocks: [ - { - type: "image", - id: "section-2-block-1", - style: { - position: "relative", - display: "block", - width: "100%", - height: "420px", - }, - style_mobile: { - width: "100%", - height: "100%", - }, - image: { - src: "https://images.pexels.com/photos/20607063/pexels-photo-20607063/free-photo-of-close-up-of-the-facade-of-an-apartment-building-with-balconies.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1", - alt: "Our Team", - caption: "Meet Our Team", - style: { - position: "relative", - width: "100%", - height: "420px", - objectFit: "cover", - backgroundColor: "gray", - zIndex: -1, - }, - }, - images: [], - }, - { - id: "section-2-block-2", - type: "html", - style: { - position: "relative", - display: "block", - width: "100%", - height: "100%", - padding: "24px", - }, - content: - "

Heading 1

Lorem ipsum odor amet, consectetuer adipiscing elit. Phasellus etiam praesent lacus, commodo sollicitudin iaculis. Nostra torquent odio lacinia massa hac. Dignissim consequat maecenas scelerisque sem laoreet felis maecenas efficitur. Malesuada mi bibendum a sem himenaeos dui in faucibus finibus. Tristique enim lacinia vel dignissim torquent condimentum dis curae pellentesque. Egestas ridiculus maecenas phasellus ornare gravida, viverra ultrices nisl accumsan. Nunc odio mus pulvinar nam conubia dolor


", - images: [], - }, - { - id: "section-2-block-3", - type: "html", - style: { - width: "100%", - height: "100%", - position: "relative", - padding: "24px", - }, - content: - "

Sub Heading

Faucibus commodo sapien venenatis imperdiet torquent scelerisque. Phasellus convallis inceptos sapien posuere amet. Consectetur venenatis mus velit elit nam. Commodo porta quis ipsum, scelerisque class pharetra nisi felis. Curabitur a duis non consectetur id commodo tortor volutpat erat. Neque nam venenatis ante elementum purus ultricies maecenas finibus tempus. Et convallis maecenas nullam purus pharetra nullam.


Porta eros maximus elit aliquam enim ac posuere. Libero habitasse sed, nulla nulla ligula consequat. Congue placerat sagittis lacus tristique penatibus litora? Tincidunt justo senectus montes pulvinar ac. Sodales mauris vitae eu tortor scelerisque class nostra. Hendrerit tristique in consectetur per taciti himenaeos, convallis suspendisse libero. Bibendum platea facilisis potenti montes orci pharetra. Ante dapibus faucibus eget curae dapibus rutrum senectus mollis. Pulvinar netus consequat primis pretium ligula urna turpis.

", - images: [], - }, - { - id: "section-2-block-4", - type: "image", - style: { - position: "relative", - width: "100%", - height: "100%", - objectFit: "cover", - backgroundColor: "gray", - }, - image: { - src: "https://images.pexels.com/photos/63430/pexels-photo-63430.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1", - alt: "Our Team", - caption: "Meet Our Team", - style: { - position: "relative", - - width: "100%", - height: "420px", - objectFit: "cover", - backgroundColor: "gray", - }, - }, - images: [], - }, - ], - }, - // { - // id: "section-3", - // order: 1, - // style: { - // width: "1280px", - // maxWidth: "100%", - // margin: "auto", - // display: "grid", - // gridTemplateColumns: "repeat(2, minmax(0, 1fr))", - // gap: "16px", - // }, - // style_mobile: { - // gridTemplateColumns: "repeat(1, minmax(0, 1fr))", - // gap: "16px", - // }, - // blocks: [ - // { - // type: "gallery", - // id: "section-3-block-1", - // style: { - // width: "100%", - // height: "100%", - // position: "relative", - // objectFit: "contain", - // objectPosition: "center", - // }, - // images: [ - // { - // src: "https://images.pexels.com/photos/3381115/pexels-photo-3381115.jpeg", - // alt: "Image 1", - // caption: "Image 1 caption", - // }, - // { - // src: "https://images.pexels.com/photos/20607063/pexels-photo-20607063/free-photo-of-close-up-of-the-facade-of-an-apartment-building-with-balconies.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1", - // alt: "Image 2", - // caption: "Image 2 caption", - // }, - // ], - // }, - // { - // type: "html", - // id: "section-3-block-2", - // style: { - // position: "relative", - // }, - // content: - // "

Welcome to our company. We are dedicated to providing the best services...

", - // images: [], - // }, - // ], - // }, - // { - // id: "section-4", - // order: 1, - // style: { - // width: "1280px", - // maxWidth: "100%", - // margin: "auto", - // display: "grid", - // gridTemplateColumns: "repeat(2, minmax(0, 1fr))", - // gap: "16px", - // }, - // style_mobile: { - // gridTemplateColumns: "repeat(1, minmax(0, 1fr))", - // gap: "16px", - // }, - // blocks: [ - // { - // type: "html", - // id: "section-4-block-1", - // style: { - // position: "relative", - // }, - // content: - // "

Welcome to our company. We are dedicated to providing the best services...

", - // images: [], - // }, - // { - // type: "gallery", - // id: "section-4-block-2", - // style: { - // position: "relative", - // width: "100%", - // height: "100%", - // objectFit: "contain", - // objectPosition: "center", - // }, - // images: [ - // { - // src: "https://images.pexels.com/photos/3381115/pexels-photo-3381115.jpeg", - // alt: "Image 1", - // caption: "Image 1 caption", - // }, - // { - // src: "https://images.pexels.com/photos/20607063/pexels-photo-20607063/free-photo-of-close-up-of-the-facade-of-an-apartment-building-with-balconies.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1", - // alt: "Image 2", - // caption: "Image 2 caption", - // }, - // ], - // }, - // ], - // }, - ], - }, + data, }, }; diff --git a/packages/ui/src/components/editor/Editor.tsx b/packages/ui/src/components/editor/Editor.tsx index ba29ceb..ef3adf1 100644 --- a/packages/ui/src/components/editor/Editor.tsx +++ b/packages/ui/src/components/editor/Editor.tsx @@ -45,7 +45,7 @@ const Editor = ({ view = "web", data, onSubmit, children }: EditorProps) => { values: data, }); - const { handleSubmit, control, setValue, watch } = methods; + const { handleSubmit, control, setValue } = methods; const { fields: sections, diff --git a/packages/ui/src/components/editor/block-editor/BlockEditor.tsx b/packages/ui/src/components/editor/block-editor/BlockEditor.tsx index b5ef793..d2211d6 100644 --- a/packages/ui/src/components/editor/block-editor/BlockEditor.tsx +++ b/packages/ui/src/components/editor/block-editor/BlockEditor.tsx @@ -15,16 +15,14 @@ interface BlockProps { block: Block; onClick?: (block: Block) => void; onChange?: (block: Block) => void; - draggable?: boolean; resizable?: boolean; } const BlockEditor = forwardRef( - ( - { block, onChange, bounds, onClick, draggable = true, resizable = true }, - _ - ) => { + ({ block, onChange, bounds, onClick }, _) => { const onDragEnd = ({ delta, active, over, collisions }: DragEndEvent) => { + console.log(active.data); + console.log("delta", delta); console.log("active", active); console.log("over", over); @@ -55,6 +53,18 @@ const BlockEditor = forwardRef( const leftPercent = (leftPx / bounds.offsetWidth) * 100; const topPercent = (topPx / bounds.offsetHeight) * 100; + console.log(active.id, over?.id); + if (active.id !== over?.id && block.style?.position !== "absolute") { + onChange?.({ + ...block, + style: { + ...block.style, + left: `${leftPercent.toFixed(0)}%`, + top: `${topPercent.toFixed(0)}%`, + position: "absolute", + }, + }); + } onChange?.({ ...block, style: { @@ -66,38 +76,48 @@ const BlockEditor = forwardRef( }; return ( - - { - onClick?.(block); - }} - onResize={(style) => { - onChange?.({ ...block, style: { ...block.style, ...style } }); - }} - draggable={draggable} - resizable={resizable} - isContentInteractive={block.type === "html"} - > - {block.type === "html" && ( - onChange?.({ ...block, content: value })} - /> - )} - {block.type === "gallery" && } + // + // { + // onClick?.(block); + // }} + // onResize={(style) => { + // onChange?.({ ...block, style: { ...block.style, ...style } }); + // }} + // draggable={draggable} + // resizable={resizable} + // isContentInteractive={block.type === "html"} + // > + <> + {block.type === "html" && ( + onChange?.({ ...block, content: value })} + /> + )} + {block.type === "gallery" && } - {block.type === "image" && ( - onChange?.({ ...block })} - /> - )} - - + {block.type === "image" && ( + onChange?.({ ...block })} + /> + )} + + // + // ); } ); diff --git a/packages/ui/src/components/editor/plugins/settings/Settings.tsx b/packages/ui/src/components/editor/plugins/settings/Settings.tsx index a0dea77..9a65e43 100644 --- a/packages/ui/src/components/editor/plugins/settings/Settings.tsx +++ b/packages/ui/src/components/editor/plugins/settings/Settings.tsx @@ -1,6 +1,11 @@ import { Block, EditorContextProps, Section } from "@/types"; import { CSSProperties } from "react"; -import { FormProvider, useForm } from "react-hook-form"; +import { + Controller, + FormProvider, + useForm, + useFormContext, +} from "react-hook-form"; import { useEditorContext } from "../../Editor"; interface Params @@ -25,7 +30,7 @@ const SettingsTab = () => { }, }); - const { control, handleSubmit } = methods; + const { handleSubmit } = methods; const onSubmitHandler = (values: Params) => { if (values.selectedSection) { @@ -105,99 +110,70 @@ const SettingsTab = () => { )} - {/*
+
- ( - - )} - /> - ( - { - onChange?.(style); - }} - /> - )} - /> -
- -
-

{`${ - selectedSection?.id ?? "" - } ${selectedBlock ? `/ ${selectedBlock.id}` : ""}`}

- {selectedSection && ( - - )} +
-
- -
Block: {selectedBlock?.id}
- - - value ? ( - onChange?.(block)} - /> - ) : ( - <> - ) - } - /> - ( - { - onChange?.(style); - }} - /> - )} - /> -
*/} +
); }; -export default SettingsTab; +const SectionSetting = () => { + const { control } = useFormContext(); + return ( + ( + { + console.log(style); + if (style.display === "flex" || style.display === "grid") { + console.log( + section?.blocks.map((block) => ({ + ...block, + style: { + ...block.style, + position: "relative", + display: "block", + width: "100%", + height: "100%", + top: 0, + left: 0, + }, + })) + ); + onChange({ + ...section, + style, + blocks: + section?.blocks.map((block) => ({ + ...block, + style: { + ...block.style, + position: "relative", + display: "block", + width: "100%", + height: "100%", + top: 0, + left: 0, + }, + })) ?? [], + }); + } + }} + /> + )} + /> + ); +}; -const StyleSetting = ({ +const LayoutSetting = ({ value: style, onChange, }: { @@ -205,147 +181,160 @@ const StyleSetting = ({ onChange?: (style: CSSProperties) => void; }) => { return ( -
- {/* Layout */} -
-

Layout

+
+

Layout

+
+ + + + +
+ + {/* Alignment Controls */} +
+

Alignment

-
+
- {/* Alignment Controls */} -
-

Alignment

-
- - - -
+ {style?.display === "grid" && ( +
+ +
+ )} +
+ ); +}; - {style?.display === "grid" && ( -
- - -
- )} -
+export default SettingsTab; + +const StyleSetting = ({ + value: style, + onChange, +}: { + value?: CSSProperties; + onChange?: (style: CSSProperties) => void; +}) => { + return ( +
+ {/* Layout */} {/* Size Controls */}
diff --git a/packages/ui/src/components/editor/section-editor/SectionEditor.tsx b/packages/ui/src/components/editor/section-editor/SectionEditor.tsx index 4d92861..90d41a4 100644 --- a/packages/ui/src/components/editor/section-editor/SectionEditor.tsx +++ b/packages/ui/src/components/editor/section-editor/SectionEditor.tsx @@ -8,15 +8,12 @@ import { PointerSensor, rectIntersection, UniqueIdentifier, + useDraggable, + useDroppable, useSensor, useSensors, } from "@dnd-kit/core"; -import { - arraySwap, - // rectSwappingStrategy, - // SortableContext, - useSortable, -} from "@dnd-kit/sortable"; +import { arraySwap, useSortable } from "@dnd-kit/sortable"; import { CSS, getEventCoordinates } from "@dnd-kit/utilities"; import React, { forwardRef, @@ -34,8 +31,8 @@ import { Section, SectionEditor as SectionEditorContext, } from "../../../types"; - -// import { snapCenterToCursor } from "@dnd-kit/modifiers"; +import { restrictToParentElement } from "@dnd-kit/modifiers"; +import Resizable from "@/components/resizable"; const BlockEditor = lazy(() => import("../block-editor")); @@ -96,8 +93,55 @@ const SectionEditor = forwardRef( onSectionSelect(section); }; - const onDragEnd = ({ active, over }: DragEndEvent) => { - if (!over || active.id === over.id) return; + const onDragEnd = ({ delta, active, over }: DragEndEvent) => { + const block = blocks.find((x) => x.id === active.id) as Block; + if ( + !over || + active.id === over.id || + block.style?.position === "absolute" + ) { + const bounds = sectionRef.current; + + if (!bounds) return; + + // Get current position values as percentages + const currentLeft = block.style?.left?.toString() || "0"; + const currentTop = block.style?.top?.toString() || "0"; + + // Parse current values to pixels + let leftPx = currentLeft.includes("%") + ? (parseFloat(currentLeft) / 100) * bounds.offsetWidth + : parseInt(currentLeft); + let topPx = currentTop.includes("%") + ? (parseFloat(currentTop) / 100) * bounds.offsetHeight + : parseInt(currentTop); + + // Add delta to get new position in pixels + leftPx += delta.x; + topPx += delta.y; + + // Ensure position stays within bounds + leftPx = Math.max(0, Math.min(leftPx, bounds.offsetWidth)); + topPx = Math.max(0, Math.min(topPx, bounds.offsetHeight)); + + // Convert back to percentages + const leftPercent = (leftPx / bounds.offsetWidth) * 100; + const topPercent = (topPx / bounds.offsetHeight) * 100; + + update( + blocks.findIndex((x) => x.id === active.id), + { + ...block, + style: { + ...block.style, + left: `${leftPercent.toFixed(0)}%`, + top: `${topPercent.toFixed(0)}%`, + }, + } + ); + + return; + } const getPosition = (id: UniqueIdentifier) => blocks.findIndex((x) => x.id === id); @@ -203,19 +247,12 @@ const SectionEditor = forwardRef(
console.log("drag over", e)} onDragStart={onDragStart} onDragEnd={onDragEnd} - // measuring={{ - // draggable: { - // measure: (node) => { - // console.log("the measured node: ", node); - // console.log("children: ", node.children); - // return node.getBoundingClientRect(); - // }, - // }, - // }} > {blocks?.map((block, i) => { const css = ` @@ -231,35 +268,24 @@ const SectionEditor = forwardRef( return ( - - {section.style?.display === "grid" ? ( - { - onBlockSelect(block); - setSelectedBlock(block); - }} - > - { - onBlockSelect(block); - setSelectedBlock(block); - }} - onChange={(block) => { - update(i, block); - }} - draggable={false} - resizable={false} - /> - - ) : ( + { + onBlockSelect(block); + setSelectedBlock(block); + }} + onChange={(block) => { + update(i, block); + }} + isContentInteractive={block.type === "html"} + > { onBlockSelect(block); setSelectedBlock(block); @@ -267,17 +293,13 @@ const SectionEditor = forwardRef( onChange={(block) => { update(i, block); }} - selected={selectedBlock?.id === block.id} - section={section} - block={block} - bounds={sectionRef.current} /> - )} + ); })} - ( />
) : null} - + */}
); @@ -306,61 +328,69 @@ const SectionEditor = forwardRef( export default SectionEditor; -interface SortableContainerProps { +interface DraggableContainerProps { id: string; block: Block; children: React.ReactNode; onSelect?: (block: Block) => void; + onChange?: (block: Block) => void; + isContentInteractive?: boolean; } -const SortableContainer = forwardRef( - ({ id, block, children, onSelect }, ref) => { - const { - isDragging, - isSorting, - // over, - attributes, - listeners, - setNodeRef, - transform, - } = useSortable({ +const DraggableContainer = forwardRef( + ({ id, block, children, onSelect, onChange, isContentInteractive }, ref) => { + const { isDragging, attributes, listeners, setNodeRef, transform } = + useDraggable({ + id, + }); + + const { isOver, setNodeRef: setDroppableNodeRef } = useDroppable({ id, }); const style = { - opacity: isDragging ? 0.4 : 1, - transform: isSorting ? undefined : CSS.Translate.toString(transform), + opacity: isDragging || isOver ? 0.4 : 1, + transform: CSS.Translate.toString(transform), }; useImperativeHandle(ref, () => block); + const resizeRef = useRef(null); + return (
{ + setNodeRef(ref); + setDroppableNodeRef(ref); + resizeRef.current = ref; + }} style={{ ...style, }} onClick={() => { onSelect?.(block); }} + {...attributes} + {...listeners} + onPointerDown={(e) => { + if (isContentInteractive && e.currentTarget !== e.target) return; + e.currentTarget.style.cursor = "move"; + listeners?.onPointerDown?.(e); + }} > -
-
- ||| -
-
- {children} + { + onSelect?.(block); + }} + onResize={(style) => { + onChange?.({ ...block, style: { ...block.style, ...style } }); + }} + > + {children} +
); } diff --git a/packages/ui/src/components/resizable/Resizable.tsx b/packages/ui/src/components/resizable/Resizable.tsx index eaa6ae0..50b2fd8 100644 --- a/packages/ui/src/components/resizable/Resizable.tsx +++ b/packages/ui/src/components/resizable/Resizable.tsx @@ -1,19 +1,15 @@ -import { useDraggable } from "@dnd-kit/core"; -import { CSS } from "@dnd-kit/utilities"; import { CSSProperties, useEffect, useRef, useState } from "react"; const Resizable = ({ children, - id, data, onResize, onClick, draggable = true, resizable = true, - isContentInteractive = true, + resizeRef, }: { children: React.ReactNode; - id: string; data: Partial>; disabled?: boolean; onResize: (style: CSSProperties) => void; @@ -21,16 +17,12 @@ const Resizable = ({ draggable?: boolean; resizable?: boolean; isContentInteractive?: boolean; + resizeRef: React.RefObject; }) => { - const { attributes, listeners, setNodeRef, transform } = useDraggable({ - id, - disabled: !draggable, // Disable dragging while resizing - }); - const [isResizing, setIsResizing] = useState(false); const [activeHandle, setActiveHandle] = useState(null); const [isFocused, setIsFocused] = useState(false); - const resizeRef = useRef(null); + // const resizeRef = useRef(null); const startPos = useRef({ x: 0, y: 0 }); const startSize = useRef({ width: 0, height: 0, top: 0, left: 0 }); @@ -68,8 +60,10 @@ const Resizable = ({ const deltaX = e.clientX - startPos.current.x; const deltaY = e.clientY - startPos.current.y; - const parentWidth = resizeRef.current.parentElement?.clientWidth || 1; - const parentHeight = resizeRef.current.parentElement?.clientHeight || 1; + const parentWidth = + resizeRef.current.parentElement?.getBoundingClientRect().width || 1; + const parentHeight = + resizeRef.current.parentElement?.getBoundingClientRect().height || 1; // Convert current percentage values to pixels const currentStyle = data || {}; @@ -176,29 +170,14 @@ const Resizable = ({ }; }, [isResizing, activeHandle, data.width, data.height, data.left, data.top]); - const handleBorderRadius = (e: React.MouseEvent, direction: string) => { - e.preventDefault(); - e.stopPropagation(); - console.log(direction); - }; - return (
{ - setNodeRef(node); - resizeRef.current = node; - }} - {...attributes} - {...(!isResizing && isFocused && draggable && listeners)} onPointerDown={(e) => { onClick?.(data); setIsFocused(true); - if (!isContentInteractive) return listeners?.onPointerDown?.(e); if (e.currentTarget === e.target) { e.currentTarget.style.cursor = "move"; - listeners?.onPointerDown?.(e); } }} onBlur={(e) => { @@ -206,11 +185,6 @@ const Resizable = ({ setIsFocused(false); }} style={{ - transform: CSS.Transform.toString(transform), - width: data.width || "100%", - height: data.height || "auto", - left: data.left || "0%", - top: data.top || "0%", cursor: draggable ? "move" : "default", }} > diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts index 4b56859..c6c9670 100644 --- a/packages/ui/src/types.ts +++ b/packages/ui/src/types.ts @@ -41,7 +41,7 @@ type SectionEditor = { updateBlock: (i: number, block: Block) => void; }; -type BlockType = "html" | "image" | "gallery" | string; +type BlockType = "html" | "image" | "gallery" | "default" | string; type BlockImage = Partial< Pick