UNPKG

@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
/** * @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 };