Skip to content

Commit de1c422

Browse files
authored
feat(NewSettingForArray): added new settings to the array (#83)
1 parent d5d8e6d commit de1c422

File tree

14 files changed

+193
-74
lines changed

14 files changed

+193
-74
lines changed

docs/spec.md

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

3335
### BooleanSpec
3436

src/lib/core/types/specs.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ export interface ArraySpec<LinkType = any> {
2222
layoutDescription?: string;
2323
layoutOpen?: boolean;
2424
itemLabel?: string;
25+
itemPrefix?: string;
2526
table?: {
2627
label: string;
2728
property: string;
2829
}[];
2930
link?: LinkType;
3031
placeholder?: string;
32+
addButtonPosition?: 'down' | 'right';
3133
};
3234
}
3335

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
@import '../../../styles/variables';
2+
3+
.#{$ns}array-base {
4+
&_add-button-right {
5+
display: flex;
6+
align-items: flex-end;
7+
}
8+
9+
&__items-wrapper {
10+
&_add-button-down {
11+
margin-bottom: 15px;
12+
}
13+
}
14+
15+
&__item-prefix {
16+
margin-top: -7px;
17+
margin-bottom: 8px;
18+
}
19+
20+
&__add-button {
21+
&_right {
22+
margin-left: 4px;
23+
}
24+
}
25+
}
Lines changed: 91 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22

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

