<script>
import theme from "#build/b24ui/editor-drag-handle";
</script>

<script setup>
import { computed, ref } from "vue";
import DragHandle from "@tiptap/extension-drag-handle-vue-3";
import { reactiveOmit, reactivePick } from "@vueuse/core";
import { defu } from "defu";
import { useAppConfig } from "#imports";
import { useComponentProps } from "../composables/useComponentProps";
import { useForwardProps } from "../composables/useForwardProps";
import { buildFloatingUIMiddleware } from "../utils/editor";
import { transformUI } from "../utils";
import { tv } from "../utils/tv";
import icons from "../dictionary/icons";
import B24Button from "./Button.vue";
defineOptions({ inheritAttrs: false });
const _props = defineProps({
  icon: { type: [Function, Object], required: false },
  color: { type: null, required: false, default: "air-tertiary-no-accent" },
  options: { type: Object, required: false },
  editor: { type: Object, required: true },
  b24ui: { type: Object, required: false },
  pluginKey: { type: [Object, String], required: false },
  nestedOptions: { type: Object, required: false },
  onElementDragStart: { type: Function, required: false },
  onElementDragEnd: { type: Function, required: false },
  getReferencedVirtualElement: { type: Function, required: false },
  nested: { type: [Boolean, Object], required: false },
  label: { type: String, required: false },
  activeColor: { type: null, required: false },
  depth: { type: null, required: false },
  activeDepth: { type: null, required: false },
  size: { type: null, required: false, default: "sm" },
  rounded: { type: Boolean, required: false },
  block: { type: Boolean, required: false },
  loadingAuto: { type: Boolean, required: false },
  normalCase: { type: Boolean, required: false },
  useWait: { type: Boolean, required: false },
  useClock: { type: Boolean, required: false },
  useDropdown: { type: Boolean, required: false },
  onClick: { type: [Function, Array], required: false },
  class: { type: null, required: false },
  avatar: { type: Object, required: false },
  loading: { type: Boolean, required: false },
  as: { type: null, required: false },
  type: { type: null, required: false },
  disabled: { type: Boolean, required: false },
  isAction: { type: Boolean, required: false },
  exactActiveClass: { type: String, required: false },
  viewTransition: { type: Boolean, required: false }
});
defineSlots();
const emit = defineEmits(["nodeChange", "hover"]);
const props = useComponentProps("editorDragHandle", _props);
const dragHandleProps = useForwardProps(reactivePick(props, "pluginKey", "nested", "nestedOptions", "onElementDragEnd", "onElementDragStart", "getReferencedVirtualElement"));
const buttonProps = useForwardProps(reactiveOmit(props, "icon", "options", "editor", "pluginKey", "nested", "nestedOptions", "onElementDragEnd", "onElementDragStart", "getReferencedVirtualElement", "class", "b24ui"));
const appConfig = useAppConfig();
const b24ui = computed(() => tv({ extend: tv(theme), ...appConfig.b24ui?.editorDragHandle || {} })());
const floatingUIOptions = computed(() => defu(props.options, {
  strategy: "absolute",
  placement: "left-start",
  offset: ({ rects }) => {
    const blockHeight = rects.reference.height;
    const handleHeight = rects.floating.height;
    if (blockHeight > 40) {
      return {
        alignmentAxis: 0,
        mainAxis: 8
      };
    }
    return {
      alignmentAxis: (blockHeight - handleHeight) / 2,
      mainAxis: 8
    };
  },
  flip: {},
  shift: {},
  size: false,
  autoPlacement: false,
  hide: false,
  inline: false
}));
const middleware = computed(() => buildFloatingUIMiddleware(floatingUIOptions.value));
const computePositionConfig = computed(() => ({
  placement: floatingUIOptions.value.placement,
  strategy: floatingUIOptions.value.strategy,
  middleware: middleware.value
}));
const currentNodePos = ref();
function onNodeChange({ pos }) {
  currentNodePos.value = pos;
  if (pos == null || pos < 0) return;
  const node = props.editor.state.doc.nodeAt(pos);
  if (node) {
    emit("hover", { node: node.toJSON(), pos });
  }
}
function onClick() {
  if (!props.editor) return;
  const pos = currentNodePos.value;
  if (pos == null || pos < 0) return;
  const node = props.editor.state.doc.nodeAt(pos);
  if (node) {
    const selectedNode = { node: node.toJSON(), pos };
    emit("nodeChange", selectedNode);
    props.editor.chain().setNodeSelection(pos).run();
    return selectedNode;
  }
}
</script>

<template>
  <DragHandle
    v-bind="dragHandleProps"
    :compute-position-config="computePositionConfig"
    :editor="props.editor"
    :on-node-change="onNodeChange"
    data-slot="root"
    :class="b24ui.root({ class: [props.b24ui?.root, props.class] })"
    @click="onClick"
  >
    <slot :b24ui="b24ui" :on-click="onClick">
      <B24Button
        v-bind="{
  ...buttonProps,
  icon: props.icon || icons.drag,
  ...$attrs
}"
        data-slot="handle"
        :class="b24ui.handle({ class: [props.b24ui?.handle, props.class] })"
        :b24ui="transformUI(b24ui, props.b24ui)"
      />
    </slot>
  </DragHandle>
</template>
