Drag-and-drop base64-encoded SVG from plugin panel

Hey there,

I’m developing an Icon Library plugin and want to support drag-and-drop of icons from the plugin panel into the document. According to the docs and examples, UXP supports event.dataTransfer.setData("text/uri-list", someData) in dragstart event handlers, where someData is a list of file paths or a base64-encoded data URIs for bitmaps and SVGs.

However, when I try this with a known-good data URI for an SVG, XD throws an error dialog stating “There was a problem importing your asset”.

Minimal example:

DOM

...
<div id="icon" draggable="true">
  <svg xmlns="http://www.w3.org/2000/svg">...</svg>
</div>
...

JS

const svgData = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0iY3VycmVudENvbG9yIiB2aWV3Qm94PSIwIDAgMjU2IDI1NiIgY2xhc3M9Imljb24iPjxyZWN0IHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2IiBmaWxsPSJub25lIj48L3JlY3Q+PHBvbHlnb24gcG9pbnRzPSIxMjAgMzIgMTg0IDgwIDEyMCAxMjggMTIwIDMyIiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ij48L3BvbHlnb24+PHBvbHlnb24gcG9pbnRzPSIxMjAgMTI4IDE4NCAxNzYgMTIwIDIyNCAxMjAgMTI4IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ij48L3BvbHlnb24+PGxpbmUgeDE9IjU2IiB5MT0iODAiIHgyPSIxMjAiIHkyPSIxMjgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMTYiPjwvbGluZT48bGluZSB4MT0iNTYiIHkxPSIxNzYiIHgyPSIxMjAiIHkyPSIxMjgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMTYiPjwvbGluZT48Y2lyY2xlIGN4PSI1MiIgY3k9IjEyOCIgcj0iMTIiPjwvY2lyY2xlPjxjaXJjbGUgY3g9IjE5NiIgY3k9IjEyOCIgcj0iMTIiPjwvY2lyY2xlPjwvc3ZnPg=="

document.querySelector("#icon").ondragstart = (event) => {
  event.dataTransfer.setData("text/uri-list", svgData);
}

The URI is valid, and does not include any unsupported elements or attributes listed here.

I want to avoid creating temporary File objects as opposed to the base64 approach, as my plugin has several thousand SVG assets which would need to all be instantiated at plugin startup – I can’t lazily create a temp File for a dragged icon, since you cannot asynchronously set an event’s dataTransfer data.

I should also note that my actual plugin is a React application, and in practice the event handler finds the SVG within the dragged parent element, gets its string representation, then uses a btoa polyfill to encode it – all of which I have verified are not at cause here. I have tried setting the dataTransfer on the SyntheticEvent’s nativeEvent too, to no avail.

Dragging a base-64 encoded SVG onto an XD canvas is not currently supported (base-64 encoded PNG, JPG, GIF are supported). Sorry that the documentation is not clear on this.

Thanks for the response. Are there plans to implement this soon? Is the only option to create a temporary File for every single icon on run?

The docs should probably be updated then, it IS clear, but it is just incorrect.

Drag from plugin panel UI into XD document
  - Only bitmap images, SVG content, or text can be dropped into the document.
  - Provide the mimetype text/uri-list and populate it only with local file paths (see File.nativePath) and/or data: image URIs.

There is no update on if or when this support will be added. For now the only option I see is to use temp files as illustrated in this example:

2 Likes