@progress/kendo-react-layout
Version:
React Layout components enable you to create a perceptive and intuitive layout of web projects. KendoReact Layout package
227 lines (226 loc) • 9.37 kB
JavaScript
/**
* @license
*-------------------------------------------------------------------------------------------
* Copyright © 2026 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the package root for more information
*-------------------------------------------------------------------------------------------
*/
import * as n from "react";
import a from "prop-types";
import { getScrollbarWidth as J, canUseDOM as Q, classNames as O, Draggable as Z } from "@progress/kendo-react-common";
import { ResizeHandlers as ee } from "./ResizeHandlers.mjs";
const H = 200, L = {
resizable: !0,
reorderable: !0
}, T = (t) => {
var M, X, Y;
const b = (M = t.reorderable) != null ? M : L.reorderable, p = (X = t.resizable) != null ? X : L.resizable, c = n.useRef(null), s = n.useRef(null), v = n.useRef(null), k = n.useRef(!1), E = n.useRef(!1), D = n.useRef(!1), z = n.useRef({ x: 0, y: 0 }), w = n.useRef({ x: 0, y: 0 }), u = n.useRef({ x: 0, y: 0 }), C = n.useRef(void 0), x = n.useRef(t), [R, F] = n.useState(!1), [q, N] = n.useState(!1), d = n.useCallback(() => v.current ? v.current.element : void 0, []), S = n.useCallback(() => {
if (c.current && s.current) {
const e = c.current.getBoundingClientRect();
s.current.style.top = e.top + "px", s.current.style.left = e.left + "px", s.current.style.height = c.current.offsetHeight + "px", s.current.style.width = c.current.offsetWidth + "px";
}
}, []), A = n.useCallback(() => {
S();
}, [S]), U = n.useCallback(() => {
setTimeout(() => {
S();
}, 100);
}, [S]), W = n.useCallback(() => {
const e = d();
if (!e || !s.current)
return;
const r = e.getBoundingClientRect(), i = r.top + u.current.y, o = r.left + u.current.x;
s.current.style.top = `${i}px`, s.current.style.left = `${o}px`, s.current.style.display = "block";
}, [d]), $ = n.useCallback(() => {
k.current = E.current = !1, u.current = { x: 0, y: 0 }, c.current && s.current && (c.current.style.zIndex = "1", s.current.classList.remove("k-layout-item-hint-resize"), N(!1));
const e = d();
e && (e.style.transform = "translate(0px, 0px)", e.style.transition = `transform ${H}ms cubic-bezier(0.2, 0, 0, 1) 0s`, e.style.marginRight = "0px", e.style.marginLeft = "0px", e.style.height = "100%", e.classList.remove("k-cursor-grabbing"), b && e.classList.add("k-cursor-move")), t.onRelease();
}, [t, b, d]), j = n.useCallback(
(e, r) => {
if (r.end) {
$();
return;
}
if (!c.current || !s.current)
return;
const i = e.clientX, o = e.clientY;
E.current = !0;
const f = (r.direction !== "ns" ? i - w.current.x : 0) * (R ? -1 : 1), l = r.direction !== "ew" ? o - w.current.y : 0, h = d();
if (h && (R ? h.style.marginLeft = -f + "px" : h.style.marginRight = -f + "px", h.style.height = `calc(100% + ${l}px)`), s.current.classList.add("k-layout-item-hint-resize"), C.current)
return;
let g = 0, m = 0;
const P = c.current.getBoundingClientRect();
f > P.width / t.defaultPosition.colSpan / 3 && (g = 1), f < -P.width / t.defaultPosition.colSpan / 1.25 && (g = -1), l > P.height / t.defaultPosition.rowSpan / 3 && (m = 1), l < -P.height / t.defaultPosition.rowSpan / 1.25 && (m = -1), (g !== 0 || m !== 0) && t.update(t.index, 0, 0, m, g);
},
[R, t, $, d]
), B = n.useCallback(
(e) => {
var o;
const r = d();
if (!r)
return;
if (w.current = {
x: e.event.clientX,
y: e.event.clientY
}, D.current = !1, (o = t.ignoreDrag) != null && o.call(t, e.event.originalEvent)) {
D.current = !0;
return;
}
c.current && (c.current.style.zIndex = "10", N(!0)), r.classList.remove("k-cursor-move"), r.classList.add("k-cursor-grabbing");
const i = r.getBoundingClientRect();
z.current = {
x: e.event.clientX - i.x,
y: e.event.clientY - i.y
}, t.onPress();
},
[t, d]
), K = n.useCallback(
(e) => {
var h;
if (D.current)
return;
const r = d();
if (e.event.originalEvent.defaultPrevented || !r)
return;
k.current = !0, e.event.originalEvent.preventDefault();
const i = r.getBoundingClientRect();
if (u.current = {
x: e.event.clientX - i.x - z.current.x + u.current.x,
y: e.event.clientY - i.y - z.current.y + u.current.y
}, r.style.transform = `translate(${u.current.x}px, ${u.current.y}px)`, r.style.transition = "transform 0s", C.current)
return;
let o = 0, f = 0;
u.current.y > 0.7 * i.height / t.defaultPosition.rowSpan && (f = 1), u.current.y < 0.7 * -i.height / t.defaultPosition.rowSpan && (f = -1), u.current.x > 0.7 * i.width / t.defaultPosition.colSpan && (o = 1), u.current.x < 0.7 * -i.width / t.defaultPosition.colSpan && (o = -1), t.update(t.index, f, R ? -o : o, 0, 0);
const l = (h = c.current) == null ? void 0 : h.closest(".k-tilelayout");
if (l && s.current) {
const g = l.getBoundingClientRect(), m = J() || 50;
e.event.clientX < g.left - m || e.event.clientX > g.right - m || e.event.clientY < g.top || e.event.clientY > g.bottom ? s.current.style.display = "none" : s.current.style.display = "block";
}
},
[t, R, d]
);
n.useEffect(() => {
c.current && (getComputedStyle(c.current).direction === "rtl" && F(!0), s.current && (s.current.style.height = c.current.offsetHeight + "px", s.current.style.width = c.current.offsetWidth + "px"));
}, []);
const I = n.useRef(null);
(Y = v.current) != null && Y.element && (I.current = v.current.element.getBoundingClientRect()), n.useLayoutEffect(() => {
const e = d();
if (!e)
return;
const r = e.getBoundingClientRect(), i = I.current;
if (!(i != null && i.width)) {
x.current = t;
return;
}
if (E.current) {
const l = r.width - i.width;
if (R) {
const m = parseFloat(e.style.marginLeft || "0");
e.style.marginLeft = m - l + "px";
} else {
const m = parseFloat(e.style.marginRight || "0");
e.style.marginRight = m + l + "px";
}
w.current.x += R ? -l : l;
const h = r.height - i.height, g = parseFloat(e.style.height.substring(12));
e.style.height = `calc(100% + ${g + h}px)`, w.current.y += h;
}
const o = i.left - r.left, f = i.top - r.top;
if (o === 0 && f === 0) {
x.current = t;
return;
}
if (k.current) {
(x.current.defaultPosition.order !== t.defaultPosition.order || x.current.defaultPosition.col !== t.defaultPosition.col) && (u.current.x = 0, u.current.y = 0, e.style.transform = "", W()), x.current = t;
return;
}
if (Math.abs(f) < 15 && Math.abs(o) < 15) {
x.current = t;
return;
}
requestAnimationFrame(() => {
const l = c.current;
l && (l.style.transform = `translate(${o}px, ${f}px)`, l.style.transition = "transform 0s", requestAnimationFrame(() => {
l.style.transform = "", l.style.transition = `transform ${H}ms cubic-bezier(0.2, 0, 0, 1) 0s`;
}));
}), x.current = t;
}), Q && clearTimeout && typeof clearTimeout == "function" && (clearTimeout(C.current), C.current = window.setTimeout(() => {
C.current = void 0;
}, 200));
const y = t.defaultPosition, V = {
gridColumnStart: y.col,
gridColumnEnd: `span ${y.colSpan}`,
gridRowStart: y.row,
gridRowEnd: `span ${y.rowSpan}`,
outline: "none",
order: y.order,
display: "block",
...t.hintStyle
}, _ = {
gridColumnStart: y.col,
gridColumnEnd: `span ${y.colSpan}`,
gridRowStart: y.row,
gridRowEnd: `span ${y.rowSpan}`,
order: y.order
}, G = /* @__PURE__ */ n.createElement(
"div",
{
role: "listitem",
tabIndex: 0,
"aria-labelledby": typeof t.header == "string" ? t.header : `tile-${t.index}`,
"aria-keyshortcuts": "Enter",
"aria-dropeffect": "execute",
"aria-grabbed": !1,
className: O("k-tilelayout-item k-card", t.className),
style: { height: "100%", ..._, ...t.style },
onMouseDown: A,
onMouseUp: U
},
t.children,
/* @__PURE__ */ n.createElement(ee, { onPress: B, onResize: j, resizable: p, rtl: R })
);
return /* @__PURE__ */ n.createElement(n.Fragment, null, q && /* @__PURE__ */ n.createElement(
"div",
{
ref: (e) => {
s.current = e;
},
style: { position: "fixed", ...V },
className: O("k-layout-item-hint", t.hintClassName)
}
), /* @__PURE__ */ n.createElement(
Z,
{
ref: (e) => {
v.current = e, c.current = e ? e.element : null;
},
onDrag: b ? K : void 0,
onRelease: b ? $ : void 0,
onPress: b ? B : void 0
},
G
));
};
T.propTypes = {
update: a.func.isRequired,
index: a.number.isRequired,
defaultPosition: a.object.isRequired,
ignoreDrag: a.func,
onPress: a.func.isRequired,
onRelease: a.func.isRequired,
children: a.node,
style: a.object,
className: a.string,
hintStyle: a.object,
hintClassName: a.string,
header: a.any,
body: a.any,
item: a.any,
resizable: a.oneOf(["horizontal", "vertical", !0, !1]),
reorderable: a.bool
};
T.displayName = "KendoTileLayoutItem";
T.defaultProps = L;
export {
T as InternalTile
};