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.

239 lines (238 loc) 7.24 kB
import { jsx } from "react/jsx-runtime"; import { Select as Select$1 } from "@mantine/core"; import { uniq, flatten } from "lodash-es"; import { useState, forwardRef } from "react"; import { ComponentErrorBoundary } from "../errorBoundary/ComponentErrorBoundary.js"; import { useSetLatestRunInTaskQuery } from "../errorBoundary/LatestRunDetails.js"; import { useCommonLayoutStyle } from "../layout/useCommonLayoutStyle.js"; import { Loader } from "../loader/Loader.js"; import { displayTaskBackedError } from "../../errors/displayTaskBackedError.js"; import { useRegisterFormInput } from "../../state/components/form/useRegisterFormInput.js"; import { useInput } from "../../state/components/input/useInput.js"; import { useSelectState } from "../../state/components/select/useSelectState.js"; import { useComponentId } from "../../state/components/useId.js"; import { useTaskQuery } from "../../state/tasks/useTaskQuery.js"; const NUMBER_PREFIX = "__airplane_number__"; const defaultProps = { searchable: true }; const Select = (props) => { const [latestRun, setLatestRun] = useState(); if (doesUseTask(props)) { return /* @__PURE__ */ jsx(ComponentErrorBoundary, { componentName: Select.displayName, latestRun, children: /* @__PURE__ */ jsx(SelectWithTask, { ...props, setLatestRun }) }); } else { return /* @__PURE__ */ jsx(ComponentErrorBoundary, { componentName: Select.displayName, children: /* @__PURE__ */ jsx(ConnectedSelect, { ...props }) }); } }; Select.displayName = "Select"; const SelectWithTask = ({ task, outputTransform, setLatestRun, ...restProps }) => { const fullQuery = useSetLatestRunInTaskQuery(task, setLatestRun); const { error, loading, output, runID } = useTaskQuery(fullQuery); const data = output ? outputToData(output, outputTransform) : []; if (error) { return displayTaskBackedError({ error, taskSlug: fullQuery.slug, runID, componentName: "Select" }); } else { return /* @__PURE__ */ jsx(ConnectedSelect, { ...restProps, loading, data }); } }; const ConnectedSelect = (props) => { const id = useComponentId(props.id); const { state, dispatch } = useSelectState(id, { initialState: { disabled: props.disabled ?? props.defaultDisabled, value: props.value ?? props.defaultValue } }); const propsOnChange = props.onChange; const { inputProps } = useInput({ ...props, onChange: propsOnChange && ((v) => propsOnChange(v !== null ? convertSelectStringToOriginalType(v) : void 0)) }, state, dispatch, (v) => v !== null ? convertSelectStringToOriginalType(v) : void 0); useRegisterFormInput(id, "select"); const { data, validate: _, onChange: __, defaultDisabled: ___, defaultValue: ____, error: propsError, ...restProps } = props; const error = propsError || inputProps.error; const newData = data.map((item) => { if (typeof item === "string") { return item; } else if (typeof item === "number") { return numberToSelectItem(item); } else { return selectItemToMantine(item); } }); return /* @__PURE__ */ jsx(SelectComponent, { data: newData, ...defaultProps, ...inputProps, ...restProps, error }); }; const SelectComponent = /* @__PURE__ */ forwardRef((props, ref) => /* @__PURE__ */ jsx(SelectComponentWithoutRef, { ...props, innerRef: ref })); SelectComponent.displayName = "SelectComponent"; const SelectComponentWithoutRef = ({ loading, data, value, defaultValue, filter, withinPortal, innerRef, unstyled, disabled, ItemComponent, itemComponent, className, style, width, height, grow, ...restProps }) => { const { classes: layoutClasses, cx } = useCommonLayoutStyle({ width, height, grow }); const newProps = { data, value: maybeConvertSelectValueToString(value), defaultValue: maybeConvertSelectValueToString(defaultValue), filter: filter ? (value2, item) => { return filter(value2, mantineToSelectItem(item)); } : void 0 }; return /* @__PURE__ */ jsx(Select$1, { withinPortal, ref: innerRef, variant: unstyled ? "unstyled" : void 0, className: cx(layoutClasses.style, className), style, itemComponent: ItemComponent || itemComponent, ...newProps, ...restProps, icon: loading && /* @__PURE__ */ jsx(Loader, { size: "xs", color: "secondary" }), disabled: loading || disabled }); }; function outputToData(output, dataTransform) { if (!output) { return []; } if (dataTransform) { return dataTransform(output); } if (Array.isArray(output)) { return output; } const unwrappedOutput = unwrapOutput(output); if (unwrappedOutput) { return unwrappedOutput; } return []; } function doesUseTask(props) { return Boolean(props.task); } const unwrapOutput = (data) => { if (data && !Array.isArray(data) && typeof data === "object") { const keys = Object.keys(data); if (keys.length === 1) { const value = data[keys[0]]; if (Array.isArray(value) && value.every((item) => typeof item === "object")) { const columns = getColumns(value); if (columns.length === 1) { return unwrapSingleColumn(value, columns[0]); } if (value.length === 1) { const rowValues = Object.values(value[0]); if (rowValues.every((item) => typeof item === "string") || rowValues.every((item) => isSelectItem(item))) { return rowValues; } } } if (Array.isArray(value) && value.every((item) => typeof item === "string" || isSelectItem(item))) { return value; } } } return void 0; }; const getColumns = (value) => { return uniq(flatten(value.map((row) => Object.keys(row)))); }; const unwrapSingleColumn = (value, column_name) => { const unwrapped = value.map((value2) => value2[column_name]); if (unwrapped.every((item) => typeof item === "string") || unwrapped.every((item) => isSelectItem(item))) { return unwrapped; } return void 0; }; const isSelectItem = (item) => !Array.isArray(item) && typeof item === "object" && typeof item.value === "string"; const numberToSelectItem = (value) => { return { value: convertSelectValueToString(value), label: String(value) }; }; const convertSelectValueToString = (value) => { if (typeof value === "number") { return NUMBER_PREFIX + String(value); } else { return value; } }; const maybeConvertSelectValueToString = (value) => { if (value === void 0) { return null; } return convertSelectValueToString(value); }; const convertSelectStringToOriginalType = (s) => { if (s.startsWith(NUMBER_PREFIX)) { return Number(s.substring(NUMBER_PREFIX.length)); } else { return s; } }; const selectItemToMantine = (item) => { const { value, ...restFields } = item; return { value: convertSelectValueToString(value), ...restFields }; }; const mantineToSelectItem = (item) => { const { value, ...restFields } = item; return { value: convertSelectStringToOriginalType(value), ...restFields }; }; export { Select, SelectComponent, SelectComponentWithoutRef, outputToData }; //# sourceMappingURL=Select.js.map