craft.js icon indicating copy to clipboard operation
craft.js copied to clipboard

Passing events data with create ref

Open nickm89 opened this issue 4 years ago • 2 comments

@ankri @unloved

Hi guys, I followed a similar approach to make the user components dragged with an absolute position inside the editor. It works really well, but I am facing problems with setting a dynamic initial position as opposed to a static one when dragged from the left sidebar.

I tried various things including passing the pageX, pageY props from the toolbar component, something like:

<div onDragEnd={(event)  => setPosition({ x: event.clientX, y: event.clientY})} ref={(ref) => create(ref, <SimpleCheckBox  pageX={position.x} pageY={position.y} />)}>
  <Tooltip title="Checkbox" placement="right">
    <Item className="m-2 pb-2 cursor-pointer block" move>
      <Check />
    </Item>
  </Tooltip>
</div>

This sets the state correctly, but the component gets dropped first in the editor. This causes the next component to be dropped to use the position set by the state earlier, but not the current one. What I want is that I could pass the dragend event data to the ref so that the current component could be loaded with a dynamic positioning as per the mouse pointer.

Here is my code of a simple user component created to drag/drop a checkbox:

import { useNode, useEditor } from '@craftjs/core';
import React, { useContext, useEffect, useState } from 'react';
import { SimpleCheckboxSettings } from './SimpleCheckboxSettings';
import Draggable from 'react-draggable';
import AuthContext from '../../../../../store/AuthContext';
import { Checkbox } from '@material-ui/core';

export type SimpleCheckBoxProps = {
    checked: boolean;
    pageX: number;
    pageY: number;
    user_id: number;
    className: string;
};

export const SimpleCheckBox = ({
    checked,
    pageX,
    pageY,
    user_id,
    className,
}: Partial<SimpleCheckBoxProps>) => {

    const {
        connectors: { connect },
        actions,
    } = useNode();

    const { enabled } = useEditor((state) => ({
        enabled: state.options.enabled
    }));

    const [disable, setDisable] = useState(true);

    const [position, setPosition] = useState({ x: pageX, y: pageY });

    const authCtx = useContext(AuthContext);

    const current_user = authCtx.user()

    const handleStop = (event: any, data: any) => {
        setPosition({ x: data.x, y: data.y })
        actions.setProp((props) => {
            props.pageX = data.x;
            props.pageY = data.y;
        });
    };

    useEffect(() => {
        // actions.setProp((prop) => { 
        //   prop.user_id = user_id; }, 500);
        if (user_id == current_user.id) {
            setDisable(false)
        }
    }, [user_id])

    return (
        <Draggable disabled={!enabled} onStop={handleStop} defaultPosition={position}>
            <Checkbox
                ref={connect}
                checked={checked}
                className={`user-${user_id}`}
                style={{
                    cursor: 'move',
                    position: 'absolute',
                    zIndex: 3
                }}
                onChange={(event) => {
                    if (user_id == current_user.id ) {
                        actions.setProp((prop) => {
                            prop.checked = !checked
                        }, 500)
                    }
                }}
            />
        </Draggable>
    );
};

SimpleCheckBox.craft = {
    displayName: 'CheckBox',
    props: {
        pageX: 0,
        pageY: 0,
        user_id: null,
        className: 'fillable-textfield',
        checked: false
    },
    rules: {
        canDrag: () => true,
    },
    related: {
        toolbar: SimpleCheckboxSettings,
    },
};

Originally posted by @nickm89 in https://github.com/prevwong/craft.js/issues/32#issuecomment-1002949758

nickm89 avatar Dec 30 '21 10:12 nickm89

Hey, I'm trying to do the same thing. Did you get this to work somehow? @nickm89

wilhus avatar Apr 21 '22 14:04 wilhus