ar-design
Version:
AR Design is a (react | nextjs) ui library.
168 lines (167 loc) • 11.1 kB
JavaScript
import React, { Fragment, memo, useEffect, useRef, useState } from "react";
import { ARIcon } from "../../../icons";
import Checkbox from "../../../form/checkbox";
import Editable from "./Editable";
import { useTranslation } from "../../../../libs/core/application/hooks";
function TBody({ data, columns, refs, methods, states, config }) {
// refs
const _hasMeasured = useRef(false);
const _tBodyTR = useRef([]);
const _tHeadTH = useRef([]);
// states
const [triggerForRender, setTriggerForRender] = useState(false);
const [rowHeights, setRowHeights] = useState([]);
// variables
const _subrowSelector = config.subrow?.selector ?? "subitems";
const _subrowButton = config.subrow?.button ?? true;
// hooks
const { t } = useTranslation(String(config.locale ?? "tr"));
// methods
const renderRow = (item, index, deph, parentKey = "") => {
const id = methods.trackBy?.(item) ?? index.toString();
const key = parentKey ? `${parentKey}.${id}` : id;
const isHasSubitems = _subrowSelector in item;
return (React.createElement(Fragment, { key: `row-${index}` },
React.createElement("tr", { ref: (element) => {
_tBodyTR.current[index] = element;
}, ...(methods.rowBackgroundColor ? { style: { backgroundColor: methods.rowBackgroundColor(item) } } : {}), ...(methods.onDnD && data.length > 1 ? { className: "draggable", draggable: true } : {}) },
methods.selections && (React.createElement("td", { ref: (element) => {
_tHeadTH.current[index] = element;
}, className: "flex justify-content-center sticky-left", style: { display: "flex", alignItems: "center", height: rowHeights[index] ?? 0 }, "data-sticky-position": "left" },
React.createElement(Checkbox, { key: Date.now(), ref: (element) => {
if (!element)
return;
refs._checkboxItems.current[index] = element;
}, variant: "filled", color: "green", checked: refs._selectionItems.current.some((selectionItem) => methods.trackBy?.(selectionItem) === methods.trackBy?.(item)), onChange: (event) => {
const key = methods.trackBy?.(item);
if (event.target.checked) {
if (!refs._selectionItems.current.some((_item) => methods.trackBy?.(_item) === key)) {
refs._selectionItems.current = [...refs._selectionItems.current, item];
}
}
else {
refs._selectionItems.current = refs._selectionItems.current.filter((_item) => methods.trackBy?.(_item) !== key);
}
methods.selections?.(refs._selectionItems.current);
setTriggerForRender((prev) => !prev);
} }))),
isHasSubitems && _subrowButton ? (React.createElement("td", null, item[_subrowSelector] && (React.createElement("div", { className: "subitem-open-button-wrapper" },
React.createElement("span", { className: `subitem-open-button ${(states.showSubitems.get[key] && "opened") ?? ""}`, onClick: () => {
states.showSubitems.set((prev) => ({
...prev,
[`${key}`]: !prev[`${key}`],
}));
} }))))) : isHasSubitems && _subrowButton ? (React.createElement("td", { style: { width: 0, minWidth: 0 } })) : null,
columns.map((column, cIndex) => {
return renderCell({
item,
column,
index,
cIndex,
depth: deph * (config.isTreeView ? 1.75 : 0),
level: 0,
height: rowHeights[index] ?? 0,
});
})),
states.showSubitems.get[key] && item[_subrowSelector] && (React.createElement(SubitemList, { items: item[_subrowSelector], columns: columns, index: index, depth: 1.5, parentKey: key }))));
};
const renderCell = ({ item, column, index, cIndex, depth, level, height = 0, isSubrows = false }) => {
let render;
// `column.key` bir string ise
if (typeof column.key !== "object")
render = column.render ? column.render(item) : item[column.key];
// `column.key` bir nesne ise ve `nestedKey` mevcutsa
else if (typeof column.key === "object") {
const _item = item[column.key.field];
if (_item && typeof _item === "object") {
render = column.render ? column.render(item) : _item[column.key.nestedKey];
}
}
else
render = null;
const _className = [];
if (column.config?.alignContent)
_className.push(`align-content-${column.config.alignContent}`);
if (column.config?.sticky)
_className.push(`sticky-${column.config.sticky}`);
if (column.config?.textWrap)
_className.push(`text-${column.config.textWrap}`);
return (React.createElement("td", { key: `cell-${index}-${cIndex}`, className: _className.join(" "), style: {
...(column.config?.sticky ? { height } : {}),
...(column.config?.width
? { width: column.config.width, minWidth: column.config.width, maxWidth: column.config.width }
: {}),
}, "data-sticky-position": column.config?.sticky },
React.createElement("div", { style: { paddingLeft: cIndex === (methods.selections ? 1 : 0) ? `${depth == 0 ? 1 : depth}rem` : "" }, className: "table-cell" },
config.isTreeView && cIndex === 0 && (React.createElement(React.Fragment, null,
isSubrows &&
Array.from({ length: level }).map((_, i) => {
if (i > 0)
i *= 1.655;
return (React.createElement("div", { key: `last-before-${i}`, style: { left: `${i + 0.65}rem` }, className: "last-before" }));
}),
React.createElement("div", { className: "before" }))),
React.isValidElement(render) ? (render) : column.editable && methods.onEditable ? (React.createElement(Editable, { c: column, item: item, trackByValue: methods.trackBy?.(item) ?? "", onEditable: methods.onEditable, config: config })) : (React.createElement("span", null, render)),
config.isTreeView && cIndex === 0 && (React.createElement("div", { className: "after" },
React.createElement("div", { className: "circle" }))))));
};
const SubitemList = ({ items, columns, index, depth, level = 1, parentKey = "" }) => {
if (config.subrow?.render) {
return (React.createElement("tr", { className: `subrow-item ${_subrowButton ? "type-b" : "type-a"}`, "data-level": level },
_subrowButton && React.createElement("td", { style: { ...config.subrow.render.styles, width: 0, minWidth: 0 } }),
React.createElement("td", { colSpan: columns.length || 1, style: { ...config.subrow.render.styles, padding: "7.5px 7.5px 7.5px 0" } }, config.subrow?.render.element(items) ?? React.createElement(React.Fragment, null))));
}
return items.map((subitem, subindex) => {
const id = methods.trackBy?.(subitem) ?? subindex.toString();
const key = `${parentKey}.${id}`;
const _subitem = subitem[_subrowSelector];
const isHasSubitems = _subrowSelector in subitem;
return (React.createElement(Fragment, { key: `subitem-${index}-${subindex}-${Math.random()}` },
React.createElement("tr", { className: `subrow-item ${_subrowButton ? "type-b" : "type-a"}`, "data-level": level },
isHasSubitems && _subrowButton ? (React.createElement("td", null,
React.createElement("div", { className: "subitem-open-button-wrapper" },
React.createElement("span", { className: `${(states.showSubitems.get[key] && "opened") ?? ""} ${!_subitem && "passive"}`, onClick: () => {
if (!_subitem)
return;
states.showSubitems.set((prev) => ({
...prev,
[key]: !prev[key],
}));
} })))) : !isHasSubitems && _subrowButton ? (React.createElement("td", { style: { width: 0, minWidth: 0 } })) : null,
!config.subrow?.render ? (columns.map((column, cIndex) => renderCell({
item: subitem,
column,
index,
cIndex,
depth: depth * (config.isTreeView ? 2.25 : 1.75),
level,
height: 0,
isSubrows: true,
}))) : (React.createElement("td", { colSpan: columns.length || 1 }, config.subrow?.render.element(items) ?? React.createElement(React.Fragment, null)))),
states.showSubitems.get[key] && _subitem && (React.createElement(SubitemList, { items: _subitem, columns: columns, index: subindex, depth: depth + 0.75, level: level + 1, parentKey: key }))));
});
};
// useEffects
useEffect(() => {
if (_hasMeasured.current)
return;
if (!data || data.length === 0)
return;
const heights = _tBodyTR.current.map((el) => (el ? el.getBoundingClientRect().height : 0));
setRowHeights(heights);
setTriggerForRender((prev) => !prev);
_hasMeasured.current = true;
}, [data]);
useEffect(() => {
if (Array.isArray(refs._checkboxItems.current) && refs._checkboxItems.current.length > 0) {
const allChecked = refs._checkboxItems.current.every((item) => item?.checked === true);
states.setSelectAll.set(allChecked);
}
}, [triggerForRender]);
return data.length > 0 ? (data.map((item, index) => React.createElement(React.Fragment, { key: index }, renderRow(item, index, 1)))) : (React.createElement("tr", null,
React.createElement("td", { colSpan: columns.length || 1 },
React.createElement("div", { className: "no-item" },
React.createElement(ARIcon, { icon: "Inbox-Fill", fill: "var(--gray-300)", size: 64, style: { position: "relative", zIndex: 1 } }),
React.createElement("span", null, t("Table.Body.NoData.Text"))))));
}
export default memo(TBody);