From bf65201e8fcf2a1864fbd44f49969bd995e5ae41 Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Tue, 3 Sep 2024 14:43:30 +0300 Subject: [PATCH 1/5] feat(ScreenSpinner): remove size prop from component --- .../src/components/ScreenSpinner/ScreenSpinnerLoader.tsx | 7 +++---- packages/vkui/src/components/ScreenSpinner/types.tsx | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/vkui/src/components/ScreenSpinner/ScreenSpinnerLoader.tsx b/packages/vkui/src/components/ScreenSpinner/ScreenSpinnerLoader.tsx index 66de100d54..fd822cbf21 100644 --- a/packages/vkui/src/components/ScreenSpinner/ScreenSpinnerLoader.tsx +++ b/packages/vkui/src/components/ScreenSpinner/ScreenSpinnerLoader.tsx @@ -3,13 +3,12 @@ import { Spinner } from '../Spinner/Spinner'; import type { SpinnerProps } from '../Spinner/Spinner'; import styles from './ScreenSpinner.module.css'; -export const ScreenSpinnerLoader: React.FC = ({ - size = 'large', +export const ScreenSpinnerLoader: React.FC> = ({ children = 'Пожалуйста, подождите...', ...restProps -}: SpinnerProps) => { +}) => { return ( - + {children} ); diff --git a/packages/vkui/src/components/ScreenSpinner/types.tsx b/packages/vkui/src/components/ScreenSpinner/types.tsx index 67ed3ed465..7fd8ffa877 100644 --- a/packages/vkui/src/components/ScreenSpinner/types.tsx +++ b/packages/vkui/src/components/ScreenSpinner/types.tsx @@ -1,7 +1,7 @@ import type { SpinnerProps } from '../Spinner/Spinner'; -export interface ScreenSpinnerProps extends SpinnerProps { +export type ScreenSpinnerProps = Omit & { state?: 'loading' | 'cancelable' | 'done' | 'error'; mode?: 'shadow' | 'overlay'; cancelLabel?: string; -} +}; From f17f40bace3e6d7b321103fa5cf0dc4c524d663b Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Thu, 5 Sep 2024 14:55:22 +0300 Subject: [PATCH 2/5] feat(ScreenSpinner): add customIcon prop to component --- .../src/components/ScreenSpinner/Readme.md | 13 +++++++++++ .../ScreenSpinner/ScreenSpinner.module.css | 3 ++- .../ScreenSpinner/ScreenSpinner.stories.tsx | 7 ++++++ .../ScreenSpinner/ScreenSpinner.tsx | 3 ++- .../ScreenSpinner/ScreenSpinnerContainer.tsx | 6 +++-- .../ScreenSpinner/ScreenSpinnerSwapIcon.tsx | 22 +++++++++++++------ .../src/components/ScreenSpinner/context.ts | 1 + .../src/components/ScreenSpinner/types.tsx | 7 +++++- 8 files changed, 50 insertions(+), 12 deletions(-) diff --git a/packages/vkui/src/components/ScreenSpinner/Readme.md b/packages/vkui/src/components/ScreenSpinner/Readme.md index 7d497ec24d..8cfdd500d2 100644 --- a/packages/vkui/src/components/ScreenSpinner/Readme.md +++ b/packages/vkui/src/components/ScreenSpinner/Readme.md @@ -43,6 +43,12 @@ const setCancelableScreenSpinner = () => { setPopout(); }; +const setScreenSpinnerWithCustomIcon = () => { + setPopout(} />); + + setTimeout(clearPopout, 20000); +}; + @@ -53,6 +59,9 @@ const setCancelableScreenSpinner = () => { Запустить успешный процесс Запустить процесс с ошибкой Запустить отменяемый процесс + + Запустить спинер с кастомной иконкой + @@ -72,5 +81,9 @@ const setCancelableScreenSpinner = () => { + }> + + + ``` diff --git a/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.module.css b/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.module.css index 0bbd80c9a4..11efbefc86 100644 --- a/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.module.css +++ b/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.module.css @@ -23,7 +23,8 @@ } .ScreenSpinner--state-done .ScreenSpinner__spinner, -.ScreenSpinner--state-error .ScreenSpinner__spinner { +.ScreenSpinner--state-error .ScreenSpinner__spinner, +.ScreenSpinner--state-custom .ScreenSpinner__spinner { opacity: 0; } diff --git a/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.stories.tsx b/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.stories.tsx index ebfdfb3eec..e64e9d8afb 100644 --- a/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.stories.tsx +++ b/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.stories.tsx @@ -1,11 +1,18 @@ import type { Meta, StoryObj } from '@storybook/react'; import { CanvasFullLayout, DisableCartesianParam } from '../../storybook/constants'; +import { createFieldWithPresets } from '../../testing/presets'; import { ScreenSpinner, type ScreenSpinnerProps } from './ScreenSpinner'; const story: Meta = { title: 'Popouts/ScreenSpinner', component: ScreenSpinner, parameters: { ...CanvasFullLayout, ...DisableCartesianParam }, + argTypes: { + customIcon: createFieldWithPresets({ + iconSizes: ['56'], + sizeIconsCount: 50, + }), + }, }; export default story; diff --git a/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.tsx b/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.tsx index 92ccf69e94..b4a8d386be 100644 --- a/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.tsx +++ b/packages/vkui/src/components/ScreenSpinner/ScreenSpinner.tsx @@ -22,13 +22,14 @@ export const ScreenSpinner: React.FC & { onClick, cancelLabel, mode, + customIcon, ...restProps }: ScreenSpinnerProps): React.ReactNode => { useScrollLock(); return ( - + diff --git a/packages/vkui/src/components/ScreenSpinner/ScreenSpinnerContainer.tsx b/packages/vkui/src/components/ScreenSpinner/ScreenSpinnerContainer.tsx index bfca042fa5..fb65b7e842 100644 --- a/packages/vkui/src/components/ScreenSpinner/ScreenSpinnerContainer.tsx +++ b/packages/vkui/src/components/ScreenSpinner/ScreenSpinnerContainer.tsx @@ -10,6 +10,7 @@ const stateClassNames = { cancelable: styles['ScreenSpinner--state-cancelable'], done: styles['ScreenSpinner--state-done'], error: styles['ScreenSpinner--state-error'], + custom: styles['ScreenSpinner--state-custom'], }; const modeClassNames = { @@ -18,15 +19,16 @@ const modeClassNames = { }; type ScreenSpinnerContainerProps = HTMLAttributesWithRootRef & - Pick; + Pick; export const ScreenSpinnerContainer: React.FC = ({ state = 'loading', mode = 'shadow', + customIcon, ...restProps }: ScreenSpinnerContainerProps) => { return ( - + = ({ cancelLabel, ...restProps }: ScreenSpinnerSwapIconProps) => { - const { state } = React.useContext(ScreenSpinnerContext); + const { state, customIcon } = React.useContext(ScreenSpinnerContext); if (state === 'cancelable') { return ; } - const Icon = { - loading: () => null, - done: Icon48DoneOutline, - error: Icon48CancelCircle, - }[state]; + const getContent = () => { + if (state === 'custom') { + return customIcon; + } + + const Icon = { + loading: () => null, + done: Icon48DoneOutline, + error: Icon48CancelCircle, + }[state]; + + return ; + }; return ( - + {getContent()} ); }; diff --git a/packages/vkui/src/components/ScreenSpinner/context.ts b/packages/vkui/src/components/ScreenSpinner/context.ts index a19ca78e6e..5e46661b4e 100644 --- a/packages/vkui/src/components/ScreenSpinner/context.ts +++ b/packages/vkui/src/components/ScreenSpinner/context.ts @@ -3,6 +3,7 @@ import { type ScreenSpinnerProps } from './types'; export interface ScreenSpinnerContextProps { state: NonNullable; + customIcon?: ScreenSpinnerProps['customIcon']; } export const ScreenSpinnerContext: React.Context = diff --git a/packages/vkui/src/components/ScreenSpinner/types.tsx b/packages/vkui/src/components/ScreenSpinner/types.tsx index 7fd8ffa877..7802585a33 100644 --- a/packages/vkui/src/components/ScreenSpinner/types.tsx +++ b/packages/vkui/src/components/ScreenSpinner/types.tsx @@ -1,7 +1,12 @@ +import type * as React from 'react'; import type { SpinnerProps } from '../Spinner/Spinner'; export type ScreenSpinnerProps = Omit & { - state?: 'loading' | 'cancelable' | 'done' | 'error'; + state?: 'loading' | 'cancelable' | 'done' | 'error' | 'custom'; + /** + * Кастомная иконка, работает совместно со `state="custom"` + */ + customIcon?: React.ReactNode; mode?: 'shadow' | 'overlay'; cancelLabel?: string; }; From 90f559c99218695315230a8cf4ec91fd3bb0cc91 Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Mon, 9 Sep 2024 20:13:21 +0300 Subject: [PATCH 3/5] tech: add remove size prop codemod for v7 --- .../screen-spinner/basic.input.tsx | 17 +++++++ .../__snapshots__/screen-spinner.ts.snap | 18 ++++++++ .../transforms/v7/__tests__/screen-spinner.ts | 11 +++++ .../src/transforms/v7/screen-spinner.ts | 45 +++++++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 packages/codemods/src/transforms/v7/__testfixtures__/screen-spinner/basic.input.tsx create mode 100644 packages/codemods/src/transforms/v7/__tests__/__snapshots__/screen-spinner.ts.snap create mode 100644 packages/codemods/src/transforms/v7/__tests__/screen-spinner.ts create mode 100644 packages/codemods/src/transforms/v7/screen-spinner.ts diff --git a/packages/codemods/src/transforms/v7/__testfixtures__/screen-spinner/basic.input.tsx b/packages/codemods/src/transforms/v7/__testfixtures__/screen-spinner/basic.input.tsx new file mode 100644 index 0000000000..ec9b917494 --- /dev/null +++ b/packages/codemods/src/transforms/v7/__testfixtures__/screen-spinner/basic.input.tsx @@ -0,0 +1,17 @@ +import { ScreenSpinner } from '@vkontakte/vkui'; +import React from 'react'; + +const App = () => { + return ( + + + + + + + + ); +}; diff --git a/packages/codemods/src/transforms/v7/__tests__/__snapshots__/screen-spinner.ts.snap b/packages/codemods/src/transforms/v7/__tests__/__snapshots__/screen-spinner.ts.snap new file mode 100644 index 0000000000..2d573580bd --- /dev/null +++ b/packages/codemods/src/transforms/v7/__tests__/__snapshots__/screen-spinner.ts.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`screen-spinner transforms correctly 1`] = ` +"import { ScreenSpinner } from '@vkontakte/vkui'; +import React from 'react'; + +const App = () => { + return ( + ( + + + + + + ) + ); +};" +`; diff --git a/packages/codemods/src/transforms/v7/__tests__/screen-spinner.ts b/packages/codemods/src/transforms/v7/__tests__/screen-spinner.ts new file mode 100644 index 0000000000..515672ebf3 --- /dev/null +++ b/packages/codemods/src/transforms/v7/__tests__/screen-spinner.ts @@ -0,0 +1,11 @@ +jest.autoMockOff(); +import { defineSnapshotTestFromFixture } from '../../../testHelpers/testHelper'; + +const name = 'screen-spinner'; +const fixtures = ['basic'] as const; + +describe(name, () => { + fixtures.forEach((test) => + defineSnapshotTestFromFixture(__dirname, name, global.TRANSFORM_OPTIONS, `${name}/${test}`), + ); +}); diff --git a/packages/codemods/src/transforms/v7/screen-spinner.ts b/packages/codemods/src/transforms/v7/screen-spinner.ts new file mode 100644 index 0000000000..9064909dca --- /dev/null +++ b/packages/codemods/src/transforms/v7/screen-spinner.ts @@ -0,0 +1,45 @@ +import {API, ASTPath, Collection, FileInfo, JSXAttribute} from "jscodeshift"; +import {getImportInfo} from "../../codemod-helpers"; +import {JSCodeShiftOptions} from "../../types"; + +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, 'ScreenSpinner', alias); + + if (!localName) { + return source.toSource(); + } + + function removeSizeProp(attribute: ASTPath) { + attribute.node.name.name === 'size' && j(attribute).remove() + } + + // Обработка ScreenSpinner + source + .find(j.JSXOpeningElement) + .filter( + (path) => path.value.name.type === 'JSXIdentifier' && path.value.name.name === localName, + ) + .find(j.JSXAttribute) + .forEach(removeSizeProp) + + // Обработка ScreenSpinner.Loader + source + .find(j.JSXElement, { + openingElement: { + name: { + type: 'JSXMemberExpression', + object: { name: localName }, + property: { name: 'Loader' } + } + } + }) + .find(j.JSXAttribute) + .forEach(removeSizeProp) + + return source.toSource(); +} From e58c7165c2e49a19880033de5eeaf2c4e1d1b768 Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Tue, 10 Sep 2024 14:03:39 +0300 Subject: [PATCH 4/5] fix: run prettier --- .../src/transforms/v7/screen-spinner.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/codemods/src/transforms/v7/screen-spinner.ts b/packages/codemods/src/transforms/v7/screen-spinner.ts index 9064909dca..8427a8f0f1 100644 --- a/packages/codemods/src/transforms/v7/screen-spinner.ts +++ b/packages/codemods/src/transforms/v7/screen-spinner.ts @@ -1,6 +1,6 @@ -import {API, ASTPath, Collection, FileInfo, JSXAttribute} from "jscodeshift"; -import {getImportInfo} from "../../codemod-helpers"; -import {JSCodeShiftOptions} from "../../types"; +import { API, ASTPath, Collection, FileInfo, JSXAttribute } from 'jscodeshift'; +import { getImportInfo } from '../../codemod-helpers'; +import { JSCodeShiftOptions } from '../../types'; export const parser = 'tsx'; @@ -15,7 +15,7 @@ export default function transformer(file: FileInfo, api: API, options: JSCodeShi } function removeSizeProp(attribute: ASTPath) { - attribute.node.name.name === 'size' && j(attribute).remove() + attribute.node.name.name === 'size' && j(attribute).remove(); } // Обработка ScreenSpinner @@ -25,7 +25,7 @@ export default function transformer(file: FileInfo, api: API, options: JSCodeShi (path) => path.value.name.type === 'JSXIdentifier' && path.value.name.name === localName, ) .find(j.JSXAttribute) - .forEach(removeSizeProp) + .forEach(removeSizeProp); // Обработка ScreenSpinner.Loader source @@ -34,12 +34,12 @@ export default function transformer(file: FileInfo, api: API, options: JSCodeShi name: { type: 'JSXMemberExpression', object: { name: localName }, - property: { name: 'Loader' } - } - } + property: { name: 'Loader' }, + }, + }, }) .find(j.JSXAttribute) - .forEach(removeSizeProp) + .forEach(removeSizeProp); return source.toSource(); } From 9d42b12ea72e5a11aa9f9339a6ef034dc79e847d Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Mon, 16 Sep 2024 16:03:07 +0300 Subject: [PATCH 5/5] fix: remove import --- packages/codemods/src/transforms/v7/screen-spinner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/codemods/src/transforms/v7/screen-spinner.ts b/packages/codemods/src/transforms/v7/screen-spinner.ts index 8427a8f0f1..2615613c54 100644 --- a/packages/codemods/src/transforms/v7/screen-spinner.ts +++ b/packages/codemods/src/transforms/v7/screen-spinner.ts @@ -1,4 +1,4 @@ -import { API, ASTPath, Collection, FileInfo, JSXAttribute } from 'jscodeshift'; +import { API, ASTPath, FileInfo, JSXAttribute } from 'jscodeshift'; import { getImportInfo } from '../../codemod-helpers'; import { JSCodeShiftOptions } from '../../types';