diff --git a/docs/spec.md b/docs/spec.md index 08fc17f..d2b3e8c 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -8,32 +8,33 @@ type Spec = ArraySpec | BooleanSpec | NumberSpec | ObjectSpec | StringSpec; ### ArraySpec -| Property | Type | Required | Description | -| :------------------------- | :----------------------------------------------------------- | :------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| defaultValue | `FieldArrayValue` | | Default value | -| type | `"array"` | yes | Entity type | -| required | `boolean` | | Can the value be `undefined` or `null` | -| maxLength | `bigint` | | Maximum number of array elements | -| minLength | `bigint` | | Minimum number of array elements | -| items | `Spec` | | Entity `spec` for an array element | -| enum | `string[]` | | An array of valid values, for example for a select | -| description | `Record` | | Beautiful names for values from `enum` | -| validator | `string` | | The key for determining the [validator](./config.md#validators) for the entity, if the value is empty, the base [validator](./config.md#validators) from the entity config will be used | -| viewSpec.disabled | `boolean` | | Is the field available for editing | -| viewSpec.type | `string` | yes | Key to define [Input](./config.md#inputs) for an entity | -| viewSpec.layout | `string` | | Key to define [Layout](./config.md#layouts) for an entity | -| viewSpec.layoutTitle | `string` | | Title for [Layout](./config.md#layouts) | -| 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; description?: string;}[]` | | An array whose elements are used to establish column names and their order, if `type === "table"`. `description` adds a hint to a field in the table's header | -| 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". | -| viewSpec.hidden | `boolean` | | Hide field and view | -| viewSpec.selectParams | `object` | | [Parameters](#selectparams) additional options for the selector | -| viewSpec.inputProps | `object` | | [InputProps](./input-props-map.md) Additional properties for internal input components | +| Property | Type | Required | Description | +| :--------------------------- | :----------------------------------------------------------- | :------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| defaultValue | `FieldArrayValue` | | Default value | +| type | `"array"` | yes | Entity type | +| required | `boolean` | | Can the value be `undefined` or `null` | +| maxLength | `bigint` | | Maximum number of array elements | +| minLength | `bigint` | | Minimum number of array elements | +| items | `Spec` | | Entity `spec` for an array element | +| enum | `string[]` | | An array of valid values, for example for a select | +| description | `Record` | | Beautiful names for values from `enum` | +| validator | `string` | | The key for determining the [validator](./config.md#validators) for the entity, if the value is empty, the base [validator](./config.md#validators) from the entity config will be used | +| viewSpec.disabled | `boolean` | | Is the field available for editing | +| viewSpec.type | `string` | yes | Key to define [Input](./config.md#inputs) for an entity | +| viewSpec.layout | `string` | | Key to define [Layout](./config.md#layouts) for an entity | +| viewSpec.layoutTitle | `string` | | Title for [Layout](./config.md#layouts) | +| 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; description?: string;}[]` | | An array whose elements are used to establish column names and their order, if `type === "table"`. `description` adds a hint to a field in the table's header | +| 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". | +| viewSpec.hidden | `boolean` | | Hide field and view | +| viewSpec.selectParams | `object` | | [Parameters](#selectparams) additional options for the selector | +| viewSpec.checkboxGroupParams | `object` | | [Parameters](#checkboxgroupparams) additional options for the checkbox group | +| viewSpec.inputProps | `object` | | [InputProps](./input-props-map.md) Additional properties for internal input components | ### BooleanSpec @@ -188,6 +189,13 @@ You can provide all props of [original component](https://preview.gravity-ui.com | filterPlaceholder | `string` | | Placeholder for filter | | meta | `Record` | | Additional text for enum values | +#### CheckboxGroupParams + +| Property | Type | Required | Description | +| :-------- | :-------------------------- | :------: | :----------------------------------------- | +| placement | `'horizontal'` `'vertical'` | | Placement checkbox, default `'horizontal'` | +| disabled | `Record` | | Disabled checkbox for enum values | + #### Link A component that serves as a wrapper for the value, if necessary, rendering the value as a link. diff --git a/src/lib/core/types/specs.ts b/src/lib/core/types/specs.ts index b19f291..02aa0ce 100644 --- a/src/lib/core/types/specs.ts +++ b/src/lib/core/types/specs.ts @@ -43,6 +43,10 @@ export interface ArraySpec< }; inputProps?: InputComponentProps; layoutProps?: LayoutComponentProps; + checkboxGroupParams?: { + placement?: 'horizontal' | 'vertical'; + disabled?: Record; + }; }; } diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/CheckboxGroup.scss b/src/lib/kit/components/Inputs/CheckboxGroup/CheckboxGroup.scss new file mode 100644 index 0000000..3378335 --- /dev/null +++ b/src/lib/kit/components/Inputs/CheckboxGroup/CheckboxGroup.scss @@ -0,0 +1,23 @@ +@import '../../../styles/variables'; + +.#{$ns}checkbox-group { + display: flex; + align-items: center; + height: 28px; + + & > *:not(:last-child) { + margin-right: 6px; + } + + &_vertical { + flex-direction: column; + align-items: flex-start; + margin-top: 8px; + height: auto; + + & > *:not(:last-child) { + margin-right: 0px; + margin-bottom: 6px; + } + } +} diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/CheckboxGroup.tsx b/src/lib/kit/components/Inputs/CheckboxGroup/CheckboxGroup.tsx new file mode 100644 index 0000000..83cae58 --- /dev/null +++ b/src/lib/kit/components/Inputs/CheckboxGroup/CheckboxGroup.tsx @@ -0,0 +1,72 @@ +import React from 'react'; + +import {ArrayInput, FieldArrayValue, transformArrIn, transformArrOut} from '../../../../core'; +import {Checkbox, type CheckboxProps as CheckboxBaseProps} from '@gravity-ui/uikit'; +import {block} from '../../../utils'; + +import './CheckboxGroup.scss'; + +const b = block('checkbox-group'); + +export interface CheckboxGroupProps + extends Omit< + CheckboxBaseProps, + 'checked' | 'onChange' | 'onBlur' | 'onFocus' | 'disabled' | 'qa' | 'content' + > {} + +export const CheckboxGroup: ArrayInput = ({name, input, spec, inputProps}) => { + const {value, onBlur, onChange, onFocus} = input; + + const _value: string[] | undefined = React.useMemo( + () => transformArrOut(value), + [value], + ); + + const options = React.useMemo( + () => + spec.enum?.map((id) => ({ + value: id, + text: spec.description?.[id] || id, + })), + [spec.enum, spec.description], + ); + + const handleUpdate = React.useCallback( + (optionValue: string, selected: boolean) => { + let newValue = _value || []; + + if (selected) { + newValue.push(optionValue); + } else { + newValue = newValue.filter((id) => id !== optionValue); + } + + onChange(transformArrIn(newValue)); + }, + [_value, onChange], + ); + + return ( +
+ {options?.map(({value: optionValue, text}) => ( + handleUpdate(optionValue, selected)} + disabled={ + spec.viewSpec.disabled || + spec.viewSpec.checkboxGroupParams?.disabled?.[optionValue] + } + content={text} + onBlur={onBlur} + onFocus={onFocus} + /> + ))} +
+ ); +}; diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-dark-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-dark-chromium-linux.png new file mode 100644 index 0000000..fca87ee Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-dark-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-dark-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-dark-webkit-linux.png new file mode 100644 index 0000000..9f00ee6 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-dark-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-light-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-light-chromium-linux.png new file mode 100644 index 0000000..46baf91 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-light-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-light-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-light-webkit-linux.png new file mode 100644 index 0000000..23835f9 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-light-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-dark-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-dark-chromium-linux.png new file mode 100644 index 0000000..fa6712e Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-dark-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-dark-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-dark-webkit-linux.png new file mode 100644 index 0000000..a148c82 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-dark-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-light-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-light-chromium-linux.png new file mode 100644 index 0000000..92e58e5 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-light-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-light-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-light-webkit-linux.png new file mode 100644 index 0000000..624a9f3 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-default-value-light-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-dark-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-dark-chromium-linux.png new file mode 100644 index 0000000..599a21b Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-dark-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-dark-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-dark-webkit-linux.png new file mode 100644 index 0000000..48b2395 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-dark-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-light-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-light-chromium-linux.png new file mode 100644 index 0000000..29fab08 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-light-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-light-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-light-webkit-linux.png new file mode 100644 index 0000000..78ffda2 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-disabled-light-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-dark-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-dark-chromium-linux.png new file mode 100644 index 0000000..4b3fc51 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-dark-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-dark-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-dark-webkit-linux.png new file mode 100644 index 0000000..dd5a3b8 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-dark-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-light-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-light-chromium-linux.png new file mode 100644 index 0000000..ed46d40 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-light-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-light-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-light-webkit-linux.png new file mode 100644 index 0000000..4f27dc2 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-placement-vertical-light-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-dark-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-dark-chromium-linux.png new file mode 100644 index 0000000..dcb761c Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-dark-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-dark-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-dark-webkit-linux.png new file mode 100644 index 0000000..69755c1 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-dark-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-light-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-light-chromium-linux.png new file mode 100644 index 0000000..c4c8959 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-light-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-light-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-light-webkit-linux.png new file mode 100644 index 0000000..618db4d Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-horizontal-light-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-dark-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-dark-chromium-linux.png new file mode 100644 index 0000000..a4035f6 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-dark-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-dark-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-dark-webkit-linux.png new file mode 100644 index 0000000..21a825b Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-dark-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-light-chromium-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-light-chromium-linux.png new file mode 100644 index 0000000..67b4209 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-light-chromium-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-light-webkit-linux.png b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-light-webkit-linux.png new file mode 100644 index 0000000..16848b8 Binary files /dev/null and b/src/lib/kit/components/Inputs/CheckboxGroup/__snapshots__/CheckboxGroup.visual.test.tsx-snapshots/CheckboxGroup-view-vertical-light-webkit-linux.png differ diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__tests__/CheckboxGroup.visual.test.tsx b/src/lib/kit/components/Inputs/CheckboxGroup/__tests__/CheckboxGroup.visual.test.tsx new file mode 100644 index 0000000..f0a61d9 --- /dev/null +++ b/src/lib/kit/components/Inputs/CheckboxGroup/__tests__/CheckboxGroup.visual.test.tsx @@ -0,0 +1,47 @@ +import React from 'react'; + +import {CHECKBOX_GROUP, VALUE} from './helpers'; + +import {test} from '~playwright/core'; +import {DynamicForm} from '~playwright/core/DynamicForm'; +import {DynamicView} from '~playwright/core/DynamicView'; + +test.describe('CheckboxGroup', () => { + test('default', async ({mount, expectScreenshot}) => { + await mount(); + + await expectScreenshot(); + }); + + test('default value', async ({mount, expectScreenshot}) => { + await mount(); + + await expectScreenshot(); + }); + + test('placement vertical', async ({mount, expectScreenshot}) => { + await mount(); + + await expectScreenshot(); + }); + + test('disabled', async ({mount, expectScreenshot}) => { + await mount(); + + await expectScreenshot(); + }); +}); + +test.describe('CheckboxGroup view', () => { + test('vertical', async ({mount, expectScreenshot}) => { + await mount(); + + await expectScreenshot(); + }); + + test('horizontal', async ({mount, expectScreenshot}) => { + await mount(); + + await expectScreenshot(); + }); +}); diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/__tests__/helpers.ts b/src/lib/kit/components/Inputs/CheckboxGroup/__tests__/helpers.ts new file mode 100644 index 0000000..411bf31 --- /dev/null +++ b/src/lib/kit/components/Inputs/CheckboxGroup/__tests__/helpers.ts @@ -0,0 +1,102 @@ +import {ArraySpec, FormValue, SpecTypes} from '../../../../../core'; + +export const CHECKBOX_GROUP: Record = { + default: { + type: SpecTypes.Array, + enum: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'], + description: { + monday: 'Mon', + tuesday: 'Tue', + wednesday: 'Wed', + thursday: 'Thu', + friday: 'Fri', + saturday: 'Sat', + sunday: 'Sun', + }, + viewSpec: { + type: 'checkbox_group', + layout: 'row', + layoutTitle: 'Days of the week', + checkboxGroupParams: { + disabled: { + monday: true, + }, + }, + }, + }, + defaultValue: { + defaultValue: ['monday', 'wednesday'], + type: SpecTypes.Array, + enum: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'], + description: { + monday: 'Mon', + tuesday: 'Tue', + wednesday: 'Wed', + thursday: 'Thu', + friday: 'Fri', + saturday: 'Sat', + sunday: 'Sun', + }, + viewSpec: { + type: 'checkbox_group', + layout: 'row', + layoutTitle: 'Days of the week', + layoutDescription: 'Description Days of the week', + checkboxGroupParams: { + disabled: { + monday: true, + }, + }, + }, + }, + placementVertical: { + defaultValue: ['monday', 'wednesday'], + type: SpecTypes.Array, + enum: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'], + description: { + monday: 'Mon', + tuesday: 'Tue', + wednesday: 'Wed', + thursday: 'Thu', + friday: 'Fri', + saturday: 'Sat', + sunday: 'Sun', + }, + viewSpec: { + type: 'checkbox_group', + layout: 'row', + layoutTitle: 'Days of the week', + layoutDescription: 'Description Days of the week', + checkboxGroupParams: { + placement: 'vertical', + disabled: { + monday: true, + }, + }, + }, + }, + disabled: { + type: SpecTypes.Array, + enum: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'], + description: { + monday: 'Mon', + tuesday: 'Tue', + wednesday: 'Wed', + thursday: 'Thu', + friday: 'Fri', + saturday: 'Sat', + sunday: 'Sun', + }, + viewSpec: { + type: 'checkbox_group', + layout: 'row', + layoutTitle: 'Days of the week', + disabled: true, + }, + }, +}; + +export const VALUE: Record = { + vertical: ['monday', 'wednesday', 'saturday'], + horizontal: ['monday', 'wednesday', 'saturday'], +}; diff --git a/src/lib/kit/components/Inputs/CheckboxGroup/index.ts b/src/lib/kit/components/Inputs/CheckboxGroup/index.ts new file mode 100644 index 0000000..7c00f7b --- /dev/null +++ b/src/lib/kit/components/Inputs/CheckboxGroup/index.ts @@ -0,0 +1 @@ +export * from './CheckboxGroup'; diff --git a/src/lib/kit/components/Inputs/index.ts b/src/lib/kit/components/Inputs/index.ts index e78a4a8..e215aaf 100644 --- a/src/lib/kit/components/Inputs/index.ts +++ b/src/lib/kit/components/Inputs/index.ts @@ -1,6 +1,7 @@ export * from './ArrayBase'; export * from './CardOneOf'; export * from './Checkbox'; +export * from './CheckboxGroup'; export * from './FileInput'; export * from './DateInput'; export * from './MonacoInput'; diff --git a/src/lib/kit/components/Views/CheckboxGroupView/CheckboxGroupView.scss b/src/lib/kit/components/Views/CheckboxGroupView/CheckboxGroupView.scss new file mode 100644 index 0000000..be57946 --- /dev/null +++ b/src/lib/kit/components/Views/CheckboxGroupView/CheckboxGroupView.scss @@ -0,0 +1,35 @@ +@import '../../../styles/variables.scss'; + +.#{$ns}checkbox-group-view { + display: flex; + + & > *:not(:last-child) { + margin-right: 6px; + } + + &_vertical { + flex-direction: column; + align-items: flex-start; + + & > *:not(:last-child) { + margin-right: 0px; + margin-bottom: 6px; + } + } + + &__tooltip { + overflow-wrap: break-word; + } + + &__tooltip-container { + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + display: block; + margin-bottom: 6px; + + &:last-child { + margin-bottom: 0; + } + } +} diff --git a/src/lib/kit/components/Views/CheckboxGroupView/CheckboxGroupView.tsx b/src/lib/kit/components/Views/CheckboxGroupView/CheckboxGroupView.tsx new file mode 100644 index 0000000..b34a9cd --- /dev/null +++ b/src/lib/kit/components/Views/CheckboxGroupView/CheckboxGroupView.tsx @@ -0,0 +1,42 @@ +import React from 'react'; + +import {Popover} from '@gravity-ui/uikit'; +import {COMMON_POPOVER_PLACEMENT} from '../../../constants/common'; +import {ArrayView} from '../../../../core'; +import {block} from '../../../utils'; + +import './CheckboxGroupView.scss'; + +const b = block('checkbox-group-view'); + +export const CheckboxGroupView: ArrayView = ({spec, value = []}) => { + const _value = value as string[]; + + const items = React.useMemo( + () => _value.map((item) => spec.description?.[item] || item), + [spec.description, _value], + ); + + const verticalPlacement = React.useMemo( + () => spec.viewSpec.checkboxGroupParams?.placement === 'vertical', + [spec.viewSpec.checkboxGroupParams?.placement], + ); + + return ( +
+ {items.map((item, idx) => ( + + {item} + {!verticalPlacement && idx !== items.length - 1 ? ', ' : null} + + ))} +
+ ); +}; diff --git a/src/lib/kit/components/Views/CheckboxGroupView/index.ts b/src/lib/kit/components/Views/CheckboxGroupView/index.ts new file mode 100644 index 0000000..9f8e717 --- /dev/null +++ b/src/lib/kit/components/Views/CheckboxGroupView/index.ts @@ -0,0 +1 @@ +export * from './CheckboxGroupView'; diff --git a/src/lib/kit/components/Views/index.ts b/src/lib/kit/components/Views/index.ts index 70dc0ed..d75e19e 100644 --- a/src/lib/kit/components/Views/index.ts +++ b/src/lib/kit/components/Views/index.ts @@ -1,5 +1,6 @@ export * from './ArrayBaseView'; export * from './BaseView'; +export * from './CheckboxGroupView'; export * from './CardOneOfView'; export * from './FileInputView'; export * from './MonacoInputView'; diff --git a/src/lib/kit/constants/config.tsx b/src/lib/kit/constants/config.tsx index d68642c..a9fd1ba 100644 --- a/src/lib/kit/constants/config.tsx +++ b/src/lib/kit/constants/config.tsx @@ -10,6 +10,8 @@ import { CardOneOfView, CardSection, Checkbox, + CheckboxGroup, + CheckboxGroupView, DateInput, DateView, FileInput, @@ -79,6 +81,7 @@ export const dynamicConfig: DynamicFormConfig = { select: {Component: MultiSelect}, table: {Component: TableArrayInput}, base: {Component: ArrayBase}, + checkbox_group: {Component: CheckboxGroup}, }, layouts: { row: Row, @@ -193,6 +196,7 @@ export const dynamicViewConfig: DynamicViewConfig = { select: {Component: MultiSelectView}, table: {Component: TableArrayView}, base: {Component: ArrayBaseView}, + checkbox_group: {Component: CheckboxGroupView}, }, layouts: { row: ViewRow, diff --git a/src/stories/ArrayBase.stories.tsx b/src/stories/ArrayBase.stories.tsx index 97a801a..be1548c 100644 --- a/src/stories/ArrayBase.stories.tsx +++ b/src/stories/ArrayBase.stories.tsx @@ -39,6 +39,7 @@ const excludeOptions = [ 'viewSpec.table', 'viewSpec.placeholder', 'viewSpec.selectParams', + 'viewSpec.checkboxGroupParams', 'viewSpec.inputProps', ]; diff --git a/src/stories/ArrayCheckboxGroup.stories.tsx b/src/stories/ArrayCheckboxGroup.stories.tsx new file mode 100644 index 0000000..ff33dda --- /dev/null +++ b/src/stories/ArrayCheckboxGroup.stories.tsx @@ -0,0 +1,59 @@ +import React from 'react'; + +import {StoryFn} from '@storybook/react'; + +import {ArraySpec, CheckboxGroup as CheckboxGroupBase, SpecTypes} from '../lib'; + +import {InputPreview} from './components'; + +export default { + title: 'Array/CheckboxGroup', + component: CheckboxGroupBase, +}; + +const spec: ArraySpec = { + type: SpecTypes.Array, + enum: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'], + description: { + monday: 'Mon', + tuesday: 'Tue', + wednesday: 'Wed', + thursday: 'Thu', + friday: 'Fri', + saturday: 'Sat', + sunday: 'Sun', + }, + viewSpec: { + type: 'checkbox_group', + layout: 'row', + layoutTitle: 'Days of the week', + checkboxGroupParams: { + disabled: { + monday: true, + }, + }, + }, +}; + +const excludeOptions = [ + 'items', + 'viewSpec.type', + 'viewSpec.itemLabel', + 'viewSpec.table', + 'viewSpec.itemPrefix', + 'viewSpec.addButtonPosition', + 'viewSpec.selectParams', + 'viewSpec.inputProps', + 'viewSpec.placeholder', + 'viewSpec.layoutOpen', +]; + +const template = () => { + const Template: StoryFn = (__, {viewMode}) => ( + + ); + + return Template; +}; + +export const CheckboxGroup = template(); diff --git a/src/stories/ArraySelect.stories.tsx b/src/stories/ArraySelect.stories.tsx index b96727b..2076153 100644 --- a/src/stories/ArraySelect.stories.tsx +++ b/src/stories/ArraySelect.stories.tsx @@ -56,6 +56,7 @@ const excludeOptions = [ 'viewSpec.table', 'viewSpec.itemPrefix', 'viewSpec.addButtonPosition', + 'viewSpec.checkboxGroupParams', ]; const template = () => { diff --git a/src/stories/ArrayTable.stories.tsx b/src/stories/ArrayTable.stories.tsx index 1ffa74c..a6b2135 100644 --- a/src/stories/ArrayTable.stories.tsx +++ b/src/stories/ArrayTable.stories.tsx @@ -62,6 +62,7 @@ const excludeOptions = [ 'viewSpec.itemPrefix', 'viewSpec.addButtonPosition', 'viewSpec.selectParams', + 'viewSpec.checkboxGroupParams', 'viewSpec.inputProps', ]; diff --git a/src/stories/Editor.stories.tsx b/src/stories/Editor.stories.tsx index 09c91af..63e2598 100644 --- a/src/stories/Editor.stories.tsx +++ b/src/stories/Editor.stories.tsx @@ -78,6 +78,32 @@ const spec: ObjectSpec = { type: SpecTypes.Number, viewSpec: {type: 'base', layout: 'row', layoutTitle: 'Age'}, }, + non_working_days: { + type: SpecTypes.Array, + enum: [ + 'monday', + 'tuesday', + 'wednesday', + 'thursday', + 'friday', + 'saturday', + 'sunday', + ], + description: { + monday: 'Mon', + tuesday: 'Tue', + wednesday: 'Wed', + thursday: 'Thu', + friday: 'Fri', + saturday: 'Sat', + sunday: 'Sun', + }, + viewSpec: { + type: 'checkbox_group', + layout: 'row', + layoutTitle: 'Non-working days', + }, + }, birthday: { type: SpecTypes.String, viewSpec: { diff --git a/src/stories/components/InputPreview/constants.ts b/src/stories/components/InputPreview/constants.ts index 1c30922..2150375 100644 --- a/src/stories/components/InputPreview/constants.ts +++ b/src/stories/components/InputPreview/constants.ts @@ -166,6 +166,44 @@ const selectParams: ObjectSpec = { }, }; +const checkboxGroupParams: ObjectSpec = { + type: SpecTypes.Object, + properties: { + placement: { + type: SpecTypes.String, + enum: ['―', 'horizontal', 'vertical'], + viewSpec: {type: 'select', layout: 'row', layoutTitle: 'Placement'}, + }, + disabled: { + type: SpecTypes.Array, + items: { + type: SpecTypes.Object, + properties: { + property: { + type: SpecTypes.String, + viewSpec: {type: 'base', layout: 'table_item'}, + }, + disabled: { + type: SpecTypes.Boolean, + viewSpec: {type: 'base', layout: 'table_item'}, + }, + }, + viewSpec: {type: ''}, + }, + viewSpec: { + type: 'table', + layout: 'accordeon', + layoutTitle: 'Disabled', + table: [ + {label: 'Property', property: 'property'}, + {label: 'Disabled', property: 'disabled'}, + ], + }, + }, + }, + viewSpec: {type: 'base', layout: 'accordeon', layoutTitle: 'Checkbox Group Params'}, +}; + const getValidator = (map: Record): StringSpec => ({ type: SpecTypes.String, enum: ['―', ...Object.keys(map)], @@ -572,6 +610,7 @@ export const getArrayOptions = (): ObjectSpec => ({ addButtonPosition, hidden, selectParams, + checkboxGroupParams, inputProps, }, [ @@ -588,6 +627,7 @@ export const getArrayOptions = (): ObjectSpec => ({ 'addButtonPosition', 'hidden', 'selectParams', + 'checkboxGroupParams', 'inputProps', ], ), diff --git a/src/stories/components/InputPreview/utils.ts b/src/stories/components/InputPreview/utils.ts index 4c61849..b70ba69 100644 --- a/src/stories/components/InputPreview/utils.ts +++ b/src/stories/components/InputPreview/utils.ts @@ -67,6 +67,15 @@ export const transformCorrect = (spec: Spec) => { })) as unknown as Record; } + if (isArraySpec(_spec) && _spec.viewSpec.checkboxGroupParams?.disabled) { + const correctMeta = _spec.viewSpec.checkboxGroupParams.disabled; + + _spec.viewSpec.checkboxGroupParams.disabled = Object.keys(correctMeta).map((key) => ({ + property: key, + disabled: correctMeta[key], + })) as unknown as Record; + } + if (isObjectSpec(_spec) && _spec.viewSpec.delimiter) { const correctDelimiter = _spec.viewSpec.delimiter; @@ -164,6 +173,22 @@ export const transformIncorrect = (spec: Spec) => { ); } + if (isArraySpec(_spec) && _spec.viewSpec.checkboxGroupParams?.disabled) { + const incorrectMeta = _spec.viewSpec.checkboxGroupParams.disabled as unknown as { + property: string; + disabled: boolean; + }[]; + + _spec.viewSpec.checkboxGroupParams.disabled = incorrectMeta.reduce( + (acc: Record, {property, disabled}) => { + acc[property] = disabled; + + return acc; + }, + {}, + ); + } + if (isObjectSpec(_spec) && _spec.viewSpec.delimiter) { const incorrectDelimiter = _spec.viewSpec.delimiter as unknown as { property: string;