@undermuz/react-json-form
Version:
Generate JSON-based forms with react
195 lines (194 loc) • 5.24 kB
JavaScript
// src/array-form/ArrayFormTabs.tsx
import { useCallback, useMemo, useState } from "react";
import {
closestCenter,
DndContext,
DragOverlay,
getFirstCollision,
PointerSensor,
pointerWithin,
rectIntersection,
useDroppable,
useSensor,
useSensors
} from "@dnd-kit/core";
import {
horizontalListSortingStrategy,
SortableContext,
useSortable
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { createPortal } from "react-dom";
import { useJsonFormUi } from "../contexts/ui.mjs";
import ArrayFormItem from "./ArrayFormItem.mjs";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import { createElement } from "react";
var SortableTab = ({
tabId,
...props
}) => {
const Ui = useJsonFormUi();
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: tabId });
const style = {
transform: CSS.Transform.toString(transform),
transition
};
if (!Ui?.Tab) {
return null;
}
return /* @__PURE__ */ jsx(
Ui.Tab,
{
...props,
ref: setNodeRef,
style,
...attributes,
...listeners
}
);
};
var TrashDroppable = () => {
const Ui = useJsonFormUi();
const { isOver, setNodeRef } = useDroppable({
id: "trash"
});
if (!Ui?.ArrayForm?.TrashContainer) {
return null;
}
return /* @__PURE__ */ jsx(
Ui.ArrayForm.TrashContainer,
{
isOver,
ref: setNodeRef,
label: "\u041E\u0442\u043F\u0443\u0441\u0442\u0438\u0442\u0435 \u0447\u0442\u043E\u0431\u044B \u0443\u0434\u0430\u043B\u0438\u0442\u044C"
}
);
};
var SortableList = ({
tabs,
onSortEnd,
children
}) => {
const [activeId, setActiveId] = useState(null);
const sensors = useSensors(
useSensor(PointerSensor, {
activationConstraint: {
distance: 20
}
})
);
const currentIndex = useMemo(() => {
return tabs.findIndex((_i) => _i.id === activeId);
}, [tabs, activeId]);
const collisionDetectionStrategy = useCallback(
(args) => {
const pointerIntersections = pointerWithin(args);
const intersections = pointerIntersections.length > 0 ? (
// If there are droppables intersecting with the pointer, return those
pointerIntersections
) : rectIntersection(args);
let overId = getFirstCollision(intersections, "id");
if (overId === "trash") {
return intersections;
}
if (overId !== null) {
return closestCenter(args);
}
return [];
},
[activeId, tabs]
);
return /* @__PURE__ */ jsxs(
DndContext,
{
sensors,
collisionDetection: collisionDetectionStrategy,
onDragEnd: (event) => {
console.log("[onDragEnd]", event);
setActiveId(null);
onSortEnd(event);
},
onDragStart: (event) => {
setActiveId(event.active.id);
},
children: [
/* @__PURE__ */ jsx(
SortableContext,
{
id: "list",
items: tabs,
strategy: horizontalListSortingStrategy,
children
}
),
typeof document !== "undefined" && createPortal(
/* @__PURE__ */ jsx(DragOverlay, { children: currentIndex > -1 ? /* @__PURE__ */ jsx(
SortableTab,
{
tabId: activeId,
label: `#${currentIndex + 1}`
}
) : null }),
document.body
),
activeId !== null && /* @__PURE__ */ jsx(TrashDroppable, {})
]
}
);
};
var ArrayFormTabs = (props) => {
const {
value,
tab,
addTab,
removeTab,
changeTab,
setTabErrors,
sortTabs,
setTab,
fillArrayDefault,
onRef,
...rest
} = props;
const tabs = value;
const Ui = useJsonFormUi();
const body = value.map((item) => {
return /* @__PURE__ */ createElement(
ArrayFormItem,
{
...rest,
key: item.id,
id: item.id,
isShow: item.id === tab,
value: item,
onRef,
onChange: changeTab,
onError: setTabErrors
}
);
});
if (!Ui?.ArrayForm || !Ui.Tab || !Ui.Icons)
return /* @__PURE__ */ jsx(Fragment, { children: body });
return /* @__PURE__ */ jsxs(Ui.ArrayForm, { style: { position: "relative", zIndex: 1 }, children: [
/* @__PURE__ */ jsxs(Ui.ArrayForm.Header, { children: [
/* @__PURE__ */ jsx(Ui.ArrayForm.Tabs, { children: /* @__PURE__ */ jsx(SortableList, { tabs, onSortEnd: sortTabs, children: tabs.map((val, index) => /* @__PURE__ */ jsx(
SortableTab,
{
label: `#${index + 1}`,
tabId: val.id,
active: tab === val.id,
onSelect: () => setTab(val.id)
},
val.id
)) }) }),
/* @__PURE__ */ jsxs(Ui.ArrayForm.Tabs, { actions: true, children: [
(!fillArrayDefault || value.length > 1) && /* @__PURE__ */ jsx(Ui.Tab, { onSelect: () => removeTab(tab), children: /* @__PURE__ */ jsx(Ui.Icons.Tabs.Remove, {}) }),
/* @__PURE__ */ jsx(Ui.Tab, { onSelect: addTab, children: /* @__PURE__ */ jsx(Ui.Icons.Tabs.Add, {}) })
] })
] }),
/* @__PURE__ */ jsx(Ui.ArrayForm.Body, { children: body })
] });
};
export {
ArrayFormTabs
};