Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(NewSettingForArray): added new settings to the array #83

Merged
merged 12 commits into from
Aug 29, 2023
2 changes: 2 additions & 0 deletions docs/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ type Spec = ArraySpec | BooleanSpec | NumberSpec | ObjectSpec | StringSpec;
| viewSpec.layoutDescription | `string` | | Additional description/hint for [Layout](./config.md#layouts) |
| viewSpec.layoutOpen | `boolean` | | Expand [Layout](./config.md#layouts) at the first rendering |
| viewSpec.itemLabel | `string` | | Text for the button that adds an array element |
| viewSpec.itemPrefix | `string` | | Additional text for an element in the array |
| viewSpec.table | `{label: string; property: string;}[]` | | An array whose elements are used to establish column names and their order, if `type === "table"` |
| viewSpec.link | `any` | | A field containing information for forming a [link](#link) for a value |
| viewSpec.placeholder | `string` | | A short hint displayed in the field before the user enters the value |
| viewSpec.addButtonPosition | `"down"/"right"` | | The location of the button adding a new element to the array. Default value "down". |

### BooleanSpec

Expand Down
2 changes: 2 additions & 0 deletions src/lib/core/types/specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ export interface ArraySpec<LinkType = any> {
layoutDescription?: string;
layoutOpen?: boolean;
itemLabel?: string;
itemPrefix?: string;
table?: {
label: string;
property: string;
}[];
link?: LinkType;
placeholder?: string;
addButtonPosition?: 'down' | 'right';
};
}

Expand Down
25 changes: 25 additions & 0 deletions src/lib/kit/components/Inputs/ArrayBase/ArrayBase.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@import '../../../styles/variables';

.#{$ns}array-base {
&_add-button-right {
display: flex;
align-items: flex-end;
}

&__items-wrapper {
&_add-button-down {
margin-bottom: 15px;
}
}

&__item-prefix {
margin-top: -7px;
margin-bottom: 8px;
}

&__add-button {
&_right {
margin-left: 4px;
}
}
}
141 changes: 91 additions & 50 deletions src/lib/kit/components/Inputs/ArrayBase/ArrayBase.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';

import {Plus} from '@gravity-ui/icons';
import {Button, Icon} from '@gravity-ui/uikit';
import {Button, Icon, Label} from '@gravity-ui/uikit';
import _ from 'lodash';

import {
Expand All @@ -19,6 +19,11 @@ import {
isObjectSpec,
transformArrIn,
} from '../../../../core';
import {block} from '../../../utils';

import './ArrayBase.scss';

const b = block('array-base');

export const ArrayBase: ArrayInput = ({spec, name, arrayInput, input}) => {
const keys = React.useMemo(
Expand All @@ -32,20 +37,6 @@ export const ArrayBase: ArrayInput = ({spec, name, arrayInput, input}) => {

const itemSpecCorrect = React.useMemo(() => isCorrectSpec(spec.items), [spec.items]);

const onItemAdd = React.useCallback(() => {
let item;

if (!spec.items?.required) {
if (isArraySpec(spec.items)) {
item = {[OBJECT_ARRAY_FLAG]: true, [OBJECT_ARRAY_CNT]: 0};
} else if (isObjectSpec(spec.items)) {
item = {};
}
}

arrayInput.onItemAdd(item);
}, [arrayInput.onItemAdd, spec.items]);

const getItemSpec = React.useCallback(
(idx: number): typeof spec.items | null => {
if (!itemSpecCorrect) {
Expand Down Expand Up @@ -80,6 +71,55 @@ export const ArrayBase: ArrayInput = ({spec, name, arrayInput, input}) => {
[input.onChange, input.name],
);

const AddButton: React.FC = React.useCallback(() => {
let onClick = () => {
let item;

if (!spec.items?.required) {
if (isArraySpec(spec.items)) {
item = {[OBJECT_ARRAY_FLAG]: true, [OBJECT_ARRAY_CNT]: 0};
} else if (isObjectSpec(spec.items)) {
item = {};
}
}

arrayInput.onItemAdd(item);
};

let qa = `${name}-add-item`;
let title = spec.viewSpec.itemLabel;

if (!arrayInput.value && spec.defaultValue) {
onClick = () => {
input.onChange(transformArrIn<ArrayValue, FieldArrayValue>(spec.defaultValue!));
};

qa = `${name}-init-arr`;
title = spec.viewSpec.layoutTitle;
}

return (
<Button
onClick={onClick}
disabled={spec.viewSpec.disabled}
qa={qa}
className={b('add-button', {right: spec.viewSpec.addButtonPosition === 'right'})}
>
<Icon data={Plus} size={14} />
{title || null}
</Button>
);
}, [
arrayInput,
input,
name,
spec.defaultValue,
spec.items,
spec.viewSpec.disabled,
spec.viewSpec.itemLabel,
spec.viewSpec.layoutTitle,
]);

const items = React.useMemo(
() =>
keys.map((key, idx) => {
Expand All @@ -89,50 +129,51 @@ export const ArrayBase: ArrayInput = ({spec, name, arrayInput, input}) => {
return null;
}

const showItemPrefix = idx !== 0 && spec.viewSpec.itemPrefix;

return (
<Controller
value={input.value?.[`<${key}>`]}
parentOnChange={parentOnChange}
parentOnUnmount={input.parentOnUnmount}
spec={itemSpec}
name={`${name}.<${key}>`}
key={`${name}.<${key}>`}
/>
<React.Fragment key={`${name}.<${key}>`}>
{showItemPrefix ? (
<Label size="m" className={b('item-prefix')}>
{spec.viewSpec.itemPrefix}
</Label>
) : null}
<Controller
value={input.value?.[`<${key}>`]}
parentOnChange={parentOnChange}
parentOnUnmount={input.parentOnUnmount}
spec={itemSpec}
name={`${name}.<${key}>`}
/>
</React.Fragment>
);
}),
[keys.join(''), name, getItemSpec, parentOnChange, input.parentOnUnmount, input.value],
[
keys.join(''),
name,
getItemSpec,
parentOnChange,
input.parentOnUnmount,
input.value,
spec.viewSpec.itemPrefix,
],
);

if (!itemSpecCorrect) {
return null;
}

return (
<React.Fragment>
{items}
{!arrayInput.value && spec.defaultValue ? (
<Button
onClick={() =>
input.onChange(
transformArrIn<ArrayValue, FieldArrayValue>(spec.defaultValue!),
)
}
disabled={spec.viewSpec.disabled}
qa={`${name}-init-arr`}
>
<Icon data={Plus} size={14} />
{spec.viewSpec.layoutTitle || null}
</Button>
) : (
<Button
onClick={onItemAdd}
disabled={spec.viewSpec.disabled}
qa={`${name}-add-item`}
>
<Icon data={Plus} size={14} />
{spec.viewSpec.itemLabel || null}
</Button>
)}
</React.Fragment>
<div className={b({'add-button-right': spec.viewSpec.addButtonPosition === 'right'})}>
<div
className={b('items-wrapper', {
'add-button-down':
spec.viewSpec.addButtonPosition !== 'right' && keys.length > 0,
})}
>
{items}
</div>
<AddButton />
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import {Plus, Xmark} from '@gravity-ui/icons';
import {Plus, TrashBin} from '@gravity-ui/icons';
import {Button, Icon, Table} from '@gravity-ui/uikit';
import _ from 'lodash';

Expand Down Expand Up @@ -93,12 +93,12 @@ export const TableArrayInput: ArrayInput = ({spec, name, arrayInput, input}) =>
sticky: 'right',
template: ({key}: {key: string}) => (
<Button
view="flat"
view="flat-secondary"
onClick={() => onItemRemove(key)}
key={`remove-${key}`}
qa={`${name}-item-remove-${key}`}
>
<Icon data={Xmark} size={16} />
<Icon data={TrashBin} size={16} />
</Button>
),
};
Expand Down
6 changes: 3 additions & 3 deletions src/lib/kit/components/Layouts/Row/Row.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';

import {HelpPopover} from '@gravity-ui/components';
import {Xmark} from '@gravity-ui/icons';
import {TrashBin} from '@gravity-ui/icons';
import {Button, Icon} from '@gravity-ui/uikit';

import {
Expand Down Expand Up @@ -63,12 +63,12 @@ const RowBase = <T extends FieldValue, S extends Spec>({
</ErrorWrapper>
{arrayItem ? (
<Button
view="flat"
view="flat-secondary"
className={b('remove-button')}
onClick={input.onDrop}
qa={`${name}-remove-item`}
>
<Icon data={Xmark} size={16} />
<Icon data={TrashBin} size={16} />
</Button>
) : null}
</div>
Expand Down
6 changes: 3 additions & 3 deletions src/lib/kit/components/Layouts/Row2/Row2.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import {Xmark} from '@gravity-ui/icons';
import {TrashBin} from '@gravity-ui/icons';
import {Button, Icon} from '@gravity-ui/uikit';

import {
Expand Down Expand Up @@ -44,12 +44,12 @@ export const Row2 = <T extends FieldValue, S extends Spec>({
</ErrorWrapper>
{isArrayItem(name) ? (
<Button
view="flat"
view="flat-secondary"
className={b('remove-button')}
onClick={input.onDrop}
qa={`${name}-remove-item`}
>
<Icon data={Xmark} size={16} />
<Icon data={TrashBin} size={16} />
</Button>
) : null}
</div>
Expand Down
6 changes: 3 additions & 3 deletions src/lib/kit/components/Layouts/Transparent/Transparent.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import {Xmark} from '@gravity-ui/icons';
import {TrashBin} from '@gravity-ui/icons';
import {Button, Icon} from '@gravity-ui/uikit';

import {
Expand Down Expand Up @@ -32,12 +32,12 @@ export const Transparent = <T extends FieldValue, S extends Spec>({
if (arrayItem) {
return (
<Button
view="flat"
view="flat-secondary"
className={b('remove-button')}
onClick={input.onDrop}
qa={`${name}-remove-item`}
>
<Icon data={Xmark} size={16} />
<Icon data={TrashBin} size={16} />
</Button>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@import '../../../styles/variables';

.#{$ns}array-base-view {
&__item-prefix {
margin-top: -10px;
margin-bottom: 15px;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import React from 'react';

import {Label} from '@gravity-ui/uikit';
import _ from 'lodash';

import {ArrayView, Spec, ViewController, isCorrectSpec} from '../../../core';
import {ArrayView, Spec, ViewController, isCorrectSpec} from '../../../../core';
import {block} from '../../../utils';

import './ArrayBaseView.scss';

const b = block('array-base-view');

export const ArrayBaseView: ArrayView = ({spec, name, value = []}) => {
const itemSpecCorrect = React.useMemo(() => isCorrectSpec(spec.items), [spec.items]);
Expand Down Expand Up @@ -36,20 +42,25 @@ export const ArrayBaseView: ArrayView = ({spec, name, value = []}) => {
return null;
}

const showItemPrefix = idx !== 0 && spec.viewSpec.itemPrefix;

return (
<ViewController
spec={itemSpec}
name={`${name}[${idx}]`}
key={`${name}[${idx}]`}
/>
<React.Fragment key={`${name}[${idx}]`}>
{showItemPrefix ? (
<Label size="m" className={b('item-prefix')}>
{spec.viewSpec.itemPrefix}
</Label>
) : null}
<ViewController spec={itemSpec} name={`${name}[${idx}]`} />
</React.Fragment>
);
}),
[value.length, name, getItemSpec],
[value.length, name, getItemSpec, spec.viewSpec.itemPrefix],
);

if (!itemSpecCorrect) {
return null;
}

return <>{items}</>;
return <React.Fragment>{items}</React.Fragment>;
};
1 change: 1 addition & 0 deletions src/lib/kit/components/Views/ArrayBaseView/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ArrayBaseView';
Loading