From 408f22b78ff2d83d6a49df531278b9cc28fc1117 Mon Sep 17 00:00:00 2001 From: Inomdzhon Mirdzhamolov Date: Fri, 8 Dec 2023 16:04:32 +0300 Subject: [PATCH] refactor: migration_v6.md (#6238) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: migration_v6.md - Добавил блок "Содержание". Для это в Styleguide добавил возможность навигироваться по заголовкам. - Отформатировал текста. - Изменил структуру. * fix(migration_v6.md): add link to "Интеграция с VK Mini Apps" * chore: fix typo * chore: fix typo x2 * fix(migration_v6.md): fix some headers --------- Co-authored-by: Victoria Zhizhonkova --- .../Components/Heading/HeadingRenderer.js | 25 +- styleguide/Components/Link/LinkRenderer.js | 42 +- styleguide/pages/migration_v6.md | 385 ++++++++++-------- styleguide/utils/index.js | 11 + styleguide/utils/third-party/lodash/index.js | 33 ++ .../utils/third-party/lodash/unicodeWords.js | 87 ++++ styleguide/utils/third-party/lodash/words.js | 42 ++ .../third-party/react-children-utils/index.js | 40 ++ 8 files changed, 492 insertions(+), 173 deletions(-) create mode 100644 styleguide/utils/third-party/lodash/index.js create mode 100644 styleguide/utils/third-party/lodash/unicodeWords.js create mode 100644 styleguide/utils/third-party/lodash/words.js create mode 100644 styleguide/utils/third-party/react-children-utils/index.js diff --git a/styleguide/Components/Heading/HeadingRenderer.js b/styleguide/Components/Heading/HeadingRenderer.js index cce4ea4e08..1c07fecda9 100644 --- a/styleguide/Components/Heading/HeadingRenderer.js +++ b/styleguide/Components/Heading/HeadingRenderer.js @@ -1,24 +1,43 @@ import * as React from 'react'; import { classNames, Headline, Title } from '@vkui'; +import { generateIdByReactNode } from '../../utils'; import './Heading.css'; const HeadingRenderer = ({ level, children, className }) => { + const id = generateIdByReactNode(children); switch (level) { case 1: return ( - + <Title + id={id} + className={classNames('Heading', 'Heading--1', className)} + level="1" + Component="h1" + > {children} ); case 2: return ( - + <Title + id={id} + className={classNames('Heading', 'Heading--2', className)} + weight="2" + level="2" + Component="h2" + > {children} ); default: return ( - + {children} ); diff --git a/styleguide/Components/Link/LinkRenderer.js b/styleguide/Components/Link/LinkRenderer.js index 6caae29e21..89f807a65f 100644 --- a/styleguide/Components/Link/LinkRenderer.js +++ b/styleguide/Components/Link/LinkRenderer.js @@ -1,10 +1,46 @@ import * as React from 'react'; import { Link } from '@vkui'; +import { generateIdByReactNode } from '../../utils'; -export const LinkRenderer = ({ href: _href, ...restProps }) => { - const href = _href?.replace('https://vkcom.github.io/VKUI/', ''); +const resolveHref = (hrefProp, children) => { + if (hrefProp) { + if (hrefProp === '{{anchor}}') { + const id = generateIdByReactNode(children); + return { + scrollTo() { + const el = document.getElementById(id); + if (el) { + window.scrollTo({ behavior: 'smooth', top: el.offsetTop }); + } + }, + native: undefined, + }; + } - return ; + return { + scrollTo: null, + native: hrefProp.replace('https://vkcom.github.io/VKUI/', ''), + }; + } +}; + +export const LinkRenderer = ({ href: hrefProp, onClick, children, ...restProps }) => { + const href = resolveHref(hrefProp, children); + + const handleClick = (event) => { + if (onClick) { + onClick(event); + } + if (href.scrollTo !== null) { + href.scrollTo(); + } + }; + + return ( + + {children} + + ); }; export default LinkRenderer; diff --git a/styleguide/pages/migration_v6.md b/styleguide/pages/migration_v6.md index 52aeb0ba59..2b58866954 100644 --- a/styleguide/pages/migration_v6.md +++ b/styleguide/pages/migration_v6.md @@ -1,119 +1,107 @@ > Документацию по миграции с **v4** на **v5** можно найти [здесь](https://github.com/VKCOM/VKUI/releases/tag/v5.0.1). -## Обновление React +## Содержание -- Минимальная поддерживаемая версия **React** увеличена до `v18.2.0`. +- Автоматизация обновления до v6 +- Зависимости +- Сборка +- Константы +- Компоненты +- `unstable_` компоненты +- Интеграция с VK Mini Apps -## Поддержка браузеров +
+
+
-Библиотека по умолчанию компилируется в [ES2015 (ES6)](https://262.ecma-international.org/6.0/). -Список поддерживаемых браузеров находится в [.browserslistrc](https://github.com/VKCOM/VKUI/blob/v6.0.0/.browserslistrc). +## Автоматизация обновления до v6 -> В VKUI есть [специальная сборка](https://vkcom.github.io/VKUI/#/CSS%20Modules) в ESNext, которая -> позволяет уменьшить размер вашего приложения. +> Пока для перевода доступны только `Typescript`-файлы (`*.ts`, `*.tsx`). -## Перечисления заменены на объекты +Чтобы упростить переход на новую мажорную версию, можно воспользоваться инструментом по +автоматической миграции ваших компонентов. -Следующие перечисления были заменены на [объекты](https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums): - -- `Platform` -- `Appearance` -- `SizeType` -- `ViewWidth` -- `ViewHeight` +1. Для начала обновите ваше приложение до новой мажорной версии (**v6**) в соответствии с требованиями + вашего пакетного менеджера и среды. -## Удалили интеграцию с [VK Mini Apps](https://vk.com/miniapps) и [@vkontakte/vk-bridge](https://www.npmjs.com/package/@vkontakte/vk-bridge) +2. Перейдите в директорию с исходниками вашего проекта (обычно это `src/`) и запустите команду `npx @vkontakte/vkui-codemods`. -> **Note** -> -> Этот Breaking Change предназначен для разработчиков мини-приложений ВКонтакте. Если вы таким -> не являетесь, то смело пропускайте эту секцию. +3. То, что можно изменить на месте, подвергнется миграции, о более сложных кейсах вы будете + оповещены в консоли по ходу выполнения команды из **п.2**. -Изначально, **VKUI** создавался как инструмент для создания клиентской части мини-приложений [ВКонтакте](https://vk.com). -Сейчас **VKUI** уже больше чем просто мини-приложения. Разработчики используют библиотеку, чтобы -создавать полноценные независимые приложения, которые никак не связаны с [VK Mini Apps](https://vk.com/miniapps). +
-В связи с этим мы отказались от завязки на мини-приложения [ВКонтакте](https://vk.com). Для этого мы -удалили интеграцию с библиотекой [VK Bridge](https://www.npmjs.com/package/@vkontakte/vk-bridge), а -также убрали упоминания о [VK Mini Apps](https://vk.com/miniapps) в документации. Это привнесло в -библиотеку ряд изменений касающихся API. - -### Конфигурация VKUI - -Из [VK Bridge](https://www.npmjs.com/package/@vkontakte/vk-bridge) мы доставали несколько настроек: - -1. тему (`light` или `dark`); -2. параметры адаптивности; -3. размеры безопасных зон (в CSS это `--safe-area-insets-*`); -4. открыто веб-вью или нет. - -Первые три пункта перенесли в библиотеку [@vkontakte/vk-bridge-react](https://www.npmjs.com/package/@vkontakte/vk-bridge-react). +Информацию по доступным параметрам можно узнать через опцию `--help` -Помимо **VK Bridge**, была завязка на мини-приложения в свойстве `webviewType` за счёт свойства -`"vkapps"`. Теперь это свойство `hasCustomPanelHeaderAfter`, который по умолчанию `false`. +```shell +npx @vkontakte/vkui-codemods --help +``` -Бойлерплейт для **VK Mini Apps** представлен на странице [Интеграция с VK Mini Apps](https://vkcom.github.io/VKUI/#/integrations-vk-mini-apps) -под заголовком **Конфигурация VKUI**. +Более подробная инструкция расположена на странице пакета [@vkontakte/vkui-codemods](https://www.npmjs.com/package/@vkontakte/vkui-codemods). -### ~~`withInsets`~~ +



-- Используйте вместо него хук `useInsets()` из [@vkontakte/vk-bridge-react](https://www.npmjs.com/package/@vkontakte/vk-bridge-react). +## Зависимости -### ~~`HasInsets`~~ +
-- Используйте вместо него `SafeAreaInsets`. -- Если вы используете [@vkontakte/vk-bridge](https://www.npmjs.com/package/@vkontakte/vk-bridge), то - вы можете объявить тип у себя следующим образом: +- Обновили минимально поддерживаемую версию [React](https://react.dev/) + до [v18.2.0](https://github.com/facebook/react/blob/main/CHANGELOG.md#1820-june-14-2022). +- Удалили зависимость [@vkontakte/vk-bridge](https://www.npmjs.com/package/@vkontakte/vk-bridge) + в рамках задачи по уменьшению сцепления с [VK Mini Apps](https://vk.com/miniapps) (см. подробнее в разделе Интеграция с VK Mini Apps). -```ts static -import type { Insets } form '@vkontakte/vk-brige'; +



-interface HasInsets { - insets?: Partial; -} -``` +## Сборка -

+
-## CSS Logical для [специальной сборки](https://vkcom.github.io/VKUI/#/CSS%20Modules) +- Обновили конфигурацию [`.browserlistrc`](https://github.com/VKCOM/VKUI/blob/master/.browserslistrc): -> **Note** -> -> Данное изменение не влияет на обычную сборку + ```diff + - android >= 5 + + ChromeAndroid >= 57 + - iOS >= 10 + + iOS >= 10.3 + - Chrome >= 51 + + Chrome >= 57 + Firefox >= 54 + Edge >= 18 + - Opera >= 38 + + Opera >= 44 + - Safari >= 10 + + Safari >= 10.1 + + + Samsung >= 7.2 + ``` -- Мы начинаем использовать [логические css свойства](https://www.w3.org/TR/css-logical-1/) вместо - физических. Если вам требуется [широкая браузерная поддержка](https://caniuse.com/css-logical-props), - рекомендуем воспользоваться [postcss-logical](https://www.npmjs.com/package/postcss-logical). +- В [специальной сборке](https://vkcom.github.io/VKUI/#/CSS%20Modules) теперь используется [CSS Logical](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_logical_properties_and_values). -

+ > Если вы используете [специальную сборку](https://vkcom.github.io/VKUI/#/CSS%20Modules) и вам + > требуется [широкая браузерная поддержка](https://caniuse.com/css-logical-props), рекомендуем + > воспользоваться [postcss-logical](https://www.npmjs.com/package/postcss-logical). -## Обновление компонентов до v6 +



-- Чтобы упростить переход на новую мажорную версию, можно воспользоваться инструментом по автоматической миграции ваших компонентов. +## Константы -> Для начала обновите ваше приложение до новой мажорной версии (**v6**) в соответствии с требованиями вашего пакетного менеджера и среды +
-> Обратите внимание, минимальная поддерживаемая версия **React** увеличена до `v18.2.0` +Следующие перечисления были заменены на [объекты](https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums): -> Пока для перевода доступны только `Typescript`-файлы (_.ts/_.tsx) +- `Platform` +- `Appearance` +- `SizeType` +- `ViewWidth` +- `ViewHeight` -Перейдите в директорию с исходниками вашего проекта (обычно это `src/`) и запустите следующую команду: +



-```shell -npx @vkontakte/vkui-codemods -``` +## Компоненты -Информацию по доступным параметрам можно узнать через опцию `--help` +
-```shell -npx @vkontakte/vkui-codemods --help -``` - -Более подробная инструкция расположена в [README](https://github.com/VKCOM/VKUI/blob/master/packages/codemods/README.md) - -

- -## [`Accordion`](#/Accordion) +### [`Accordion`](#/Accordion) - `Accordion` избавился от нативного элемента `detail`, теперь для компонента стали доступны анимации. @@ -140,9 +128,9 @@ npx @vkontakte/vkui-codemods --help ``` -

+
-## [`ActionSheet`](#/ActionSheet) +### [`ActionSheet`](#/ActionSheet) - Свойство `toggleRef` теперь обязательно. - Свойство `popupDirection` удалено, используйте `placement`. @@ -154,9 +142,9 @@ npx @vkontakte/vkui-codemods --help ``` -

+
-## [`ActionSheetItem`](#/ActionSheetItem) +### [`ActionSheetItem`](#/ActionSheetItem) - Свойство `autoClose` удалено, теперь это поведение по умолчанию. @@ -169,9 +157,9 @@ npx @vkontakte/vkui-codemods --help ``` -

+
-## [`Alert`](#/Alert) +### [`Alert`](#/Alert) - Свойство `autoClose` удалено, теперь это поведение по-умолчанию. @@ -195,9 +183,9 @@ npx @vkontakte/vkui-codemods --help /> ``` -

+
-## [`AppearanceProvider`](#/AppearanceProvider) +### [`AppearanceProvider`](#/AppearanceProvider) - По аналогии с остальными провайдерами свойство `appearance` заменено на `value`. @@ -206,9 +194,9 @@ npx @vkontakte/vkui-codemods --help + ... ``` -

+
-## [`Banner`](#/Banner) +### [`Banner`](#/Banner) - Убрали установку внешних отступов. Теперь, при необходимости, следует их добавлять самостоятельно. Соответственно, свойство `noPadding` удалёно. @@ -227,9 +215,9 @@ npx @vkontakte/vkui-codemods --help + ``` -

+
-## [`Calendar`](#/Calendar) +### [`Calendar`](#/Calendar) - Изменены a11y-свойства @@ -258,9 +246,9 @@ npx @vkontakte/vkui-codemods --help /> ``` -

+
-## [`CalendarRange`](#/CalendarRange) +### [`CalendarRange`](#/CalendarRange) - Изменены a11y-свойства @@ -283,9 +271,9 @@ npx @vkontakte/vkui-codemods --help /> ``` -

+
-## [`ConfigProvider`](#/ConfigProvider) +### [`ConfigProvider`](#/ConfigProvider) - `hasCustomPanelHeaderAfter` теперь по умолчанию `false`. - ~~`onDetectAppearanceByBridge`~~ удален, используйте хук `useAppearance()` из библиотеки @@ -308,9 +296,9 @@ npx @vkontakte/vkui-codemods --help /> ``` -

+
-## [`Chip`](#/ChipsInput) +### [`Chip`](#/ChipsInput) - Изменено a11y-свойство @@ -325,9 +313,9 @@ npx @vkontakte/vkui-codemods --help ``` -

+
-## [`ChipsInput`](#/ChipsInput) +### [`ChipsInput`](#/ChipsInput) - Компонент теперь может быть контролируемым и неконтролируемым. - `getOptionValue`, `getOptionLabel`, `getNewOptionData` – все аргументы функции теперь обязательны. @@ -350,9 +338,9 @@ npx @vkontakte/vkui-codemods --help /> ``` -

+
-## [`ContentCard`](#/ContentCard) +### [`ContentCard`](#/ContentCard) - Изменён тeг (с `h4` на `span`), в котором `header` компонента рендерится по умолчанию. Переопределить тег по умолчанию можно с помощью свойства `headerComponent`. @@ -361,24 +349,24 @@ npx @vkontakte/vkui-codemods --help ``` -

+
-## [`CustomScrollView`](#/CustomScrollView) +### [`CustomScrollView`](#/CustomScrollView) - Компонент больше не принимает свойства `window`/`document`. -

+
-## [`CustomSelect`](#/CustomSelect) +### [`CustomSelect`](#/CustomSelect) - Функция `onInputChange` больше не получает вторым параметром список опций, а также никак не обрабатывает результат исполнения. Для фильтрации обновляйте `props.options` самостоятельно или используйте свойство `filterFn`. - Удалено свойство `option` из `CustomSelectOption`. -

+
-## [`DateInput`](#/DateInput) +### [`DateInput`](#/DateInput) - Изменены a11y-свойства @@ -413,9 +401,9 @@ npx @vkontakte/vkui-codemods --help /> ``` -

+
-## [`DateRangeInput`](#/DateInputRange) +### [`DateRangeInput`](#/DateInputRange) - Изменены a11y-свойства @@ -462,25 +450,25 @@ npx @vkontakte/vkui-codemods --help /> ``` -

+
-## [`FixedLayout`](#/FixedLayout) +### [`FixedLayout`](#/FixedLayout) ```diff - ... + ... ``` -

+
-## [`Footer`](#/Footer) +### [`Footer`](#/Footer) - Вертикальный отступ теперь задаётся через `padding`, вместо `margin`, поэтому схлопывание `margin` будет исключено. -

+
-## [`FormItem`](#/FormItem) +### [`FormItem`](#/FormItem) - Изменён тeг (с `h5` на `span`), в котором значение `top` рендерится по умолчанию, если не указано свойство `htmlFor`. Если свойство `htmlFor` указано, но тег будет `label`. @@ -490,16 +478,16 @@ npx @vkontakte/vkui-codemods --help ``` -

+
-## [`Gradient`](#/Gradient) +### [`Gradient`](#/Gradient) - У свойства `mode` были удалены значения `black` и `white`, используйте `tint` или `default`. `default` теперь значение по умолчанию. -

+
-## [`Header`](#/Header) +### [`Header`](#/Header) - Теперь для подзаголовка `subtitle` можно задать тип тэга с помощью свойства `subtitleComponent`. @@ -509,9 +497,9 @@ npx @vkontakte/vkui-codemods --help ``` -

+
-## [`ModalCard`](#/ModalCard) и [`ModaCardBase`](#/ModaCardBase) +### [`ModalCard`](#/ModalCard) и [`ModaCardBase`](#/ModaCardBase) - Тeг, в котором значение `header` рендерится по умолчанию, изменён с `h2` на `span`. - Тег, в котором значение `subheader` рендерится по умолчанию, изменён с `h5` на `span`. @@ -526,18 +514,18 @@ npx @vkontakte/vkui-codemods --help /> ``` -

+
-## [`ModalPageHeader`](#/ModalPageHeader) +### [`ModalPageHeader`](#/ModalPageHeader) ```diff - ... + ... ``` -

+
-## [`Pagination`](#/Pagination) +### [`Pagination`](#/Pagination) - Свойство `getPageAriaLabel` переименовано в `getPageLabel` и обновлено: теперь оно принимает только `(isCurrent: boolean)` и не нуждается в номере страницы. Возвращайте текст с учетом того, @@ -556,22 +544,22 @@ npx @vkontakte/vkui-codemods --help /> ``` -

+
-## ~~`PanelHeader.Content`~~ +### ~~`PanelHeader.Content`~~ - Подкомпонент удален, используйте вместо него `typographyProps` у [`PanelHeader`](#/PanelHeader). -

+
-## ~~`PromoBanner`~~ +### ~~`PromoBanner`~~ - Компонент удален. - Для своей реализации, используйте событие [`VKWebAppShowBannerAd`](https://dev.vk.com/mini-apps/monetization/ad/banners). -

+
-## [`PullToRefresh`](#/PullToRefresh) +### [`PullToRefresh`](#/PullToRefresh) - До этого `runTapticImpactOccurred()` вызывался внутри компонента после вызова обработчика `onRefresh`. Сам `runTapticImpactOccurred()` через `vkBridge.send` вызывает событие `VKWebAppTapticImpactOccurred`. @@ -580,9 +568,9 @@ npx @vkontakte/vkui-codemods --help - Пример представлен на странице [Интеграция с VK Mini Apps](https://vkcom.github.io/VKUI/#/integrations-vk-mini-apps) под заголовком **Виброотклик (Taptic Engine)**. -

+
-## ~~`RangeSlider`~~ +### ~~`RangeSlider`~~ - Компонент удален, используйте [`Slider`](#/Slider). @@ -591,16 +579,16 @@ npx @vkontakte/vkui-codemods --help + ``` -

+
-## [`Search`](#/Search) +### [`Search`](#/Search) - Свойство `iconAriaLabel` переименовано в `iconLabel`. - Свойство `clearAriaLabel` переименовано в `clearLabel`. -

+
-## [`SimpleCell`](#/SimpleCell) +### [`SimpleCell`](#/SimpleCell) - Свойство `expandable` теперь не принимает значения типа `boolean`. @@ -612,23 +600,23 @@ npx @vkontakte/vkui-codemods --help + ... ``` -

+
-## [`Slider`](#/Slider) +### [`Slider`](#/Slider) - Свойство `step` теперь принимает значение `1` по умолчанию. - Функция `onChange` вторым параметром теперь дополнительно расширяется типом `React.ChangeEvent`. -

+
-## [`Spinner`](#/Spinner) +### [`Spinner`](#/Spinner) - У свойства `aria-label` теперь отсутствует значение по умолчанию, для доступности воспользуйтесь свойством `children`. -

+
-## [`SplitCol`](#/SplitCol) +### [`SplitCol`](#/SplitCol) ```diff @@ -637,12 +625,12 @@ npx @vkontakte/vkui-codemods --help ``` -

+
-## [`Tappable`](#/Tappable) +### [`Tappable`](#/Tappable) -Свойства `onEnter`, `onLeave`, `onStart`, `onEnd`, `onMove` и `stopPropagation` удалены. -Используйте вместо них [нативные свойства](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events#event_types_and_global_event_handlers). +- Свойства `onEnter`, `onLeave`, `onStart`, `onEnd`, `onMove` и `stopPropagation` удалены. + Используйте вместо них [нативные свойства](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events#event_types_and_global_event_handlers). ```diff ``` -### Улучшение доступности - -Теперь если в кликабельный компонент не был передано свойство `onClick` или `href`, то у такого -компонента будут отключены состояния наведения, активирования и ripple-эффекты. Если вы использовали -`disabled` для отключения состояний, рекомендуем удалить это свойство. +- Улучшение доступности. Теперь если в кликабельный компонент не был передано свойство `onClick` или + `href`, то у такого компонента будут отключены состояния наведения, активирования и ripple-эффекты. + Если вы использовали `disabled` для отключения состояний, рекомендуем удалить это свойство. ```diff ``` -

- ### ~~`Tooltip`~~ -> [`OnboardingTooltip`](#/OnboardingTooltip) - Стал доступнее за счёт `role="tooltip"` и `aria-describedby`. @@ -713,9 +697,9 @@ npx @vkontakte/vkui-codemods --help + ``` -## Typography +
-### [`Title`](#/Title) +### [`Typography/Title`](#/Title) - По умолчанию тeг в котором рендерится компонент теперь `span` и он больше не привязан к значению свойства `level`. @@ -725,7 +709,9 @@ npx @vkontakte/vkui-codemods --help ``` -### [`Headline`](#/Headline) +<br/> + +### [`Typography/Headline`](#/Headline) - Изменён тeг (с `h4` на `span`), в котором компонент рендерится по умолчанию. - Переопределить тeг по умолчанию можно с помощью свойства `Component`. @@ -734,7 +720,9 @@ npx @vkontakte/vkui-codemods --help <Headline Component="h4" /> ``` -### [`Subhead`](#/Subhead) +<br/> + +### [`Typography/Subhead`](#/Subhead) - Изменён тeг (с `h5` на `span`), в котором компонент рендерится по умолчанию. - Переопределить тeг по умолчанию можно с помощью свойства `Component`. @@ -743,9 +731,9 @@ npx @vkontakte/vkui-codemods --help <Subhead Component="h5" /> ``` -<br/><br/> +<br/> -## [`UsersStack`](#/UsersStack) +### [`UsersStack`](#/UsersStack) ```diff - <UsersStack layout="vertical">...</UsersStack> @@ -755,9 +743,9 @@ npx @vkontakte/vkui-codemods --help + <UsersStack direction="row">...</UsersStack> ``` -<br/><br/> +<br/> -## ~~`VisuallyHiddenInput`~~ +### ~~`VisuallyHiddenInput`~~ - Компонент удален, используйте [`VisuallyHidden`](#/VisuallyHidden). @@ -766,9 +754,11 @@ npx @vkontakte/vkui-codemods --help + <VisuallyHidden Component="input" /> ``` -<br/><br/> +<br/><br/><hr/><br/> + +## `unstable_` компоненты -## Unstable +<br/> ### 🎉 ~~`unstable_ChipsSelect`~~ -> [`ChipsSelect`](#/ChipsSelect) @@ -805,6 +795,8 @@ npx @vkontakte/vkui-codemods --help /> ``` +<br/> + ### 🎉 ~~`unstable_Popover`~~ -> [`Popover`](#/Popover) - Теперь экспортируется как стабильный. @@ -849,6 +841,8 @@ npx @vkontakte/vkui-codemods --help </Popover> ``` +<br/> + ### 🎉 ~~`unstable_Popper`~~ -> [`Popper`](#/Popper) - Теперь экспортируется как стабильный. @@ -885,6 +879,8 @@ npx @vkontakte/vkui-codemods --help </Popper> ``` +<br/> + ### 🎉 ~~`unstable_TextTooltip`~~ -> [`Tooltip`](#/Tooltip) - Теперь экспортируется как стабильный. @@ -932,10 +928,14 @@ npx @vkontakte/vkui-codemods --help + </Tooltip> ``` +<br/> + ### 🎉 ~~`unstable_HorizontalCellShowMore`~~ -> [`HorizontalCellShowMore`](#/HorizontalCellShowMore) - Теперь экспортируется как стабильный. +<br/> + ### ~~`RichTooltip`~~ -> 🗑️ - Компонент удален, используйте [`Tooltip`](#/Tooltip). @@ -951,3 +951,54 @@ npx @vkontakte/vkui-codemods --help - </RichTooltip> + </Tooltip> ``` + +<br/><br/><hr/><br/> + +## Интеграция с [VK Mini Apps](https://vk.com/miniapps) + +> Этот **Breaking Change** предназначен для разработчиков мини-приложений ВКонтакте. Если вы таким +> не являетесь, то смело пропускайте эту секцию. + +Изначально, **VKUI** создавался как инструмент для создания клиентской части мини-приложений [ВКонтакте](https://vk.com). +Сейчас **VKUI** уже больше чем просто мини-приложения. Разработчики используют библиотеку, чтобы +создавать полноценные независимые приложения, которые никак не связаны с [VK Mini Apps](https://vk.com/miniapps). + +В связи с этим мы отказались от завязки на мини-приложения [ВКонтакте](https://vk.com). Для этого мы +удалили интеграцию с библиотекой [VK Bridge](https://www.npmjs.com/package/@vkontakte/vk-bridge), а +также убрали упоминания о [VK Mini Apps](https://vk.com/miniapps) в документации. Это привнесло в +библиотеку ряд изменений касающихся API. + +### Конфигурация VKUI + +Из [VK Bridge](https://www.npmjs.com/package/@vkontakte/vk-bridge) мы доставали несколько настроек: + +1. тему (`light` или `dark`); +2. параметры адаптивности; +3. размеры безопасных зон (в CSS это `--safe-area-insets-*`); +4. открыто веб-вью или нет. + +Первые три пункта перенесли в библиотеку [@vkontakte/vk-bridge-react](https://www.npmjs.com/package/@vkontakte/vk-bridge-react). + +Помимо **VK Bridge**, была завязка на мини-приложения в свойстве `webviewType` за счёт свойства +`"vkapps"`. Теперь это свойство `hasCustomPanelHeaderAfter`, который по умолчанию `false`. + +Бойлерплейт для **VK Mini Apps** представлен на странице [Интеграция с VK Mini Apps](https://vkcom.github.io/VKUI/#/integrations-vk-mini-apps) +под заголовком **Конфигурация VKUI**. + +### ~~`withInsets`~~ + +- Используйте вместо него хук `useInsets()` из [@vkontakte/vk-bridge-react](https://www.npmjs.com/package/@vkontakte/vk-bridge-react). + +### ~~`HasInsets`~~ + +- Используйте вместо него `SafeAreaInsets`. +- Если вы используете [@vkontakte/vk-bridge](https://www.npmjs.com/package/@vkontakte/vk-bridge), то + вы можете объявить тип у себя следующим образом: + +```ts static +import type { Insets } form '@vkontakte/vk-brige'; + +interface HasInsets { + insets?: Partial<Insets>; +} +``` diff --git a/styleguide/utils/index.js b/styleguide/utils/index.js index 67b5df8c52..766ea318cc 100644 --- a/styleguide/utils/index.js +++ b/styleguide/utils/index.js @@ -1,3 +1,6 @@ +import { kebabCase } from './third-party/lodash'; +import { getTextFromChildren } from './third-party/react-children-utils'; + export const perfLogger = { _isEnabled: localStorage.getItem('vkui:perf-logging') === 'true', set isEnabled(value) { @@ -29,3 +32,11 @@ export const getDeprecatedFromComponentTags = (component) => { }; export * from './useViewPortSize'; + +export const generateIdByReactNode = (children) => { + const text = getTextFromChildren(children); + if (typeof text === 'string') { + return kebabCase(text); + } + return; +}; diff --git a/styleguide/utils/third-party/lodash/index.js b/styleguide/utils/third-party/lodash/index.js new file mode 100644 index 0000000000..a9a5a4716d --- /dev/null +++ b/styleguide/utils/third-party/lodash/index.js @@ -0,0 +1,33 @@ +/* eslint-disable */ + +/** + * Original https://github.com/lodash/lodash/blob/main/src/kebabCase.ts + */ + +import { words } from './words'; + +/** + * Converts `string` to + * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). + * + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the kebab cased string. + * @see camelCase, lowerCase, snakeCase, startCase, upperCase, upperFirst + * @example + * + * kebabCase('Foo Bar') + * // => 'foo-bar' + * + * kebabCase('fooBar') + * // => 'foo-bar' + * + * kebabCase('__FOO_BAR__') + * // => 'foo-bar' + */ +export const kebabCase = (string) => + words(string.toString().replace(/['\u2019]/g, '')).reduce( + (result, word, index) => result + (index ? '-' : '') + word.toLowerCase(), + '', + ); diff --git a/styleguide/utils/third-party/lodash/unicodeWords.js b/styleguide/utils/third-party/lodash/unicodeWords.js new file mode 100644 index 0000000000..b249ab5170 --- /dev/null +++ b/styleguide/utils/third-party/lodash/unicodeWords.js @@ -0,0 +1,87 @@ +/* eslint-disable */ + +/** + * Original https://github.com/lodash/lodash/blob/main/src/.internal/unicodeWords.ts + */ + +/** Used to compose unicode character classes. */ +const rsAstralRange = '\\ud800-\\udfff'; +const rsComboMarksRange = '\\u0300-\\u036f'; +const reComboHalfMarksRange = '\\ufe20-\\ufe2f'; +const rsComboSymbolsRange = '\\u20d0-\\u20ff'; +const rsComboMarksExtendedRange = '\\u1ab0-\\u1aff'; +const rsComboMarksSupplementRange = '\\u1dc0-\\u1dff'; +const rsComboRange = + rsComboMarksRange + + reComboHalfMarksRange + + rsComboSymbolsRange + + rsComboMarksExtendedRange + + rsComboMarksSupplementRange; +const rsDingbatRange = '\\u2700-\\u27bf'; +const rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff'; +const rsMathOpRange = '\\xac\\xb1\\xd7\\xf7'; +const rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf'; +const rsPunctuationRange = '\\u2000-\\u206f'; +const rsSpaceRange = + ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000'; +const rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde'; +const rsVarRange = '\\ufe0e\\ufe0f'; +const rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; + +/** Used to compose unicode capture groups. */ +const rsApos = "['\u2019]"; +const rsBreak = `[${rsBreakRange}]`; +const rsCombo = `[${rsComboRange}]`; +const rsDigit = '\\d'; +const rsDingbat = `[${rsDingbatRange}]`; +const rsLower = `[${rsLowerRange}]`; +const rsMisc = `[^${rsAstralRange}${ + rsBreakRange + rsDigit + rsDingbatRange + rsLowerRange + rsUpperRange +}]`; +const rsFitz = '\\ud83c[\\udffb-\\udfff]'; +const rsModifier = `(?:${rsCombo}|${rsFitz})`; +const rsNonAstral = `[^${rsAstralRange}]`; +const rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}'; +const rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]'; +const rsUpper = `[${rsUpperRange}]`; +const rsZWJ = '\\u200d'; + +/** Used to compose unicode regexes. */ +const rsMiscLower = `(?:${rsLower}|${rsMisc})`; +const rsMiscUpper = `(?:${rsUpper}|${rsMisc})`; +const rsOptContrLower = `(?:${rsApos}(?:d|ll|m|re|s|t|ve))?`; +const rsOptContrUpper = `(?:${rsApos}(?:D|LL|M|RE|S|T|VE))?`; +const reOptMod = `${rsModifier}?`; +const rsOptVar = `[${rsVarRange}]?`; +const rsOptJoin = `(?:${rsZWJ}(?:${[rsNonAstral, rsRegional, rsSurrPair].join('|')})${ + rsOptVar + reOptMod +})*`; +const rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])'; +const rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])'; +const rsSeq = rsOptVar + reOptMod + rsOptJoin; +const rsEmoji = `(?:${[rsDingbat, rsRegional, rsSurrPair].join('|')})${rsSeq}`; + +const reUnicodeWords = RegExp( + [ + `${rsUpper}?${rsLower}+${rsOptContrLower}(?=${[rsBreak, rsUpper, '$'].join('|')})`, + `${rsMiscUpper}+${rsOptContrUpper}(?=${[rsBreak, rsUpper + rsMiscLower, '$'].join('|')})`, + `${rsUpper}?${rsMiscLower}+${rsOptContrLower}`, + `${rsUpper}+${rsOptContrUpper}`, + rsOrdUpper, + rsOrdLower, + `${rsDigit}+`, + rsEmoji, + ].join('|'), + 'g', +); + +/** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ +export function unicodeWords(string) { + return string.match(reUnicodeWords); +} diff --git a/styleguide/utils/third-party/lodash/words.js b/styleguide/utils/third-party/lodash/words.js new file mode 100644 index 0000000000..ffcd514fae --- /dev/null +++ b/styleguide/utils/third-party/lodash/words.js @@ -0,0 +1,42 @@ +/* eslint-disable */ + +/** + * Original https://github.com/lodash/lodash/blob/main/src/words.ts + */ +import { unicodeWords } from './unicodeWords'; + +const hasUnicodeWord = RegExp.prototype.test.bind( + /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/, +); + +/** Used to match words composed of alphanumeric characters. */ +// eslint-disable-next-line no-control-regex +const reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + +function asciiWords(string) { + return string.match(reAsciiWord); +} + +/** + * Splits `string` into an array of its words. + * + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {RegExp|string} [pattern] The pattern to match words. + * @returns {Array} Returns the words of `string`. + * @example + * + * words('fred, barney, & pebbles') + * // => ['fred', 'barney', 'pebbles'] + * + * words('fred, barney, & pebbles', /[^, ]+/g) + * // => ['fred', 'barney', '&', 'pebbles'] + */ +export function words(string, pattern) { + if (pattern === undefined) { + const result = hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string); + return result || []; + } + return string.match(pattern) || []; +} diff --git a/styleguide/utils/third-party/react-children-utils/index.js b/styleguide/utils/third-party/react-children-utils/index.js new file mode 100644 index 0000000000..e20faf6580 --- /dev/null +++ b/styleguide/utils/third-party/react-children-utils/index.js @@ -0,0 +1,40 @@ +/* eslint-disable */ + +// copied from react-children-utilities +// @see https://github.com/fernandopasik/react-children-utilities/tree/main +import { Children, isValidElement } from 'react'; + +export const childToString = (child) => { + if (typeof child === 'undefined' || child === null || typeof child === 'boolean') { + return ''; + } + + if (JSON.stringify(child) === '{}') { + return ''; + } + + return child.toString(); +}; + +export const getTextFromChildren = (children) => { + if (!(children instanceof Array) && !isValidElement(children)) { + return childToString(children); + } + + return Children.toArray(children).reduce((text, child) => { + let newText = ''; + + const isValidElementResult = isValidElement(child); + const hasChildren = isValidElementResult && 'children' in child.props; + + if (isValidElementResult && hasChildren) { + newText = getTextFromChildren(child.props.children); + } else if (isValidElementResult && !hasChildren) { + newText = ''; + } else { + newText = childToString(child); + } + + return text.concat(newText); + }, ''); +};