react-tierlist
Version:
A lightweight, customizable React Tier List Maker & Viewer component package with drag-and-drop support and theming.
189 lines (187 loc) • 6.74 kB
JavaScript
// src/components/TierListMaker.tsx
import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
import { jsx, jsxs } from "react/jsx-runtime";
var defaultColors = ["#FF6B6B", "#FFD93D", "#6BCB77", "#4D96FF", "#9D4EDD"];
var TierListMaker = ({ data, onChange, config }) => {
const colors = config?.colors ?? defaultColors;
const rowHeight = config?.rowHeight ?? 120;
const handleDragEnd = (result) => {
if (!result.destination) return;
const sourceTierIndex = Number(result.source.droppableId);
const destTierIndex = Number(result.destination.droppableId);
const newData = data.map((t) => ({ ...t, items: [...t.items] }));
const [moved] = newData[sourceTierIndex].items.splice(result.source.index, 1);
newData[destTierIndex].items.splice(result.destination.index, 0, moved);
onChange?.(newData);
};
return /* @__PURE__ */ jsx(DragDropContext, { onDragEnd: handleDragEnd, children: /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: data.map((tier, tierIndex) => /* @__PURE__ */ jsx(Droppable, { droppableId: String(tierIndex), direction: "horizontal", children: (droppableProvided) => /* @__PURE__ */ jsxs(
"div",
{
style: {
display: "flex",
alignItems: "center",
gap: 12,
padding: 8,
borderRadius: 10,
background: "rgba(255,255,255,0.05)"
},
children: [
/* @__PURE__ */ jsx("div", { style: { width: 72, textAlign: "center" }, children: /* @__PURE__ */ jsx(
"div",
{
style: {
padding: "6px 8px",
borderRadius: 8,
fontWeight: 700,
color: "#fff",
background: colors[tierIndex % colors.length],
boxShadow: "0 4px 12px rgba(0,0,0,0.25)"
},
children: tier.name
}
) }),
/* @__PURE__ */ jsxs(
"div",
{
ref: droppableProvided.innerRef,
...droppableProvided.droppableProps,
style: {
display: "flex",
flexWrap: "wrap",
gap: 8,
padding: 8,
minHeight: rowHeight,
width: "100%",
borderRadius: 8,
background: "rgba(255,255,255,0.03)",
boxSizing: "border-box"
},
children: [
tier.items.map((url, itemIndex) => /* @__PURE__ */ jsx(
Draggable,
{
draggableId: `${tierIndex}-${url}-${itemIndex}`,
index: itemIndex,
children: (draggableProvided, snapshot) => /* @__PURE__ */ jsx(
"div",
{
ref: draggableProvided.innerRef,
...draggableProvided.draggableProps,
...draggableProvided.dragHandleProps,
style: {
borderRadius: 8,
overflow: "hidden",
background: "#fff",
width: 80,
height: 80,
display: "flex",
alignItems: "center",
justifyContent: "center",
boxShadow: snapshot.isDragging ? "0 8px 20px rgba(0,0,0,0.25)" : "0 2px 6px rgba(0,0,0,0.15)",
...draggableProvided.draggableProps.style
},
children: /* @__PURE__ */ jsx(
"img",
{
src: url,
alt: "item",
style: { width: "100%", height: "100%", objectFit: "cover" }
}
)
}
)
},
`${tierIndex}-${url}-${itemIndex}`
)),
droppableProvided.placeholder
]
}
)
]
}
) }, tier.name)) }) });
};
var TierListMaker_default = TierListMaker;
// src/components/TierListViewer.tsx
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
var defaultColors2 = ["#FF6B6B", "#FFD93D", "#6BCB77", "#4D96FF", "#9D4EDD"];
var TierListViewer = ({ data, config }) => {
const colors = config?.colors ?? defaultColors2;
const rowHeight = config?.rowHeight ?? 120;
return /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: data.map((tier, tierIndex) => /* @__PURE__ */ jsxs2(
"div",
{
style: {
display: "flex",
alignItems: "center",
gap: 12,
padding: 8,
borderRadius: 10,
background: "rgba(255,255,255,0.05)"
},
children: [
/* @__PURE__ */ jsx2("div", { style: { width: 72, textAlign: "center" }, children: /* @__PURE__ */ jsx2(
"div",
{
style: {
padding: "6px 8px",
borderRadius: 8,
fontWeight: 700,
color: "#fff",
background: colors[tierIndex % colors.length],
boxShadow: "0 4px 12px rgba(0,0,0,0.25)"
},
children: tier.name
}
) }),
/* @__PURE__ */ jsx2(
"div",
{
style: {
display: "flex",
flexWrap: "wrap",
gap: 8,
padding: 8,
minHeight: rowHeight,
width: "100%",
borderRadius: 8,
background: "rgba(255,255,255,0.03)",
boxSizing: "border-box"
},
children: tier.items.map((url, idx) => /* @__PURE__ */ jsx2(
"div",
{
style: {
borderRadius: 8,
overflow: "hidden",
background: "#fff",
width: 80,
height: 80,
display: "flex",
alignItems: "center",
justifyContent: "center",
boxShadow: "0 2px 6px rgba(0,0,0,0.15)"
},
children: /* @__PURE__ */ jsx2(
"img",
{
src: url,
alt: "item",
style: { width: "100%", height: "100%", objectFit: "cover" }
}
)
},
idx
))
}
)
]
},
tier.name
)) });
};
var TierListViewer_default = TierListViewer;
export {
TierListMaker_default as TierListMaker,
TierListViewer_default as TierListViewer
};