UNPKG

@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
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