@trail-ui/react
Version:
313 lines (305 loc) • 12.4 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/editable-table/editable-table-header.tsx
var editable_table_header_exports = {};
__export(editable_table_header_exports, {
default: () => EditableTableHeader
});
module.exports = __toCommonJS(editable_table_header_exports);
var import_react_table = require("@tanstack/react-table");
var import_icons = require("@trail-ui/icons");
// src/editable-table/focus-handler/focus-handler-provider.tsx
var import_react2 = require("react");
// src/editable-table/table-context/table-context-provider.tsx
var import_react = require("react");
var import_jsx_runtime = require("react/jsx-runtime");
var EditableTableContext = (0, import_react.createContext)({
handleSaveData: () => {
},
idSelector: () => {
},
table: {},
tableName: "",
groupData: [],
allowBulkGroupSelection: false,
doesRowHeaderExist: false
});
function useTableContext(cell) {
const { handleSaveData, ...rest } = (0, import_react.useContext)(EditableTableContext);
function updateData(value) {
var _a, _b;
if (cell) {
const accessorKey = cell.column.columnDef.accessorKey;
const groupId = (_a = cell.row.original) == null ? void 0 : _a.editableTableGroupId;
handleSaveData({
accessorKey,
columnId: cell.column.id,
rowId: rest.idSelector(cell.row.original),
value,
...groupId ? { groupId } : {}
});
(_b = rest.table.options.meta) == null ? void 0 : _b.updateData(cell.row.id, accessorKey, value);
}
}
return {
...cell ? { updateData } : {},
...rest
};
}
// src/editable-table/focus-handler/focus-handler-provider.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var FocusDataContext = (0, import_react2.createContext)({
columnIndex: 0,
rowId: null,
cellType: "headerCell" /* headerCell */,
groupId: null,
rowIndex: 0
});
var FocusDispatchContext = (0, import_react2.createContext)(() => {
});
function useFocusHandler({
cellType,
columnIndex,
groupId,
rowId,
rowIndex
}) {
var _a;
const focusedCell = (0, import_react2.useContext)(FocusDataContext);
const setFocusedCell = (0, import_react2.useContext)(FocusDispatchContext);
const { allowBulkGroupSelection, tableRef, table, serverPagination } = useTableContext();
const filteredRows = (_a = table == null ? void 0 : table.getRowModel().rows) != null ? _a : [];
const localRowIndex = filteredRows.findIndex((row) => row.id === rowId);
const isCurrentCellFocused = (0, import_react2.useMemo)(() => {
var _a2;
const isFocused = ((_a2 = tableRef.current) == null ? void 0 : _a2.contains(document.activeElement)) && focusedCell.cellType === cellType;
switch (cellType) {
case "headerCell" /* headerCell */:
case "footerCell" /* footerCell */:
return isFocused && focusedCell.columnIndex === columnIndex;
case "groupHeaderCell" /* groupHeaderCell */: {
let isGroup = focusedCell.groupId === groupId;
if (allowBulkGroupSelection) {
isGroup && (isGroup = columnIndex === 0 ? focusedCell.columnIndex === 0 : focusedCell.columnIndex > 0);
}
return isFocused && isGroup;
}
case "dataCell" /* dataCell */:
return isFocused && focusedCell.rowIndex === localRowIndex && focusedCell.columnIndex === columnIndex;
default:
return false;
}
}, [focusedCell, columnIndex, cellType, groupId, localRowIndex, allowBulkGroupSelection]);
const focusCurrentCell = (0, import_react2.useCallback)(() => {
setFocusedCell == null ? void 0 : setFocusedCell({ columnIndex, rowId, cellType, groupId, rowIndex });
}, [columnIndex, rowId, cellType, groupId, rowIndex]);
const resetFocus = (0, import_react2.useCallback)(() => {
setFocusedCell == null ? void 0 : setFocusedCell({
cellType: "headerCell" /* headerCell */,
rowId: null,
groupId: null,
rowIndex: -1,
columnIndex: 0
});
}, []);
return {
isCurrentCellFocused,
focusCurrentCell,
resetFocus
};
}
// src/editable-table/editable-table-header.tsx
var import_react4 = require("react");
// src/_utils/utils.tsx
var import_utils = require("@react-aria/utils");
var import_react3 = __toESM(require("react"));
var import_react_aria = require("react-aria");
var import_react_dom = __toESM(require("react-dom"));
var import_jsx_runtime3 = require("react/jsx-runtime");
if (typeof HTMLTemplateElement !== "undefined") {
const getFirstChild = Object.getOwnPropertyDescriptor(Node.prototype, "firstChild").get;
Object.defineProperty(HTMLTemplateElement.prototype, "firstChild", {
configurable: true,
enumerable: true,
get: function() {
if (this.dataset.reactAriaHidden) {
return this.content.firstChild;
} else {
return getFirstChild.call(this);
}
}
});
}
var HiddenContext = (0, import_react3.createContext)(false);
var hiddenFragment = typeof DocumentFragment !== "undefined" ? new DocumentFragment() : null;
function replaceSpacesWithHyphens(str) {
return str.toLowerCase().trim().replace(/\s+/g, "-");
}
// src/editable-table/editable-table-header.tsx
var import_jsx_runtime4 = require("react/jsx-runtime");
function EditableTableHeader({
table,
selectAllCheckBoxName,
tableName
}) {
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("thead", { className: "sticky top-0 z-10 after:absolute after:bottom-0 after:w-full after:border-t after:border-t-neutral-200", children: table.getHeaderGroups().map((group) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tr", { children: group.headers.map((header) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
HeaderCell,
{
header,
tableName,
selectAllCheckBoxName
},
header.id
)) }, group.id)) });
}
function HeaderCell({
header,
selectAllCheckBoxName,
tableName
}) {
var _a, _b;
const cellRef = (0, import_react4.useRef)(null);
const { table, tableRef } = useTableContext();
const { isCurrentCellFocused, focusCurrentCell } = useFocusHandler({
cellType: "headerCell" /* headerCell */,
columnIndex: header.column.getIndex(),
groupId: null,
rowId: null,
rowIndex: -1
});
const canSort = header.column.getCanSort();
const isCheckbox = ((_a = header.column.columnDef.meta) == null ? void 0 : _a.type) === "checkbox";
const tabIndex = ((_b = tableRef.current) == null ? void 0 : _b.contains(document.activeElement)) ? isCurrentCellFocused ? 0 : -1 : 0 === header.column.getIndex() ? 0 : -1;
const classes = "border-b border-r bg-neutral-100 p-2 text-sm font-normal last:border-r-0";
function onFocusChange() {
if (!isCurrentCellFocused && 0 === header.column.getIndex()) {
focusCurrentCell();
}
}
const renderSortIcon = (sorted) => {
switch (sorted) {
case "asc":
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons.ArrowUpIcon, { className: "h-4 w-4 text-purple-600" });
case "desc":
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons.ArrowDownIcon, { className: "h-4 w-4 text-purple-600" });
default:
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons.CaretUpDownIcon, { className: "h-4 w-4 text-neutral-600" });
}
};
const toggleCheckbox = (elem) => {
const checkbox = elem.querySelector('input[type="checkbox"]');
checkbox == null ? void 0 : checkbox.click();
};
(0, import_react4.useEffect)(() => {
var _a2;
if (isCurrentCellFocused) {
(_a2 = cellRef.current) == null ? void 0 : _a2.focus();
}
}, [isCurrentCellFocused]);
if (isCheckbox) {
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
"td",
{
id: header.column.id,
style: {
minWidth: header.column.columnDef.size === 100 ? "auto" : header.column.columnDef.size,
maxWidth: header.column.columnDef.size === 100 ? "auto" : header.column.columnDef.size,
width: header.column.columnDef.size === 100 ? "auto" : header.column.columnDef.size
},
className: `${classes} text-center`,
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
"div",
{
id: `${replaceSpacesWithHyphens(tableName)}-${header.column.getIndex()}`,
ref: cellRef,
role: "checkbox",
"aria-label": selectAllCheckBoxName != null ? selectAllCheckBoxName : `Select all ${tableName}`,
"aria-checked": table.getIsAllRowsSelected() ? "true" : table.getIsSomeRowsSelected() ? "mixed" : "false",
className: "th-content flex h-6 w-6 cursor-pointer items-center justify-center outline-purple-600",
onClick: (e) => toggleCheckbox(e.currentTarget),
onKeyDown: (e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
toggleCheckbox(e.currentTarget);
}
},
tabIndex,
onFocus: onFocusChange,
children: (0, import_react_table.flexRender)(header.column.columnDef.header, header.getContext())
}
)
},
header.id
);
}
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
"th",
{
id: header.column.id,
scope: "col",
className: `${classes} text-left`,
style: {
minWidth: header.column.columnDef.size === 100 ? "auto" : header.column.columnDef.size,
width: header.column.columnDef.size === 100 ? "auto" : header.column.columnDef.size
},
...canSort && {
"aria-sort": header.column.getIsSorted() === "asc" ? "ascending" : header.column.getIsSorted() === "desc" ? "descending" : "none"
},
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
"div",
{
ref: cellRef,
className: `th-content flex items-center justify-between rounded px-2 text-sm font-semibold outline-purple-600 focus:outline focus:outline-2 ${canSort ? "cursor-pointer select-none" : ""}`,
onClick: () => {
if (canSort) {
header.column.toggleSorting();
}
focusCurrentCell();
},
onKeyDown: (e) => {
if (e.key === " " && canSort) {
e.preventDefault();
header.column.toggleSorting();
}
},
tabIndex,
onFocus: onFocusChange,
children: [
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { id: `${replaceSpacesWithHyphens(tableName)}-${header.column.getIndex()}`, children: (0, import_react_table.flexRender)(header.column.columnDef.header, header.getContext()) }),
canSort && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sr-only", children: "Sortable" }),
renderSortIcon(header.column.getIsSorted())
] })
]
}
)
},
header.id
);
}