Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
431 lines
12 KiB
Plaintext
431 lines
12 KiB
Plaintext
'use client';
|
|
|
|
import { c as _c } from "react/compiler-runtime";
|
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
import { DndContext, DragOverlay, useDraggable, useDroppable } from '@dnd-kit/core';
|
|
import { snapCenterToCursor } from '@dnd-kit/modifiers';
|
|
import { ChevronIcon, Popup, PopupList, useTranslation, XIcon } from '@payloadcms/ui';
|
|
import React, { useMemo, useState } from 'react';
|
|
/**
|
|
* Custom modifier that only applies snapCenterToCursor for pointer events.
|
|
* During keyboard navigation, we handle positioning ourselves via the coordinate getter.
|
|
*/
|
|
const snapCenterToCursorOnlyForPointer = args => {
|
|
const {
|
|
activatorEvent
|
|
} = args;
|
|
// Only apply snap for pointer events (mouse/touch), not keyboard
|
|
// Check activatorEvent.type since KeyboardEvent may not exist on server
|
|
if (activatorEvent && 'key' in activatorEvent) {
|
|
return args.transform;
|
|
}
|
|
return snapCenterToCursor(args);
|
|
};
|
|
import { DashboardStepNav } from './DashboardStepNav.js';
|
|
import { useDashboardLayout } from './useDashboardLayout.js';
|
|
import { closestInXAxis } from './utils/collisionDetection.js';
|
|
import { useDashboardSensors } from './utils/sensors.js';
|
|
/* eslint-disable perfectionist/sort-objects */
|
|
const WIDTH_TO_PERCENTAGE = {
|
|
'x-small': 25,
|
|
small: 1 / 3 * 100,
|
|
medium: 50,
|
|
large: 2 / 3 * 100,
|
|
'x-large': 75,
|
|
full: 100
|
|
};
|
|
export function ModularDashboardClient(t0) {
|
|
const $ = _c(21);
|
|
const {
|
|
clientLayout: initialLayout,
|
|
widgets
|
|
} = t0;
|
|
const {
|
|
t
|
|
} = useTranslation();
|
|
const {
|
|
addWidget,
|
|
cancel,
|
|
cancelModal,
|
|
currentLayout,
|
|
deleteWidget,
|
|
isEditing,
|
|
moveWidget,
|
|
resetLayout,
|
|
resizeWidget,
|
|
saveLayout,
|
|
setIsEditing
|
|
} = useDashboardLayout(initialLayout);
|
|
const [activeDragId, setActiveDragId] = useState(null);
|
|
const sensors = useDashboardSensors();
|
|
let t1;
|
|
if ($[0] !== activeDragId || $[1] !== addWidget || $[2] !== cancel || $[3] !== cancelModal || $[4] !== currentLayout || $[5] !== deleteWidget || $[6] !== isEditing || $[7] !== moveWidget || $[8] !== resetLayout || $[9] !== resizeWidget || $[10] !== saveLayout || $[11] !== sensors || $[12] !== setIsEditing || $[13] !== t || $[14] !== widgets) {
|
|
let t2;
|
|
if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
|
|
t2 = () => {
|
|
setActiveDragId(null);
|
|
};
|
|
$[16] = t2;
|
|
} else {
|
|
t2 = $[16];
|
|
}
|
|
let t3;
|
|
if ($[17] !== currentLayout || $[18] !== moveWidget) {
|
|
t3 = event => {
|
|
if (!event.over) {
|
|
setActiveDragId(null);
|
|
return;
|
|
}
|
|
const droppableId = event.over.id;
|
|
const i = droppableId.lastIndexOf("-");
|
|
const slug = droppableId.slice(0, i);
|
|
const position = droppableId.slice(i + 1);
|
|
if (slug === event.active.id) {
|
|
return;
|
|
}
|
|
const moveFromIndex = currentLayout?.findIndex(widget => widget.item.id === event.active.id);
|
|
let moveToIndex = currentLayout?.findIndex(widget_0 => widget_0.item.id === slug);
|
|
if (moveFromIndex < moveToIndex) {
|
|
moveToIndex--;
|
|
}
|
|
if (position === "after") {
|
|
moveToIndex++;
|
|
}
|
|
moveWidget({
|
|
moveFromIndex,
|
|
moveToIndex
|
|
});
|
|
setActiveDragId(null);
|
|
};
|
|
$[17] = currentLayout;
|
|
$[18] = moveWidget;
|
|
$[19] = t3;
|
|
} else {
|
|
t3 = $[19];
|
|
}
|
|
let t4;
|
|
if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
|
|
t4 = event_0 => {
|
|
setActiveDragId(event_0.active.id);
|
|
};
|
|
$[20] = t4;
|
|
} else {
|
|
t4 = $[20];
|
|
}
|
|
t1 = _jsxs("div", {
|
|
children: [_jsx(DndContext, {
|
|
autoScroll: {
|
|
enabled: true,
|
|
threshold: {
|
|
x: 0,
|
|
y: 0.2
|
|
}
|
|
},
|
|
collisionDetection: closestInXAxis,
|
|
id: "dashboard-dnd-context",
|
|
onDragCancel: t2,
|
|
onDragEnd: t3,
|
|
onDragStart: t4,
|
|
sensors,
|
|
children: _jsxs("div", {
|
|
className: `modular-dashboard ${isEditing ? "editing" : ""}`,
|
|
style: {
|
|
display: "flex",
|
|
flexWrap: "wrap"
|
|
},
|
|
children: [currentLayout?.length === 0 && _jsx("div", {
|
|
className: "modular-dashboard__empty",
|
|
children: _jsx("p", {
|
|
children: "There are no widgets on your dashboard. You can add them from the \"Dashboard\" menu located in the top bar."
|
|
})
|
|
}), currentLayout?.map((widget_1, _index) => _jsx(React.Fragment, {
|
|
children: _jsx(DraggableItem, {
|
|
disabled: !isEditing,
|
|
id: widget_1.item.id,
|
|
style: {
|
|
width: `${WIDTH_TO_PERCENTAGE[widget_1.item.width]}%`,
|
|
padding: "6px"
|
|
},
|
|
width: widget_1.item.width,
|
|
children: _jsxs("div", {
|
|
className: `widget-wrapper ${isEditing ? "widget-wrapper--editing" : ""}`,
|
|
children: [_jsx("div", {
|
|
"aria-hidden": isEditing,
|
|
className: "widget-content",
|
|
inert: isEditing,
|
|
children: widget_1.component
|
|
}), isEditing && _jsxs("div", {
|
|
className: "widget-wrapper__controls",
|
|
onPointerDown: _temp,
|
|
children: [_jsx(WidgetWidthDropdown, {
|
|
currentWidth: widget_1.item.width,
|
|
maxWidth: widget_1.item.maxWidth,
|
|
minWidth: widget_1.item.minWidth,
|
|
onResize: width => resizeWidget(widget_1.item.id, width)
|
|
}), _jsxs("button", {
|
|
className: "widget-wrapper__delete-btn",
|
|
onClick: () => deleteWidget(widget_1.item.id),
|
|
type: "button",
|
|
children: [_jsx("span", {
|
|
className: "sr-only",
|
|
children: t("dashboard:deleteWidget", {
|
|
id: widget_1.item.id
|
|
})
|
|
}), _jsx(XIcon, {})]
|
|
})]
|
|
})]
|
|
})
|
|
})
|
|
}, widget_1.item.id)), _jsx(DragOverlay, {
|
|
className: "drag-overlay",
|
|
dropAnimation: {
|
|
duration: 100
|
|
},
|
|
modifiers: [snapCenterToCursorOnlyForPointer],
|
|
children: activeDragId ? (() => {
|
|
const draggedWidget = currentLayout?.find(widget_2 => widget_2.item.id === activeDragId);
|
|
return draggedWidget ? _jsx("div", {
|
|
style: {
|
|
transform: "scale(0.25)"
|
|
},
|
|
children: _jsx("div", {
|
|
className: `widget-wrapper ${isEditing ? "widget-wrapper--editing" : ""}`,
|
|
children: _jsx("div", {
|
|
className: "widget-content",
|
|
children: draggedWidget.component
|
|
})
|
|
})
|
|
}) : null;
|
|
})() : null
|
|
})]
|
|
})
|
|
}), _jsx(DashboardStepNav, {
|
|
addWidget,
|
|
cancel,
|
|
isEditing,
|
|
resetLayout,
|
|
saveLayout,
|
|
setIsEditing,
|
|
widgets
|
|
}), cancelModal]
|
|
});
|
|
$[0] = activeDragId;
|
|
$[1] = addWidget;
|
|
$[2] = cancel;
|
|
$[3] = cancelModal;
|
|
$[4] = currentLayout;
|
|
$[5] = deleteWidget;
|
|
$[6] = isEditing;
|
|
$[7] = moveWidget;
|
|
$[8] = resetLayout;
|
|
$[9] = resizeWidget;
|
|
$[10] = saveLayout;
|
|
$[11] = sensors;
|
|
$[12] = setIsEditing;
|
|
$[13] = t;
|
|
$[14] = widgets;
|
|
$[15] = t1;
|
|
} else {
|
|
t1 = $[15];
|
|
}
|
|
return t1;
|
|
}
|
|
function _temp(e) {
|
|
return e.stopPropagation();
|
|
}
|
|
function WidgetWidthDropdown({
|
|
currentWidth,
|
|
maxWidth,
|
|
minWidth,
|
|
onResize
|
|
}) {
|
|
// Filter options based on minWidth and maxWidth
|
|
const validOptions = useMemo(() => {
|
|
const minPercentage = WIDTH_TO_PERCENTAGE[minWidth];
|
|
const maxPercentage = WIDTH_TO_PERCENTAGE[maxWidth];
|
|
return Object.entries(WIDTH_TO_PERCENTAGE).map(([key, value]) => ({
|
|
width: key,
|
|
percentage: value
|
|
})).filter(option => option.percentage >= minPercentage && option.percentage <= maxPercentage);
|
|
}, [minWidth, maxWidth]);
|
|
const isDisabled = validOptions.length <= 1;
|
|
return /*#__PURE__*/_jsx(Popup, {
|
|
button: /*#__PURE__*/_jsxs("button", {
|
|
className: "widget-wrapper__size-btn",
|
|
disabled: isDisabled,
|
|
onPointerDown: e => e.stopPropagation(),
|
|
type: "button",
|
|
children: [/*#__PURE__*/_jsx("span", {
|
|
className: "widget-wrapper__size-btn-text",
|
|
children: currentWidth
|
|
}), /*#__PURE__*/_jsx(ChevronIcon, {
|
|
className: "widget-wrapper__size-btn-icon"
|
|
})]
|
|
}),
|
|
buttonType: "custom",
|
|
disabled: isDisabled,
|
|
render: ({
|
|
close
|
|
}) => /*#__PURE__*/_jsx(PopupList.ButtonGroup, {
|
|
children: validOptions.map(option_0 => {
|
|
const isSelected = option_0.width === currentWidth;
|
|
return /*#__PURE__*/_jsxs(PopupList.Button, {
|
|
active: isSelected,
|
|
onClick: () => {
|
|
onResize(option_0.width);
|
|
close();
|
|
},
|
|
children: [/*#__PURE__*/_jsx("span", {
|
|
className: "widget-wrapper__size-btn-label",
|
|
children: option_0.width
|
|
}), /*#__PURE__*/_jsxs("span", {
|
|
className: "widget-wrapper__size-btn-percentage",
|
|
children: [option_0.percentage.toFixed(0), "%"]
|
|
})]
|
|
}, option_0.width);
|
|
})
|
|
}),
|
|
size: "small",
|
|
verticalAlign: "bottom"
|
|
});
|
|
}
|
|
function DraggableItem(props) {
|
|
const $ = _c(13);
|
|
let t0;
|
|
if ($[0] !== props.disabled || $[1] !== props.id) {
|
|
t0 = {
|
|
id: props.id,
|
|
disabled: props.disabled
|
|
};
|
|
$[0] = props.disabled;
|
|
$[1] = props.id;
|
|
$[2] = t0;
|
|
} else {
|
|
t0 = $[2];
|
|
}
|
|
const {
|
|
attributes,
|
|
isDragging,
|
|
listeners,
|
|
setNodeRef
|
|
} = useDraggable(t0);
|
|
const t1 = isDragging ? 0.3 : 1;
|
|
let t2;
|
|
if ($[3] !== attributes || $[4] !== listeners || $[5] !== props.children || $[6] !== props.disabled || $[7] !== props.id || $[8] !== props.style || $[9] !== props.width || $[10] !== setNodeRef || $[11] !== t1) {
|
|
const mergedStyles = {
|
|
...props.style,
|
|
opacity: t1,
|
|
position: "relative"
|
|
};
|
|
const draggableProps = props.disabled ? {} : {
|
|
...listeners,
|
|
...attributes
|
|
};
|
|
t2 = _jsxs("div", {
|
|
className: "widget",
|
|
"data-slug": props.id,
|
|
"data-width": props.width,
|
|
style: mergedStyles,
|
|
children: [_jsx(DroppableItem, {
|
|
id: props.id,
|
|
position: "before"
|
|
}), _jsx("div", {
|
|
className: "draggable",
|
|
id: props.id,
|
|
ref: setNodeRef,
|
|
...draggableProps,
|
|
style: {
|
|
width: "100%",
|
|
height: "100%"
|
|
},
|
|
children: props.children
|
|
}), _jsx(DroppableItem, {
|
|
id: props.id,
|
|
position: "after"
|
|
})]
|
|
});
|
|
$[3] = attributes;
|
|
$[4] = listeners;
|
|
$[5] = props.children;
|
|
$[6] = props.disabled;
|
|
$[7] = props.id;
|
|
$[8] = props.style;
|
|
$[9] = props.width;
|
|
$[10] = setNodeRef;
|
|
$[11] = t1;
|
|
$[12] = t2;
|
|
} else {
|
|
t2 = $[12];
|
|
}
|
|
return t2;
|
|
}
|
|
function DroppableItem(t0) {
|
|
const $ = _c(11);
|
|
const {
|
|
id,
|
|
position
|
|
} = t0;
|
|
const t1 = `${id}-${position}`;
|
|
let t2;
|
|
if ($[0] !== position) {
|
|
t2 = {
|
|
position
|
|
};
|
|
$[0] = position;
|
|
$[1] = t2;
|
|
} else {
|
|
t2 = $[1];
|
|
}
|
|
let t3;
|
|
if ($[2] !== t1 || $[3] !== t2) {
|
|
t3 = {
|
|
id: t1,
|
|
data: t2
|
|
};
|
|
$[2] = t1;
|
|
$[3] = t2;
|
|
$[4] = t3;
|
|
} else {
|
|
t3 = $[4];
|
|
}
|
|
const {
|
|
setNodeRef,
|
|
isOver
|
|
} = useDroppable(t3);
|
|
const t4 = `${id}-${position}`;
|
|
const t5 = position === "before" ? -2 : "auto";
|
|
const t6 = position === "after" ? -2 : "auto";
|
|
const t7 = isOver ? "var(--theme-success-400)" : "transparent";
|
|
let t8;
|
|
if ($[5] !== setNodeRef || $[6] !== t4 || $[7] !== t5 || $[8] !== t6 || $[9] !== t7) {
|
|
t8 = _jsx("div", {
|
|
className: "droppable-widget",
|
|
"data-testid": t4,
|
|
ref: setNodeRef,
|
|
style: {
|
|
position: "absolute",
|
|
left: t5,
|
|
right: t6,
|
|
top: 0,
|
|
bottom: 0,
|
|
borderRadius: "1000px",
|
|
width: "4px",
|
|
backgroundColor: t7,
|
|
marginBottom: "10px",
|
|
marginTop: "10px",
|
|
pointerEvents: "none",
|
|
zIndex: 1000
|
|
}
|
|
});
|
|
$[5] = setNodeRef;
|
|
$[6] = t4;
|
|
$[7] = t5;
|
|
$[8] = t6;
|
|
$[9] = t7;
|
|
$[10] = t8;
|
|
} else {
|
|
t8 = $[10];
|
|
}
|
|
return t8;
|
|
}
|
|
//# sourceMappingURL=index.client.js.map |