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