Skip to content

Commit

Permalink
fix: Remove depth and transparentBorders from FieldProps, remove Obje…
Browse files Browse the repository at this point in the history
…ctArrayField, and refactor OpenObjectField (microsoft#6633)

* Remove depth and transparentBorder

* Update OneOfField dropdown styles

* Remove ObjectArrayField

* fix tests

* Refactor OpenObjectField

* updated test

* minor

* fix test

* minor

Co-authored-by: Ben Yackley <61990921+beyackle@users.noreply.github.com>
  • Loading branch information
tdurnford and beyackle committed May 21, 2021
1 parent 11cfb8e commit 28ecd66
Show file tree
Hide file tree
Showing 37 changed files with 157 additions and 861 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ export const AdaptiveForm: React.FC<AdaptiveFormProps> = function AdaptiveForm(p
onChange={(newData) => onChange({ ...formData, ...newData })}
/>
<SchemaField
isRoot
definitions={schema?.definitions}
depth={-1}
id={formData?.$designer?.id ? `root[${formData?.$designer?.id}]` : 'root'}
name="root"
rawErrors={errors}
Expand Down
37 changes: 37 additions & 0 deletions Composer/packages/adaptive-form/src/components/AddButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import React from 'react';
import styled from '@emotion/styled';
import { ActionButton, IButtonStyles } from 'office-ui-fabric-react/lib/components/Button';
import { FluentTheme } from '@uifabric/fluent-theme';
import formatMessage from 'format-message';

export const ButtonContainer = styled.div({
borderTop: `1px solid ${FluentTheme.palette.neutralLight}`,
width: '100%',
});

export const actionButtonStyles: IButtonStyles = {
root: {
fontSize: FluentTheme.fonts.small.fontSize,
fontWeight: FluentTheme.fonts.small.fontWeight,
color: FluentTheme.palette.themePrimary,
paddingLeft: 8,
height: 20,
},
};

type Props = {
onClick: () => void;
};

export const AddButton = ({ children, onClick }: React.PropsWithChildren<Props>) => {
return (
<ButtonContainer>
<ActionButton styles={actionButtonStyles} onClick={onClick}>
{children ?? formatMessage('Add new')}
</ActionButton>
</ButtonContainer>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const styles = {
header: css`
background-color: #eff6fc;
display: flex;
margin: 4px 0px;
margin: 4px -18px;
align-items: center;
`,
};
Expand Down
4 changes: 0 additions & 4 deletions Composer/packages/adaptive-form/src/components/FormRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,10 @@ export interface FormRowProps extends Omit<FieldProps, 'onChange'> {
export function getRowProps(rowProps: FormRowProps, field: string): FieldProps {
const {
id,
depth,
schema,
definitions,
value,
uiOptions,
transparentBorder,
className,
label,
rawErrors,
Expand Down Expand Up @@ -60,9 +58,7 @@ export function getRowProps(rowProps: FormRowProps, field: string): FieldProps {
uiOptions: newUiOptions,
value: !newUiOptions.additionalField && value ? value[field] : value,
onChange: !newUiOptions.additionalField ? handleChange : onChange,
depth,
definitions,
transparentBorder,
className,
onBlur,
onFocus,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ const FormTitle: React.FC<FormTitleProps> = (props) => {
<div>
<EditableField
ariaLabel={formatMessage('form title')}
depth={0}
fontSize={FontSizes.size20}
id="form-title"
name="$designer.name"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import { getUIOptions, resolveFieldWidget, resolveRef, getUiLabel, getUiPlacehol
import { ErrorMessage } from './ErrorMessage';

const schemaField = {
container: (depth = 0) => css`
container: (isRoot?: boolean) => css`
display: flex;
flex-direction: column;
margin: 10px ${depth === 0 ? 18 : 0}px;
margin: 10px ${isRoot ? 18 : 0}px;
label: SchemaFieldContainer;
`,
Expand All @@ -34,6 +34,7 @@ export const SchemaField: React.FC<FieldProps> = (props) => {
expression,
onBlur,
id,
isRoot,
...rest
} = props;
const formUIOptions = useFormConfig();
Expand Down Expand Up @@ -108,7 +109,7 @@ export const SchemaField: React.FC<FieldProps> = (props) => {
};

return (
<div className={className} css={schemaField.container(props.depth)}>
<div className={className} css={schemaField.container(isRoot)}>
<FieldWidget {...fieldProps} />
{!hideError && !uiOptions.hideError && error}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function WithTypeIcons(WrappedComponent: FieldWidget): FieldWidget {
<div css={styles.mainWrapper}>
{iconText && <div css={styles.iconWrapper}>{iconText}</div>}
<div css={styles.componentWrapper}>
<WrappedComponent hasIcon {...props} label={undefined} />
<WrappedComponent hasIcon {...props} label={false} />
</div>
</div>
</React.Fragment>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const field: FormRowProps = {
onChange: jest.fn(),
row: '',
definitions: {},
depth: 0,
id: 'test',
name: 'row',
schema: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ jest.mock('@bfc/extension-client', () => ({

const defaultProps: FieldProps = {
onChange: jest.fn(),
depth: 0,
id: 'test-id',
name: 'test-name',
definitions: { foo: { type: 'string' } },
Expand Down
100 changes: 22 additions & 78 deletions Composer/packages/adaptive-form/src/components/fields/ArrayField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,19 @@
// Licensed under the MIT License.
/** @jsx jsx */
import { jsx } from '@emotion/core';
import React, { useState } from 'react';
import { TextField } from 'office-ui-fabric-react/lib/TextField';
import { IconButton } from 'office-ui-fabric-react/lib/Button';
import { TooltipHost } from 'office-ui-fabric-react/lib/Tooltip';
import { SharedColors, NeutralColors, FontSizes } from '@uifabric/fluent-theme';
import React from 'react';
import { FieldProps } from '@bfc/extension-client';
import formatMessage from 'format-message';

import { getArrayItemProps, useArrayItems } from '../../utils';
import { FieldLabel } from '../FieldLabel';
import { AddButton } from '../AddButton';

import { arrayField } from './styles';
import { ArrayFieldItem } from './ArrayFieldItem';
import { UnsupportedField } from './UnsupportedField';

const ArrayField: React.FC<FieldProps<unknown[]>> = (props) => {
const {
value = [],
value,
onChange,
schema,
label,
Expand All @@ -29,89 +24,38 @@ const ArrayField: React.FC<FieldProps<unknown[]>> = (props) => {
uiOptions,
className,
required,
placeholder,
...rest
} = props;
const [newValue, setNewValue] = useState<string>();
const { arrayItems, handleChange, addItem } = useArrayItems(value, onChange);

const moreLabel = formatMessage('Item actions');

const handleNewChange = (_e: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue?: string) =>
setNewValue(newValue || '');

const handleKeyDown = (event) => {
if (event.key.toLowerCase() === 'enter') {
event.preventDefault();

if (newValue) {
addItem(newValue);
setNewValue('');
}
}
};

const itemSchema = Array.isArray(schema.items) ? schema.items[0] : schema.items;

const onClick = React.useCallback(() => {
addItem(undefined);
}, [addItem]);

if (!itemSchema || itemSchema === true) {
return <UnsupportedField {...props} />;
}

return (
<div className={className}>
<FieldLabel description={description} helpLink={uiOptions?.helpLink} id={id} label={label} required={required} />
<div>
{arrayItems.map((element, idx) => (
<ArrayFieldItem
{...rest}
key={element.id}
stackArrayItems
transparentBorder
error={rawErrors[idx]}
id={id}
label={false}
rawErrors={rawErrors[idx]}
schema={itemSchema}
uiOptions={uiOptions}
value={element.value}
{...getArrayItemProps(arrayItems, idx, handleChange)}
/>
))}
</div>
<div css={arrayField.inputFieldContainer}>
<div css={arrayField.field}>
<TextField
ariaLabel={formatMessage('New value')}
data-testid="string-array-text-input"
iconProps={{
iconName: 'ReturnKey',
style: { color: SharedColors.cyanBlue10, opacity: 0.6 },
}}
placeholder={placeholder}
styles={{ root: { width: '100%' } }}
value={newValue}
onChange={handleNewChange}
onKeyDown={handleKeyDown}
/>
<TooltipHost content={moreLabel}>
<IconButton
disabled
ariaLabel={moreLabel}
menuIconProps={{ iconName: 'MoreVertical' }}
styles={{
menuIcon: {
backgroundColor: NeutralColors.white,
color: NeutralColors.gray130,
fontSize: FontSizes.size16,
},
rootDisabled: {
backgroundColor: NeutralColors.white,
},
}}
/>
</TooltipHost>
</div>
</div>
{arrayItems.map((element, idx) => (
<ArrayFieldItem
{...rest}
key={element.id}
error={rawErrors[idx]}
id={id}
label={false}
rawErrors={rawErrors[idx]}
schema={itemSchema}
uiOptions={uiOptions}
value={element.value}
{...getArrayItemProps(arrayItems, idx, handleChange)}
/>
))}
<AddButton onClick={onClick} />
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ const ArrayFieldItem: React.FC<ArrayFieldItemProps> = (props) => {
onRemove,
index,
label,
depth,
onBlur,
stackArrayItems,
transparentBorder,
uiOptions,
value,
className,
Expand Down Expand Up @@ -89,12 +86,10 @@ const ArrayFieldItem: React.FC<ArrayFieldItemProps> = (props) => {
<div css={arrayItem.field}>
<SchemaField
{...rest}
css={arrayItem.schemaFieldOverride(!!stackArrayItems)}
depth={depth + 1}
label={!stackArrayItems || label === false ? false : undefined}
css={arrayItem.schemaFieldOverride}
label={label}
placeholder={undefined}
rawErrors={typeof rawErrors === 'object' ? rawErrors[index] : rawErrors}
transparentBorder={!stackArrayItems ? transparentBorder : undefined}
uiOptions={{ ...uiOptions, placeholder: undefined }}
value={value}
onBlur={handleBlur}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,11 @@ import { FieldProps } from '@bfc/extension-client';
interface EditableFieldProps extends Omit<FieldProps, 'definitions'> {
fontSize?: string;
styles?: Partial<ITextFieldStyles>;
transparentBorder?: boolean;
ariaLabel?: string;
}

const EditableField: React.FC<EditableFieldProps> = (props) => {
const {
depth,
styles = {},
placeholder,
fontSize,
onChange,
onBlur,
value,
id,
error,
className,
transparentBorder,
ariaLabel,
} = props;
const { styles = {}, placeholder, fontSize, onChange, onBlur, value, id, error, className, ariaLabel } = props;
const [editing, setEditing] = useState<boolean>(false);
const [hasFocus, setHasFocus] = useState<boolean>(false);
const [localValue, setLocalValue] = useState<string | undefined>(value);
Expand All @@ -55,7 +41,7 @@ const EditableField: React.FC<EditableFieldProps> = (props) => {
let borderColor: string | undefined = undefined;

if (!editing && !error) {
borderColor = localValue || transparentBorder || depth > 1 ? 'transparent' : NeutralColors.gray30;
borderColor = localValue ? 'transparent' : NeutralColors.gray30;
}

return (
Expand Down
Loading

0 comments on commit 28ecd66

Please sign in to comment.