daybrush / moveable

Moveable! Draggable! Resizable! Scalable! Rotatable! Warpable! Pinchable! Groupable! Snappable!
https://daybrush.com/moveable/
MIT License
10.05k stars 617 forks source link

children.map is not a function (in able) #764

Closed alexconstantin closed 2 years ago

alexconstantin commented 2 years ago

Environments

Description

Hello, daybrush! Please check the link above. When rendering the custom able, that error is thrown. I am not sure what is the scenario for this. I have other custom ables which are working just fine (the code is pretty much the same as the one in the code-sandbox link). Can you please give me a hint of what I am doing wrong? Thank you!

daybrush commented 2 years ago

@alexconstantin

All moveable modules except React and Preact have a built-in Renderer (Mini React).

Try this code:

import { Able, MoveableManagerInterface } from "moveable";
import { Renderer } from "react-moveable/types";
// import React from "preact/compat";
// import { h } from "preact";

interface MOOptionsProps {
  mooptions: boolean;
}

const MOOptions = {
  name: "mooptions",
  props: {},
  render(
    moveable: MoveableManagerInterface<MOOptionsProps>,
    { createElement: h }: Renderer
  ) {
    // const h = Renderer.createElement;
    const rect = moveable.getRect();
    const id = new Date().getTime();

    return (
      <div
        key={`mooptions-${id}`}
        className={"moveable-mooptions"}
        style={{
          position: "absolute",
          left: `${rect.width / 2}px`,
          top: `${rect.height / 2}px`,
          borderRadius: "50%",
          padding: "2px 4px",
          color: "white",
          fontSize: "13px",
          whiteSpace: "nowrap",
          fontWeight: "bold",
          willChange: "transform",
          transform: "translate(-50%, -50%)",
          width: "40px",
          height: "40px",
          backgroundColor: "rgba(252,95,87,.75)",
          backgroundPosition: "center",
          backgroundSize: "16px 16px"
        }}
      >
        <span>My custom element here</span>
      </div>
    );
  }
} as Able;

export default MOOptions;
alexconstantin commented 2 years ago

@daybrush thank you! The sample code you provided works as expected in the code sandbox link. However, I am still experiencing this issue in my project, but I cannot find a cause / reproducible scenario. This project is written using preact, but we are using the Vanilla distribution of Moveable.

I can get it to work using a code like this:

import {Able, MoveableManagerInterface, Renderer} from "moveable";

interface MOOptionsProps {
  mooptions: boolean;
}

const MOOptions = {
  name: "mooptions",
  render(moveable: MoveableManagerInterface<MOOptionsProps>, { createElement: h }: Renderer) {
    const id = new Date().getTime();
    return <div key={id}>
      TEST!!! {id}
    </div>
  },
} as Able;

export default MOOptions;

This appears to work because I am using that {id} variable in the div. If I replace it with this piece of code (I just remove the {id} variable), errors are thrown:

return <div key={id}>
      TEST!!!
    </div>

Screenshot 2022-10-12 at 22 11 52

Another scenario which doesn't work is this one (wrap the working example into a span element):

return <div key={id}>
      <span>TEST!!! {id}</span>
    </div>

My guess is that the preact renderer is not used, but I don't have any idea how can I ensure it does. Do you have any idea on what can be the cause for this? I am out of ideas on how to approach this, so any hints/ directions I should take for debugging would be appreciated.

Thank you!

daybrush commented 2 years ago

@alexconstantin I don't know the details, but if this method doesn't work, it's probably a Renderer problem of Moveable.

Use tagged-jsx with jsx-like template.

import { Able, MoveableManagerInterface, Renderer } from "moveable";
import { html } from "tagged-jsx";

interface MOOptionsProps {
  mooptions: boolean;
}

const MOOptions = {
  name: "mooptions",
  props: {},
  render(moveable: MoveableManagerInterface<MOOptionsProps>, Renderer) {
    // const h = Renderer.createElement;
    const rect = moveable.getRect();
    const id = new Date().getTime();

    return html`<div
      key=${`mooptions-${id}`}
      className=${"moveable-mooptions"}
      style=${{
        position: "absolute",
        left: `${rect.width / 2}px`,
        top: `${rect.height / 2}px`,
        borderRadius: "50%",
        padding: "2px 4px",
        color: "white",
        fontSize: "13px",
        whiteSpace: "nowrap",
        fontWeight: "bold",
        willChange: "transform",
        transform: "translate(-50%, -50%)",
        width: "40px",
        height: "40px",
        backgroundColor: "rgba(252,95,87,.75)",
        backgroundPosition: "center",
        backgroundSize: "16px 16px"
      }}
    >
      String <span>My custom element here</span>
    </div>`(Renderer.createElement);
  }
} as Able;

export default MOOptions;
alexconstantin commented 2 years ago

@daybrush thank you! using the code above I no longer get the error. I am unable to render custom components (they just get rendered as a custom tag ), but this is no issue at the moment. Thank you!

william-spec commented 1 year ago

@daybrush I have the same problem, so have you find out whether it is a Renderer problem of Moveable, I'm using React