@farmzone/fz-react-ui 1.0.10 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -7960,6 +7960,15 @@ function MultiTabBar(props) {
7960
7960
  const [draggingId, setDraggingId] = React6.useState(null);
7961
7961
  const [dropTargetId, setDropTargetId] = React6.useState(null);
7962
7962
  const [dropSide, setDropSide] = React6.useState("before");
7963
+ const draggingIdRef = React6.useRef(null);
7964
+ const dropTargetIdRef = React6.useRef(null);
7965
+ const dropSideRef = React6.useRef("before");
7966
+ const tabsRef = React6.useRef(tabs);
7967
+ const dropHandledRef = React6.useRef(false);
7968
+ draggingIdRef.current = draggingId;
7969
+ dropTargetIdRef.current = dropTargetId;
7970
+ dropSideRef.current = dropSide;
7971
+ tabsRef.current = tabs;
7963
7972
  React6.useEffect(() => {
7964
7973
  if (!activeTabId || !scrollRef.current) return;
7965
7974
  const el = tabRefs.current.get(activeTabId);
@@ -7997,60 +8006,100 @@ function MultiTabBar(props) {
7997
8006
  el.addEventListener("wheel", onWheel, { passive: false });
7998
8007
  return () => el.removeEventListener("wheel", onWheel);
7999
8008
  }, []);
8009
+ const resolveDropPosition = (clientX) => {
8010
+ for (const [tabId, el] of tabRefs.current) {
8011
+ if (tabId === draggingIdRef.current) continue;
8012
+ const rect = el.getBoundingClientRect();
8013
+ if (clientX >= rect.left && clientX < rect.right) {
8014
+ setDropSide(clientX < rect.left + rect.width / 2 ? "before" : "after");
8015
+ setDropTargetId(tabId);
8016
+ return;
8017
+ }
8018
+ }
8019
+ let rightmostTabId = null;
8020
+ let maxRight = -Infinity;
8021
+ for (const [tabId, el] of tabRefs.current) {
8022
+ if (tabId === draggingIdRef.current) continue;
8023
+ const rect = el.getBoundingClientRect();
8024
+ if (rect.right > maxRight) {
8025
+ maxRight = rect.right;
8026
+ rightmostTabId = tabId;
8027
+ }
8028
+ }
8029
+ if (rightmostTabId && clientX >= maxRight) {
8030
+ setDropSide("after");
8031
+ setDropTargetId(rightmostTabId);
8032
+ }
8033
+ };
8034
+ const reorderTabs = (targetTabId, side, sourceTabs, sourceId) => {
8035
+ if (!onTabsReorder || sourceId === targetTabId) return;
8036
+ const fromIdx = sourceTabs.findIndex((t) => t.id === sourceId);
8037
+ if (fromIdx === -1) return;
8038
+ const newTabs = [...sourceTabs];
8039
+ const moved = newTabs.splice(fromIdx, 1)[0];
8040
+ let insertIdx = newTabs.findIndex((t) => t.id === targetTabId);
8041
+ if (insertIdx === -1) return;
8042
+ if (side === "after") insertIdx += 1;
8043
+ newTabs.splice(insertIdx, 0, moved);
8044
+ onTabsReorder(newTabs);
8045
+ };
8046
+ React6.useEffect(() => {
8047
+ if (!onTabsReorder) return;
8048
+ const onDocDragOver = (e) => {
8049
+ if (!draggingIdRef.current) return;
8050
+ e.preventDefault();
8051
+ resolveDropPosition(e.clientX);
8052
+ };
8053
+ const onDocDrop = (e) => {
8054
+ if (dropHandledRef.current) {
8055
+ dropHandledRef.current = false;
8056
+ return;
8057
+ }
8058
+ e.preventDefault();
8059
+ const id = draggingIdRef.current;
8060
+ const target = dropTargetIdRef.current;
8061
+ if (id && target) reorderTabs(target, dropSideRef.current, tabsRef.current, id);
8062
+ setDraggingId(null);
8063
+ setDropTargetId(null);
8064
+ };
8065
+ document.addEventListener("dragover", onDocDragOver);
8066
+ document.addEventListener("drop", onDocDrop);
8067
+ return () => {
8068
+ document.removeEventListener("dragover", onDocDragOver);
8069
+ document.removeEventListener("drop", onDocDrop);
8070
+ };
8071
+ }, [onTabsReorder]);
8000
8072
  const handleDragStart = (e, tabId) => {
8001
8073
  setDraggingId(tabId);
8002
8074
  e.dataTransfer.effectAllowed = "move";
8003
8075
  };
8004
- const handleDragOver = (e, tabId) => {
8005
- e.preventDefault();
8006
- if (tabId === draggingId) return;
8007
- e.dataTransfer.dropEffect = "move";
8008
- const rect = e.currentTarget.getBoundingClientRect();
8009
- setDropSide(e.clientX < rect.left + rect.width / 2 ? "before" : "after");
8010
- setDropTargetId(tabId);
8011
- };
8012
8076
  const handleDrop = (e, targetTabId) => {
8013
8077
  e.preventDefault();
8014
8078
  e.stopPropagation();
8015
- if (!draggingId || draggingId === targetTabId) {
8016
- setDraggingId(null);
8017
- setDropTargetId(null);
8018
- return;
8019
- }
8020
- if (onTabsReorder) {
8021
- const fromIdx = tabs.findIndex((t) => t.id === draggingId);
8022
- if (fromIdx !== -1) {
8023
- const newTabs = [...tabs];
8024
- const moved = newTabs.splice(fromIdx, 1)[0];
8025
- let insertIdx = newTabs.findIndex((t) => t.id === targetTabId);
8026
- if (insertIdx !== -1) {
8027
- if (dropSide === "after") insertIdx += 1;
8028
- newTabs.splice(insertIdx, 0, moved);
8029
- onTabsReorder(newTabs);
8030
- }
8031
- }
8032
- }
8079
+ dropHandledRef.current = true;
8080
+ const id = draggingIdRef.current;
8081
+ if (id && id !== targetTabId) reorderTabs(targetTabId, dropSideRef.current, tabsRef.current, id);
8033
8082
  setDraggingId(null);
8034
8083
  setDropTargetId(null);
8035
8084
  };
8036
8085
  const handleContainerDrop = (e) => {
8037
8086
  e.preventDefault();
8038
- if (!draggingId || !onTabsReorder) {
8039
- setDraggingId(null);
8040
- setDropTargetId(null);
8041
- return;
8042
- }
8043
- const fromIdx = tabs.findIndex((t) => t.id === draggingId);
8044
- if (fromIdx !== -1 && fromIdx < tabs.length - 1) {
8045
- const newTabs = [...tabs];
8046
- const moved = newTabs.splice(fromIdx, 1)[0];
8047
- newTabs.push(moved);
8048
- onTabsReorder(newTabs);
8087
+ dropHandledRef.current = true;
8088
+ const id = draggingIdRef.current;
8089
+ if (id && onTabsReorder) {
8090
+ const fromIdx = tabsRef.current.findIndex((t) => t.id === id);
8091
+ if (fromIdx !== -1 && fromIdx < tabsRef.current.length - 1) {
8092
+ const newTabs = [...tabsRef.current];
8093
+ const moved = newTabs.splice(fromIdx, 1)[0];
8094
+ newTabs.push(moved);
8095
+ onTabsReorder(newTabs);
8096
+ }
8049
8097
  }
8050
8098
  setDraggingId(null);
8051
8099
  setDropTargetId(null);
8052
8100
  };
8053
8101
  const handleDragEnd = () => {
8102
+ dropHandledRef.current = false;
8054
8103
  setDraggingId(null);
8055
8104
  setDropTargetId(null);
8056
8105
  };
@@ -8101,7 +8150,6 @@ function MultiTabBar(props) {
8101
8150
  if (!isActive) onTabClick(tab.id);
8102
8151
  },
8103
8152
  onDragStart: (e) => handleDragStart(e, tab.id),
8104
- onDragOver: (e) => handleDragOver(e, tab.id),
8105
8153
  onDrop: (e) => handleDrop(e, tab.id),
8106
8154
  onDragEnd: handleDragEnd,
8107
8155
  className: `