77
import {
@@ -19,6 +19,11 @@ import {
1919
isObjectSpec,
2020
transformArrIn,
2121
} from '../../../../core';
22+
import {block} from '../../../utils';
23+
24+
import './ArrayBase.scss';
25+
26+
const b = block('array-base');
2227

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

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

35-
const onItemAdd = React.useCallback(() => {
36-
let item;
37-
38-
if (!spec.items?.required) {
39-
if (isArraySpec(spec.items)) {
40-
item = {[OBJECT_ARRAY_FLAG]: true, [OBJECT_ARRAY_CNT]: 0};
41-
} else if (isObjectSpec(spec.items)) {
42-
item = {};
43-
}
44-
}
45-
46-
arrayInput.onItemAdd(item);
47-
}, [arrayInput.onItemAdd, spec.items]);
48-
4940
const getItemSpec = React.useCallback(
5041
(idx: number): typeof spec.items | null => {
5142
if (!itemSpecCorrect) {
@@ -80,6 +71,55 @@ export const ArrayBase: ArrayInput = ({spec, name, arrayInput, input}) => {
8071
[input.onChange, input.name],
8172
);
8273

74+
const AddButton: React.FC = React.useCallback(() => {
75+
let onClick = () => {
76+
let item;
77+
78+
if (!spec.items?.required) {
79+
if (isArraySpec(spec.items)) {
80+
item = {[OBJECT_ARRAY_FLAG]: true, [OBJECT_ARRAY_CNT]: 0};
81+
} else if (isObjectSpec(spec.items)) {
82+
item = {};
83+
}
84+
}
85+
86+
arrayInput.onItemAdd(item);
87+
};
88+
89+
let qa = `${name}-add-item`;
90+
let title = spec.viewSpec.itemLabel;
91+
92+
if (!arrayInput.value && spec.defaultValue) {
93+
onClick = () => {
94+
input.onChange(transformArrIn<ArrayValue, FieldArrayValue>(spec.defaultValue!));
95+
};
96+
97+
qa = `${name}-init-arr`;
98+
title = spec.viewSpec.layoutTitle;
99+
}
100+
101+
return (
102+
<Button
103+
onClick={onClick}
104+
disabled={spec.viewSpec.disabled}
105+
qa={qa}
106+
className={b('add-button', {right: spec.viewSpec.addButtonPosition === 'right'})}
107+
>
108+
<Icon data={Plus} size={14} />
109+
{title || null}
110+
</Button>
111+
);
112+
}, [
113+
arrayInput,
114+
input,
115+
name,
116+
spec.defaultValue,
117+
spec.items,
118+
spec.viewSpec.disabled,
119+
spec.viewSpec.itemLabel,
120+
spec.viewSpec.layoutTitle,
121+
]);
122+
83123
const items = React.useMemo(
84124
() =>
85125
keys.map((key, idx) => {
@@ -89,50 +129,51 @@ export const ArrayBase: ArrayInput = ({spec, name, arrayInput, input}) => {
89129
return null;
90130
}
91131

132+
const showItemPrefix = idx !== 0 && spec.viewSpec.itemPrefix;
133+
92134
return (
93-
<Controller
94-
value={input.value?.[`<${key}>`]}
95-
parentOnChange={parentOnChange}
96-
parentOnUnmount={input.parentOnUnmount}
97-
spec={itemSpec}
98-
name={`${name}.<${key}>`}
99-
key={`${name}.<${key}>`}
100-
/>
135+
<React.Fragment key={`${name}.<${key}>`}>
136+
{showItemPrefix ? (
137+
<Label size="m" className={b('item-prefix')}>
138+
{spec.viewSpec.itemPrefix}
139+
</Label>
140+
) : null}
141+
<Controller
142+
value={input.value?.[`<${key}>`]}
143+
parentOnChange={parentOnChange}
144+
parentOnUnmount={input.parentOnUnmount}
145+
spec={itemSpec}
146+
name={`${name}.<${key}>`}
147+
/>
148+
</React.Fragment>
101149
);
102150
}),
103-
[keys.join(''), name, getItemSpec, parentOnChange, input.parentOnUnmount, input.value],
151+
[
152+
keys.join(''),
153+
name,
154+
getItemSpec,
155+
parentOnChange,
156+
input.parentOnUnmount,
157+
input.value,
158+
spec.viewSpec.itemPrefix,
159+
],
104160
);
105161

106162
if (!itemSpecCorrect) {
107163
return null;
108164
}
109165

110166
return (
111-
<React.Fragment>
112-
{items}
113-
{!arrayInput.value && spec.defaultValue ? (
114-
<Button
115-
onClick={() =>
116-
input.onChange(
117-
transformArrIn<ArrayValue, FieldArrayValue>(spec.defaultValue!),
118-
)
119-
}
120-
disabled={spec.viewSpec.disabled}
121-
qa={`${name}-init-arr`}
122-
>
123-
<Icon data={Plus} size={14} />
124-
{spec.viewSpec.layoutTitle || null}
125-
</Button>
126-
) : (
127-
<Button
128-
onClick={onItemAdd}
129-
disabled={spec.viewSpec.disabled}
130-
qa={`${name}-add-item`}
131-
>
132-
<Icon data={Plus} size={14} />
133-
{spec.viewSpec.itemLabel || null}
134-
</Button>
135-
)}
136-
</React.Fragment>
167+
<div className={b({'add-button-right': spec.viewSpec.addButtonPosition === 'right'})}>
168+
<div
169+
className={b('items-wrapper', {
170+
'add-button-down':
171+
spec.viewSpec.addButtonPosition !== 'right' && keys.length > 0,
172+
})}
173+
>
174+
{items}
175+
</div>
176+
<AddButton />
177+
</div>
137178
);
138179
};

src/lib/kit/components/Inputs/TableArrayInput/TableArrayInput.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22

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

@@ -93,12 +93,12 @@ export const TableArrayInput: ArrayInput = ({spec, name, arrayInput, input}) =>
9393
sticky: 'right',
9494
template: ({key}: {key: string}) => (
9595
<Button
96-
view="flat"
96+
view="flat-secondary"
9797
onClick={() => onItemRemove(key)}
9898
key={`remove-${key}`}
9999
qa={`${name}-item-remove-${key}`}
100100
>
101-
<Icon data={Xmark} size={16} />
101+
<Icon data={TrashBin} size={16} />
102102
</Button>
103103
),
104104
};

src/lib/kit/components/Layouts/Row/Row.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22

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

77
import {
@@ -63,12 +63,12 @@ const RowBase = <T extends FieldValue, S extends Spec>({
6363
</ErrorWrapper>
6464
{arrayItem ? (
6565
<Button
66-
view="flat"
66+
view="flat-secondary"
6767
className={b('remove-button')}
6868
onClick={input.onDrop}
6969
qa={`${name}-remove-item`}
7070
>
71-
<Icon data={Xmark} size={16} />
71+
<Icon data={TrashBin} size={16} />
7272
</Button>
7373
) : null}
7474
</div>

src/lib/kit/components/Layouts/Row2/Row2.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22

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

66
import {
@@ -44,12 +44,12 @@ export const Row2 = <T extends FieldValue, S extends Spec>({
4444
</ErrorWrapper>
4545
{isArrayItem(name) ? (
4646
<Button
47-
view="flat"
47+
view="flat-secondary"
4848
className={b('remove-button')}
4949
onClick={input.onDrop}
5050
qa={`${name}-remove-item`}
5151
>
52-
<Icon data={Xmark} size={16} />
52+
<Icon data={TrashBin} size={16} />
5353
</Button>
5454
) : null}
5555
</div>

src/lib/kit/components/Layouts/Transparent/Transparent.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22

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

66
import {
@@ -32,12 +32,12 @@ export const Transparent = <T extends FieldValue, S extends Spec>({
3232
if (arrayItem) {
3333
return (
3434
<Button
35-
view="flat"
35+
view="flat-secondary"
3636
className={b('remove-button')}
3737
onClick={input.onDrop}
3838
qa={`${name}-remove-item`}
3939
>
40-
<Icon data={Xmark} size={16} />
40+
<Icon data={TrashBin} size={16} />
4141
</Button>
4242
);
4343
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@import '../../../styles/variables';
2+
3+
.#{$ns}array-base-view {
4+
&__item-prefix {
5+
margin-top: -10px;
6+
margin-bottom: 15px;
7+
}
8+
}

src/lib/kit/components/Views/ArrayBaseView.tsx renamed to src/lib/kit/components/Views/ArrayBaseView/ArrayBaseView.tsx

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
import React from 'react';
22

3+
import {Label} from '@gravity-ui/uikit';
34
import _ from 'lodash';
45

5-
import {ArrayView, Spec, ViewController, isCorrectSpec} from '../../../core';
6+
import {ArrayView, Spec, ViewController, isCorrectSpec} from '../../../../core';
7+
import {block} from '../../../utils';
8+
9+
import './ArrayBaseView.scss';
10+
11+
const b = block('array-base-view');
612

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

45+
const showItemPrefix = idx !== 0 && spec.viewSpec.itemPrefix;
46+
3947
return (
40-
<ViewController
41-
spec={itemSpec}
42-
name={`${name}[${idx}]`}
43-
key={`${name}[${idx}]`}
44-
/>
48+
<React.Fragment key={`${name}[${idx}]`}>
49+
{showItemPrefix ? (
50+
<Label size="m" className={b('item-prefix')}>
51+
{spec.viewSpec.itemPrefix}
52+
</Label>
53+
) : null}
54+
<ViewController spec={itemSpec} name={`${name}[${idx}]`} />
55+
</React.Fragment>
4556
);
4657
}),
47-
[value.length, name, getItemSpec],
58+
[value.length, name, getItemSpec, spec.viewSpec.itemPrefix],
4859
);
4960

5061
if (!itemSpecCorrect) {
5162
return null;
5263
}
5364

54-
return <>{items}</>;
65+
return <React.Fragment>{items}</React.Fragment>;
5566
};

0 commit comments

Comments
 (0)