UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

142 lines (141 loc) 7.41 kB
import * as React from 'react'; import { Box, Flex } from 'rebass'; import FormLayout, { FormRow } from '../FormLayout'; import Input from '../Input'; import SimpleButton from '../SimpleButton'; import AdaptableInput from '../../View/Components/AdaptableInput'; import { useMemo } from 'react'; import { useAdaptable } from '../../View/AdaptableContext'; import { Select } from '../Select'; export function AdaptableFormComponentButtons({ formDef, onClick, defaultTone, disabledButtons, api, context, focusFirstButton = true, }) { return (React.createElement(React.Fragment, null, formDef.buttons.map((button, index) => { const buttonIcon = api.internalApi.getIconForButton(button, context, { height: 15, width: 15, }); let buttonStyle = api.internalApi.getStyleForButton(button, context ? context : { ...api.internalApi.buildBaseContext(), }); let buttonLabel = api.internalApi.getLabelForButton(button, context ? context : { ...api.internalApi.buildBaseContext(), }); let buttonTooltip = api.internalApi.getTooltipForButton(button, context ? context : { ...api.internalApi.buildBaseContext(), }); return (React.createElement(SimpleButton, { autoFocus: focusFirstButton && index === 0, disabled: disabledButtons[index], key: index, tooltip: buttonTooltip, icon: buttonIcon, tone: buttonStyle?.tone ?? defaultTone, variant: buttonStyle?.variant, "data-text": buttonLabel, className: buttonStyle?.className, marginLeft: index ? 2 : 0, onClick: () => { onClick(button); } }, buttonLabel)); }))); } export function AdaptableFormComponent({ formDef, data, onChange, onButtonClick, displayTitle, api, context, focusFirstButton, }) { const getFieldValue = (key) => data[key]; const setFieldValue = (key, value) => { const newData = { ...data, [key]: value }; onChange(newData); }; const adaptable = useAdaptable(); const disabledButtons = useMemo(() => formDef.buttons?.map((button) => { // defensive programming: conventionally context should ALWAYS be present for validating buttons const isValid = !!button.disabled && !!context ? !button.disabled(button, context) : true; return !isValid; }) ?? [], [data]); const renderLabel = (field) => { return (React.createElement(Box, { className: 'ab-FormLayout_column--label', style: { textAlign: 'end' } }, field.label)); }; const renderField = (field) => { const value = getFieldValue(field.name) ?? ''; const onChange = (event) => { if (field.fieldType === 'number') { const numberValue = Number(event.target.value); if (isNaN(numberValue)) { setFieldValue(field.name, null); } else { setFieldValue(field.name, numberValue); } } else { setFieldValue(field.name, event.target.value); } }; switch (field.fieldType) { case 'text': case 'number': case 'date': return (React.createElement(AdaptableInput, { type: field.fieldType, style: { width: '100%' }, name: field.name, value: value, onChange: onChange })); case 'select': let items = field.options.map((item) => ({ value: item.value, label: item.label, onClick: () => setFieldValue(field.name, item.value), })); return (React.createElement(Select, { style: { width: '100%' }, className: `ab-options__select`, options: items, onChange: (newValue) => setFieldValue(field.name, newValue), value: value })); case 'checkbox': return (React.createElement(Input, { type: "checkbox", name: field.name, checked: value, onChange: (event) => { setFieldValue(field.name, event.target.checked); } })); case 'textOutput': return (React.createElement(Box, { paddingLeft: 2, style: { textAlign: 'left' } }, value)); default: return React.createElement("div", null, "Unknown field type: ", field.fieldType); } }; // by default we have 2 columns: label & input const columns = formDef.config?.columns ?? [1, 2]; return (React.createElement(React.Fragment, null, displayTitle && formDef.title && (React.createElement(Box, { "data-name": "form-title", fontSize: 5, mb: 2, style: { fontWeight: 'bold' } }, formDef.title)), formDef.description && (React.createElement(Box, { "data-name": "form-description", mb: 3 }, formDef.description)), React.createElement(FormLayout, { onKeyDown: (event) => { const target = event.target; const targetName = target.name; const field = formDef.fields .map((field) => { if (Array.isArray(field)) { return field.filter((f) => f.name === targetName)[0]; } else { return field.name === targetName ? field : null; } }) .filter(Boolean)[0]; if (field && field.fieldType === 'number') { // for number fields // hook them up to the CellEditorKeyDown event // so Shortcuts work as expected const value = event.target.value; adaptable._emit('CellEditorKeyDown', { keyDownEvent: event, cellValue: value, columnId: field.name, updateValueCallback: (updatedValue) => { setFieldValue(field.name, updatedValue); }, }); } }, "data-name": "form-content", columns: columns, style: { overflow: 'auto' }, paddingRight: 1 }, formDef.fields?.map((field, index) => { if (Array.isArray(field)) { const rowFields = {}; field.map((fieldItem, index) => { const rowFieldIndex = 2 * index + 1; rowFields[rowFieldIndex] = renderLabel(fieldItem); rowFields[rowFieldIndex + 1] = renderField(fieldItem); }); return React.createElement(FormRow, { key: index, ...rowFields }); } else { return (React.createElement(FormRow, { key: field.name }, renderLabel(field), renderField(field))); } })), formDef.buttons ? (React.createElement(Flex, { "data-name": "form-buttons", marginTop: 3, flexDirection: "row", alignItems: "center", justifyContent: "center" }, React.createElement(AdaptableFormComponentButtons, { focusFirstButton: focusFirstButton, onClick: onButtonClick, disabledButtons: disabledButtons, defaultTone: "success", formDef: formDef, api: api, context: context }))) : null)); }