Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,10 @@ type Spec = ArraySpec | BooleanSpec | NumberSpec | ObjectSpec | StringSpec;

#### OneOfParams

| Property | Type | Required | Description |
| :--------- | :----------------------------------------- | :------: | :--------------------------------------------- |
| toggler | `'select'` `'radio'` `'card'` `'checkbox'` | | Switch type |
| booleanMap | `Record<'true' 'false', string>` | | Special object for oneof toggler type checkbox |
| Property | Type | Required | Description |
| :--------- | :---------------------------------------------------- | :------: | :--------------------------------------------- |
| toggler | `'select'` `'radio'` `'card'` `'checkbox'` `'switch'` | | Switch type |
| booleanMap | `Record<'true' 'false', string>` | | Special object for oneof toggler type checkbox |

#### FileInput

Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/types/specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export interface ObjectSpec<
order?: string[];
link?: LinkType;
oneOfParams?: {
toggler?: 'select' | 'radio' | 'card' | 'checkbox';
toggler?: 'select' | 'radio' | 'card' | 'checkbox' | 'switch';
booleanMap?: Record<'true' | 'false', string>;
};
placeholder?: string;
Expand Down
6 changes: 5 additions & 1 deletion src/lib/kit/components/Views/OneOfView/OneOfView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ const OneOfViewComponent: React.FC<OneOfViewProps> = (props) => {
const valueKey = React.useMemo(() => Object.keys(value)[0], [value]);

const valueName = React.useMemo(() => {
if (spec.viewSpec.oneOfParams?.toggler === 'checkbox' && specBooleanMap) {
if (
(spec.viewSpec.oneOfParams?.toggler === 'checkbox' ||
spec.viewSpec.oneOfParams?.toggler === 'switch') &&
specBooleanMap
) {
return objectKeys(specBooleanMap).find((key) => specBooleanMap[key] === valueKey);
}

Expand Down
6 changes: 6 additions & 0 deletions src/lib/kit/hooks/useOneOf/useOneOf.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,10 @@
display: flex;
align-items: center;
}

&__switch {
height: var(--df-use-oneof-switch-height, $df-switch-height);
display: flex;
align-items: center;
}
}
32 changes: 23 additions & 9 deletions src/lib/kit/hooks/useOneOf/useOneOf.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import {Checkbox, SegmentedRadioGroup, Select} from '@gravity-ui/uikit';
import {Checkbox, SegmentedRadioGroup, Select, Switch} from '@gravity-ui/uikit';
import isObjectLike from 'lodash/isObjectLike';
import some from 'lodash/some';

Expand Down Expand Up @@ -61,7 +61,7 @@ export const useOneOf = ({props, onTogglerChange}: UseOneOfParams) => {
[setOneOfValue, input.onChange, oneOfValue],
);

const onCheckboxChange = React.useCallback(
const onCheckedChange = React.useCallback(
(checked: boolean) => {
if (specBooleanMap) {
const value = String(checked) as 'true' | 'false';
Expand All @@ -73,7 +73,7 @@ export const useOneOf = ({props, onTogglerChange}: UseOneOfParams) => {
[onOneOfChange, specBooleanMap],
);

const checkboxValue = React.useMemo(() => {
const checkedValue = React.useMemo(() => {
if (specBooleanMap) {
const keyBooleanMap = objectKeys(specBooleanMap).find(
(key) => specBooleanMap[key] === oneOfValue,
Expand Down Expand Up @@ -123,11 +123,12 @@ export const useOneOf = ({props, onTogglerChange}: UseOneOfParams) => {
}

if (
spec.viewSpec.oneOfParams?.toggler === 'checkbox' &&
(spec.viewSpec.oneOfParams?.toggler === 'checkbox' ||
spec.viewSpec.oneOfParams?.toggler === 'switch') &&
options.length === 2 &&
specBooleanMap
) {
return 'checkbox';
return spec.viewSpec.oneOfParams.toggler;
}

return 'radio';
Expand Down Expand Up @@ -176,8 +177,21 @@ export const useOneOf = ({props, onTogglerChange}: UseOneOfParams) => {
return (
<div className={b('checkbox')}>
<Checkbox
checked={checkboxValue}
onUpdate={onCheckboxChange}
checked={checkedValue}
onUpdate={onCheckedChange}
disabled={spec.viewSpec.disabled}
qa={name}
/>
</div>
);
}

if (togglerType === 'switch') {
return (
<div className={b('switch')}>
<Switch
checked={checkedValue}
onUpdate={onCheckedChange}
disabled={spec.viewSpec.disabled}
qa={name}
/>
Expand Down Expand Up @@ -208,8 +222,8 @@ export const useOneOf = ({props, onTogglerChange}: UseOneOfParams) => {
options,
onOneOfChange,
specProperties,
onCheckboxChange,
checkboxValue,
onCheckedChange,
checkedValue,
]);

const toggler = React.useMemo(() => {
Expand Down
3 changes: 3 additions & 0 deletions src/lib/kit/styles/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ $df-popover-item-margin-bottom: 6px;
// Checbox height
$df-checkbox-height: 28px;

// Switch height
$df-switch-height: 28px;

// Fonts
$defaultFontFamily: var(--g-text-body-font-family);
$titleFontFamily: 'YS Display', helveticaneue, arial, helvetica, sans-serif; // stylelint-disable-line
57 changes: 38 additions & 19 deletions src/stories/ObjectOneOf.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,25 +61,7 @@ const baseSpec: ObjectSpec = {
},
};

const excludeOptions = [
'viewSpec.type',
'viewSpec.placeholder',
'viewSpec.delimiter',
'viewSpec.inputProps',
'viewSpec.layoutProps',
];

const template = (spec: ObjectSpec = baseSpec) => {
const Template: StoryFn<typeof OneOfBase> = (__, {viewMode}) => (
<InputPreview spec={spec} excludeOptions={excludeOptions} viewMode={viewMode} />
);

return Template;
};

export const OneOf = template();

export const OneOfCheckbox = template({
const baseToggleSpec: ObjectSpec = {
...baseSpec,
properties: {
internal: {
Expand Down Expand Up @@ -121,4 +103,41 @@ export const OneOfCheckbox = template({
},
},
},
};

const excludeOptions = [
'viewSpec.type',
'viewSpec.placeholder',
'viewSpec.delimiter',
'viewSpec.inputProps',
'viewSpec.layoutProps',
];

const template = (spec: ObjectSpec = baseSpec) => {
const Template: StoryFn<typeof OneOfBase> = (__, {viewMode}) => (
<InputPreview spec={spec} excludeOptions={excludeOptions} viewMode={viewMode} />
);

return Template;
};

export const OneOf = template();

export const OneOfCheckbox = template({
...baseToggleSpec,
});

export const OneOfSwitch = template({
...baseToggleSpec,
viewSpec: {
...baseToggleSpec.viewSpec,
order: ['external', 'internal'],
oneOfParams: {
toggler: 'switch',
booleanMap: {
true: 'external',
false: 'internal',
},
},
},
});
57 changes: 38 additions & 19 deletions src/stories/ObjectOneOfFlat.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,25 +61,7 @@ const baseSpec: ObjectSpec = {
},
};

const excludeOptions = [
'viewSpec.type',
'viewSpec.placeholder',
'viewSpec.delimiter',
'viewSpec.inputProps',
'viewSpec.layoutProps',
];

const template = (spec: ObjectSpec = baseSpec) => {
const Template: StoryFn<typeof OneOfFlatBase> = (__, {viewMode}) => (
<InputPreview spec={spec} excludeOptions={excludeOptions} viewMode={viewMode} />
);

return Template;
};

export const OneOfFlat = template();

export const OneOfFlatCheckbox = template({
const baseToggleSpec: ObjectSpec = {
...baseSpec,
properties: {
empty: {
Expand Down Expand Up @@ -121,4 +103,41 @@ export const OneOfFlatCheckbox = template({
},
},
},
};

const excludeOptions = [
'viewSpec.type',
'viewSpec.placeholder',
'viewSpec.delimiter',
'viewSpec.inputProps',
'viewSpec.layoutProps',
];

const template = (spec: ObjectSpec = baseSpec) => {
const Template: StoryFn<typeof OneOfFlatBase> = (__, {viewMode}) => (
<InputPreview spec={spec} excludeOptions={excludeOptions} viewMode={viewMode} />
);

return Template;
};

export const OneOfFlat = template();

export const OneOfFlatCheckbox = template({
...baseToggleSpec,
});

export const OneOfFlatSwitch = template({
...baseToggleSpec,
viewSpec: {
...baseToggleSpec.viewSpec,
order: ['empty', 'external'],
oneOfParams: {
toggler: 'switch',
booleanMap: {
true: 'external',
false: 'empty',
},
},
},
});
2 changes: 1 addition & 1 deletion src/stories/components/InputPreview/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ const oneOfParams: ObjectSpec = {
properties: {
toggler: {
type: SpecTypes.String,
enum: ['―', 'radio', 'select', 'card', 'checkbox'],
enum: ['―', 'radio', 'select', 'card', 'checkbox', 'switch'],
viewSpec: {type: 'select', layout: 'row', layoutTitle: 'Switch type'},
},
booleanMap: {
Expand Down