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(PanelHeaderButton): refactor pressets #7874

Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { noop, PanelHeaderBack } from '@vkontakte/vkui';
import React from 'react';

const App = () => {
return (
<React.Fragment>
<PanelHeaderBack onClick={noop}>
Закрыть
</PanelHeaderBack>

<PanelHeaderBack onClick={noop}>
<span>Закрыть</span>
</PanelHeaderBack>

<PanelHeaderBack onClick={noop} children="Закрыть" />
</React.Fragment>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { noop, PanelHeaderClose } from '@vkontakte/vkui';
import React from 'react';

const App = () => {
return (
<React.Fragment>
<PanelHeaderClose onClick={noop}>
Закрыть
</PanelHeaderClose>

<PanelHeaderClose onClick={noop}>
<span>Закрыть</span>
</PanelHeaderClose>

<PanelHeaderClose onClick={noop} children="Закрыть" />
</React.Fragment>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { noop, PanelHeaderEdit } from '@vkontakte/vkui';
import React from 'react';

const App = () => {
return (
<React.Fragment>
<PanelHeaderEdit label="Label" onClick={noop}>
Edit Label
</PanelHeaderEdit>

<PanelHeaderEdit label="Label" children={'Edit Label'} onClick={noop} />
</React.Fragment>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { noop, PanelHeaderSubmit } from '@vkontakte/vkui';
import React from 'react';

const App = () => {
return (
<React.Fragment>
<PanelHeaderSubmit onClick={noop}>
Закрыть
</PanelHeaderSubmit>

<PanelHeaderSubmit onClick={noop}>
<span>Закрыть</span>
</PanelHeaderSubmit>

<PanelHeaderSubmit onClick={noop} children="Закрыть" />
</React.Fragment>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`panel-header-back transforms correctly 1`] = `
"import { noop, PanelHeaderBack } from '@vkontakte/vkui';
import React from 'react';

const App = () => {
return (
(<React.Fragment>
<PanelHeaderBack onClick={noop} label={"Закрыть"} hideLabelOnVKCom hideLabelOnIOS></PanelHeaderBack>
<PanelHeaderBack
onClick={noop}
label={<><span>Закрыть</span></>}
hideLabelOnVKCom
hideLabelOnIOS></PanelHeaderBack>
<PanelHeaderBack onClick={noop} label="Закрыть" hideLabelOnVKCom hideLabelOnIOS />
</React.Fragment>)
);
};"
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`panel-header-close transforms correctly 1`] = `
"import { noop, PanelHeaderClose } from '@vkontakte/vkui';
import React from 'react';

const App = () => {
return (
(<React.Fragment>
<PanelHeaderClose onClick={noop} label={"Закрыть"}></PanelHeaderClose>
<PanelHeaderClose onClick={noop} label={<><span>Закрыть</span></>}></PanelHeaderClose>
<PanelHeaderClose onClick={noop} label="Закрыть" />
</React.Fragment>)
);
};"
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`panel-header-edit transforms correctly 1`] = `
"import { noop, PanelHeaderEdit } from '@vkontakte/vkui';
import React from 'react';

const App = () => {
return (
(<React.Fragment>
<PanelHeaderEdit onClick={noop}></PanelHeaderEdit>
<PanelHeaderEdit onClick={noop} />
</React.Fragment>)
);
};"
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`panel-header-submit transforms correctly 1`] = `
"import { noop, PanelHeaderSubmit } from '@vkontakte/vkui';
import React from 'react';

const App = () => {
return (
(<React.Fragment>
<PanelHeaderSubmit onClick={noop} label={"Закрыть"}></PanelHeaderSubmit>
<PanelHeaderSubmit onClick={noop} label={<><span>Закрыть</span></>}></PanelHeaderSubmit>
<PanelHeaderSubmit onClick={noop} label="Закрыть" />
</React.Fragment>)
);
};"
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
jest.autoMockOff();

import { defineSnapshotTestFromFixture } from '../../../testHelpers/testHelper';

const name = 'panel-header-back';
const fixtures = ['basic'] as const;

describe(name, () => {
fixtures.forEach((test) =>
defineSnapshotTestFromFixture(__dirname, name, global.TRANSFORM_OPTIONS, `${name}/${test}`),
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
jest.autoMockOff();

import { defineSnapshotTestFromFixture } from '../../../testHelpers/testHelper';

const name = 'panel-header-close';
const fixtures = ['basic'] as const;

describe(name, () => {
fixtures.forEach((test) =>
defineSnapshotTestFromFixture(__dirname, name, global.TRANSFORM_OPTIONS, `${name}/${test}`),
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
jest.autoMockOff();

import { defineSnapshotTestFromFixture } from '../../../testHelpers/testHelper';

const name = 'panel-header-edit';
const fixtures = ['basic'] as const;

describe(name, () => {
fixtures.forEach((test) =>
defineSnapshotTestFromFixture(__dirname, name, global.TRANSFORM_OPTIONS, `${name}/${test}`),
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
jest.autoMockOff();

import { defineSnapshotTestFromFixture } from '../../../testHelpers/testHelper';

const name = 'panel-header-submit';
const fixtures = ['basic'] as const;

describe(name, () => {
fixtures.forEach((test) =>
defineSnapshotTestFromFixture(__dirname, name, global.TRANSFORM_OPTIONS, `${name}/${test}`),
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { API, ASTPath, Collection, JSXAttribute, JSXElement } from 'jscodeshift';
import { removeAttribute } from '../../../codemod-helpers';
import { report } from '../../../report';

export const moveFromChildrenToLabel = (
api: API,
source: Collection,
localName: string,
needToAddHideLabelProps = false,
) => {
const j = api.jscodeshift;

// Находим все JSX элементы с указанным именем
source
.find(j.JSXElement)
.filter((path: ASTPath<JSXElement>) => {
const elementName = path.node.openingElement.name;
return elementName.type === 'JSXIdentifier' && elementName.name === localName;
})
.forEach((path: ASTPath<JSXElement>) => {
const element = path.node;
const openingElement = element.openingElement;

const existingLabelProp = openingElement.attributes?.find(
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'label',
) as JSXAttribute;

// Получаем содержимое из props children
const childrenProp = openingElement.attributes?.find(
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'children',
);

// Получаем содержимое из обычных children
const regularChildren = element.children?.filter(
(child) => child.type !== 'JSXText' || child.value.trim() !== '',
);

let labelValue;

if (childrenProp && childrenProp.type === 'JSXAttribute') {
// Если есть проп children
if (childrenProp.value?.type === 'JSXElement') {
// Если children содержит JSX элемент, оборачиваем его в Fragment
labelValue = j.jsxExpressionContainer(
j.jsxFragment(j.jsxOpeningFragment(), j.jsxClosingFragment(), [childrenProp.value]),
);
} else {
labelValue = childrenProp.value;
}
removeAttribute(openingElement.attributes, childrenProp);
} else if (regularChildren && regularChildren.length > 0) {
if (regularChildren.length === 1 && regularChildren[0].type === 'JSXText') {
const firstChild = regularChildren[0];
if (firstChild.type === 'JSXText') {
labelValue = j.jsxExpressionContainer(j.stringLiteral(firstChild.value.trim()));
}
} else {
// Оборачиваем все children в Fragment
labelValue = j.jsxExpressionContainer(
j.jsxFragment(j.jsxOpeningFragment(), j.jsxClosingFragment(), regularChildren),
);
}
}

if (labelValue) {
if (existingLabelProp) {
report(
api,
`Manual changes required for ${localName}'s "label" prop. Need to remove "children" prop. You can mode "children" value to "label" prop`,
);
return;
}

// Очищаем существующие children
element.children = [];
// Добавляем проп label
openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier('label'), labelValue));
if (needToAddHideLabelProps) {
// Добавляем проп hideLabelOnVKCom и hideLabelOnIOS, так как раньше children был скрыт визуально
// и после того как мы перенесли children в label, визуально ничего не должно измениться
openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier('hideLabelOnVKCom')));
openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier('hideLabelOnIOS')));
}
}
});

return source.toSource();
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { API, ASTPath, Collection, JSXElement } from 'jscodeshift';

export const removeChildrenFromComponent = (api: API, source: Collection, localName: string) => {
const j = api.jscodeshift;
source
.find(j.JSXElement)
.filter((path: ASTPath<JSXElement>) => {
const elementName = path.node.openingElement.name;
return elementName.type === 'JSXIdentifier' && elementName.name === localName;
})
.forEach((path: ASTPath<JSXElement>) => {
const element = path.node;
element.children = [];
});
};
21 changes: 21 additions & 0 deletions packages/codemods/src/transforms/v7/panel-header-back.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { API, FileInfo } from 'jscodeshift';
import { getImportInfo } from '../../codemod-helpers';
import { JSCodeShiftOptions } from '../../types';
import { moveFromChildrenToLabel } from './common/moveFromChildrenToLabel';

export const parser = 'tsx';

export default function transformer(file: FileInfo, api: API, options: JSCodeShiftOptions) {
const { alias } = options;
const j = api.jscodeshift;
const source = j(file.source);
const { localName } = getImportInfo(j, file, 'PanelHeaderBack', alias);

if (!localName) {
return source.toSource();
}

moveFromChildrenToLabel(api, source, localName, true);

return source.toSource();
}
21 changes: 21 additions & 0 deletions packages/codemods/src/transforms/v7/panel-header-close.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { API, FileInfo } from 'jscodeshift';
import { getImportInfo } from '../../codemod-helpers';
import { JSCodeShiftOptions } from '../../types';
import { moveFromChildrenToLabel } from './common/moveFromChildrenToLabel';

export const parser = 'tsx';

export default function transformer(file: FileInfo, api: API, options: JSCodeShiftOptions) {
const { alias } = options;
const j = api.jscodeshift;
const source = j(file.source);
const { localName } = getImportInfo(j, file, 'PanelHeaderClose', alias);

if (!localName) {
return source.toSource();
}

moveFromChildrenToLabel(api, source, localName, false);

return source.toSource();
}
22 changes: 22 additions & 0 deletions packages/codemods/src/transforms/v7/panel-header-edit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { API, FileInfo } from 'jscodeshift';
import { getImportInfo, removeProps } from '../../codemod-helpers';
import { JSCodeShiftOptions } from '../../types';
import { removeChildrenFromComponent } from './common/removeChildrenFromComponent';

export const parser = 'tsx';

export default function transformer(file: FileInfo, api: API, options: JSCodeShiftOptions) {
const { alias } = options;
const j = api.jscodeshift;
const source = j(file.source);
const { localName } = getImportInfo(j, file, 'PanelHeaderEdit', alias);

if (!localName) {
return source.toSource();
}

removeProps(j, api, source, localName, ['children', 'label']);
removeChildrenFromComponent(api, source, localName);

return source.toSource();
}
21 changes: 21 additions & 0 deletions packages/codemods/src/transforms/v7/panel-header-submit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { API, FileInfo } from 'jscodeshift';
import { getImportInfo } from '../../codemod-helpers';
import { JSCodeShiftOptions } from '../../types';
import { moveFromChildrenToLabel } from './common/moveFromChildrenToLabel';

export const parser = 'tsx';

export default function transformer(file: FileInfo, api: API, options: JSCodeShiftOptions) {
const { alias } = options;
const j = api.jscodeshift;
const source = j(file.source);
const { localName } = getImportInfo(j, file, 'PanelHeaderSubmit', alias);

if (!localName) {
return source.toSource();
}

moveFromChildrenToLabel(api, source, localName, false);

return source.toSource();
}
Loading