atlassian / pragmatic-drag-and-drop

Fast drag and drop for any experience on any tech stack
https://atlassian.design/components/pragmatic-drag-and-drop
Other
7.45k stars 133 forks source link

Vertical trees #35

Closed shipurjan closed 4 weeks ago

shipurjan commented 1 month ago

Hello, it would be great if there was a built-in way for making vertical trees

So that the hitboxes for "reorder above" would be on the left and hitboxes for "reorder below" -- on the right.

https://atlassian.design/components/pragmatic-drag-and-drop/optional-packages/hitbox/about#tree-item

Or another solution would be to add something like maxDetectionDistance parameter to attachClosestEdge() function to allow for detecting the hitbox of the container

EDIT:

For my use case I just patched the hitbox calculating function with pnpm patch (the code bellow also in /es2019 and /cjs directories):

diff --git a/dist/esm/tree-item.js b/dist/esm/tree-item.js
index 47356cf1b195747f52f47b73ee8c0dd8b7155f82..7ca74ff683bcfc12f33c41c87cddea2c9320a376 100644
--- a/dist/esm/tree-item.js
+++ b/dist/esm/tree-item.js
@@ -14,16 +14,16 @@ function getCenter(rect) {
 function standardHitbox(_ref) {
   var client = _ref.client,
     borderBox = _ref.borderBox;
-  var quarterOfHeight = borderBox.height / 4;
+  var quarterOfHeight = borderBox.width / 4;

   // In the top 1/4: reorder-above
   // On the line = in the top 1/4 to give this zone a bit more space
-  if (client.y <= borderBox.top + quarterOfHeight) {
+  if (client.x <= borderBox.left + quarterOfHeight) {
     return 'reorder-above';
   }
   // In the bottom 1/4: reorder-below
   // On the line = in the bottom 1/4 to give this zone a bit more space
-  if (client.y >= borderBox.bottom - quarterOfHeight) {
+  if (client.x >= borderBox.right - quarterOfHeight) {
     return 'reorder-below';
   }
   return 'make-child';

And then the drop indicator is hacked like this:

import { DropIndicator as TreeItemDropIndicator } from "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/tree-item";
import { DropIndicator as BoxDropIndicator } from "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box";

export type DropIndicatorProps = {
  instruction: Instruction;
  gap?: string;
};
export const DropIndicator = ({ instruction, gap }: DropIndicatorProps) => {
  if (instruction.type === "reorder-above") {
    return <BoxDropIndicator edge={"left"} gap={gap} />;
  }
  if (instruction.type === "reorder-below") {
    return <BoxDropIndicator edge={"right"} gap={gap} />;
  }
  return <TreeItemDropIndicator instruction={instruction} />;
};
alexreardon commented 1 month ago

Hi @shipurjan,

I am not sure what you mean by "vertical trees". Would you be able to post a screenshot, example or similar?


Great news: even if our optional tree hitbox / indicator does not work for you - you are totally free to use your own hitbox / indicator. Patch package is one way to do that, but you could also fork / copy paste our tree packages and adjust them for your use case

shipurjan commented 1 month ago

Hi @shipurjan,

I am not sure what you mean by "vertical trees". Would you be able to post a screenshot, example or similar?

Something like this diagram, but rotated 90 degrees. Instead of reorder-above and reorder-below there would be reorder-left and reorder-right (or reorder-before and reorder-after to be direction agnostic) tree-hitbox

But I do admit it's probably a niche use case, but being able to fork the package sounds great

alexreardon commented 4 weeks ago

The incremental nature of Pragmatic drag and drop let's you use your own pieces, while still being able to use as many shared pieces as you can! 🚀