@airplane/views
Version:
A React library for building Airplane views. Views components are optimized in style and functionality to produce internal apps that are easy to build and maintain.
223 lines (222 loc) • 7.56 kB
JavaScript
import { jsx } from "react/jsx-runtime";
import { useRef, useCallback, useMemo } from "react";
import { UnconnectedButton } from "../button/Button.js";
import { getFullMutation, getSlug } from "../query.js";
import { fontFamily } from "../theme/typography.js";
import { useTableState } from "../../state/components/table/useTableState.js";
import { useComponentId } from "../../state/components/useId.js";
import { TableComponent } from "./TableComponent.js";
const ConnectedTable = (props) => {
const tableComponentRef = useRef(null);
const clearSelection = useCallback(() => tableComponentRef.current.toggleAllRowsSelected(false), [tableComponentRef]);
const id = useComponentId(props.id);
const {
changeRowSelection,
setRowActionResult
} = useTableState(id, {
singleSelect: props.rowSelection === "single",
clearSelection
});
const canvas = useMemo(() => document.createElement("canvas"), []);
const rowActions = getRowActions(props.rowActions, setRowActionResult);
const rowActionsMenu = getRowActions(props.rowActionsMenu, setRowActionResult, true);
const rowActionsMenuWidth = getRowActionsMenuWidth(props.rowActionsMenu, canvas);
const columns = useColumns(props.data, props.columns, props.columnsTransform);
return /* @__PURE__ */ jsx(TableComponent, { ...props, columns, rowActions, rowActionsMenu, rowActionsMenuWidth, onRowSelectionChanged: changeRowSelection, tableRef: tableComponentRef });
};
function getRowActions(rowActions, setRowActionResult, inMenu) {
if (rowActions === void 0) {
return void 0;
}
const arrayRowActions = Array.isArray(rowActions) ? rowActions : [rowActions];
return arrayRowActions.map((rowAction) => {
if (typeof rowAction === "function") {
return rowAction;
}
if (typeof rowAction !== "string" && !("slug" in rowAction) && !("fn" in rowAction)) {
const WrappedButton2 = ({
row
}) => {
return /* @__PURE__ */ jsx(RowActionButton, { rowAction, row, inMenu });
};
return WrappedButton2;
}
const WrappedButton = ({
row
}) => {
return /* @__PURE__ */ jsx(RowActionButtonWithTask, { rowAction, setRowActionResult, row, inMenu });
};
return WrappedButton;
});
}
function getRowActionsMenuWidth(rowActions, canvas) {
if (rowActions === void 0) {
return void 0;
}
const arrayRowActions = Array.isArray(rowActions) ? rowActions : [rowActions];
if (arrayRowActions.some((rowAction) => typeof rowAction === "function") || arrayRowActions.length === 0) {
return void 0;
}
const context = canvas.getContext("2d");
if (context) {
context.font = `14px ${fontFamily}`;
}
const getTextWidth = (text) => {
if (context) {
return context.measureText(text).width;
}
return 10 * text.length;
};
const widths = arrayRowActions.map((rowAction) => {
if (typeof rowAction === "function") {
throw new Error("component row action has no width");
}
let label = "";
if (typeof rowAction !== "string" && !("slug" in rowAction) && !("fn" in rowAction)) {
label = rowAction.label;
} else {
const fullMutation = getFullMutation(rowAction);
const slug = getSlug(fullMutation);
label = rowAction.label ?? slug;
}
return getTextWidth(label) * 1.05 + 20;
});
return widths.reduce((a, b) => Math.max(a, b)) + 8;
}
const RowActionButton = ({
rowAction,
row,
inMenu
}) => {
const label = rowAction.label;
const buttonDisplayProps = getButtonDisplayProps(rowAction, inMenu);
if ("href" in rowAction && rowAction.href) {
return /* @__PURE__ */ jsx(UnconnectedButton, { href: rowAction.href(row), newTab: rowAction.newTab, stopPropagation: true, ...buttonDisplayProps, children: label });
} else {
return /* @__PURE__ */ jsx(UnconnectedButton, { confirm: typeof rowAction.confirm === "function" ? rowAction.confirm(row) : rowAction.confirm, onClick: () => {
rowAction.onClick(row);
}, stopPropagation: true, ...buttonDisplayProps, children: label });
}
};
const RowActionButtonWithTask = ({
rowAction,
setRowActionResult,
row,
inMenu
}) => {
const fullMutation = getFullMutation(rowAction);
const slug = getSlug(fullMutation);
const label = rowAction.label ?? slug;
const {
onSuccess: fullMutationOnSuccess,
onError: fullMutationOnError
} = fullMutation;
const onSuccess = useCallback(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(output, runID) => {
setRowActionResult({
output
});
fullMutationOnSuccess == null ? void 0 : fullMutationOnSuccess(output, runID);
},
[setRowActionResult, fullMutationOnSuccess]
);
const onError = useCallback(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(output, error, runID, status) => {
setRowActionResult({
output,
error
});
fullMutationOnError == null ? void 0 : fullMutationOnError(output, error, runID);
},
[setRowActionResult, fullMutationOnError]
);
let getParamsFromRow = (row2) => row2;
if (rowAction.getParamsFromRow) {
getParamsFromRow = rowAction.getParamsFromRow;
} else if (rowAction.rowTransform) {
getParamsFromRow = rowAction.rowTransform;
}
const r = getParamsFromRow(row);
const m = {
...fullMutation,
params: {
...r,
...fullMutation == null ? void 0 : fullMutation.params
},
onSuccess,
onError
};
const buttonDisplayProps = getButtonDisplayProps(rowAction, inMenu);
return /* @__PURE__ */ jsx(UnconnectedButton, { task: m, confirm: typeof rowAction.confirm === "function" ? rowAction.confirm(row) : rowAction.confirm, stopPropagation: true, ...buttonDisplayProps, children: label });
};
const getButtonDisplayProps = (rowAction, inMenu) => {
const buttonProps = {
compact: true,
size: "sm",
preset: rowAction.preset,
variant: rowAction.variant || (rowAction.preset ? void 0 : "subtle"),
color: rowAction.color
};
if (rowAction.disabled !== void 0) {
buttonProps.disabled = rowAction.disabled;
}
if (inMenu) {
buttonProps.fullWidth = true;
buttonProps.leftAlign = true;
buttonProps.disableFocusRing = true;
buttonProps.radius = "sm";
}
return buttonProps;
};
const useColumns = (data, columns, columnsTransform) => {
return useMemo(() => {
const outputColumns = columns ? createColumns(columns) : tryInferColumns(data);
if (columnsTransform) {
return columnsTransform(outputColumns);
}
return outputColumns;
}, [data, columns, columnsTransform]);
};
const createColumns = (columns) => {
return columns.map((colOrAccessor) => {
if (isColumn(colOrAccessor)) {
return {
...colOrAccessor,
label: colOrAccessor.label === void 0 ? colOrAccessor.accessor.toString() : colOrAccessor.label
};
} else {
return {
accessor: colOrAccessor,
label: colOrAccessor.toString()
};
}
});
};
const isColumn = (colOrAccessor) => {
return typeof colOrAccessor === "object";
};
const tryInferColumns = (data) => {
if (data.length) {
const keySet = /* @__PURE__ */ new Set();
const keys = [];
for (const row of data) {
for (const key of Object.keys(row)) {
if (!keySet.has(key)) {
keys.push(key);
keySet.add(key);
}
}
}
return keys.map((key) => ({
label: key.toString(),
accessor: key
}));
}
return [];
};
export {
ConnectedTable
};
//# sourceMappingURL=ConnectedTable.js.map