npm explorer

@salutejs/spatial

v3.0.14TypeScript

Spatial navigation

spatial navigationspatnavspat nav
0/weekUpdated 2 years agoUnpacked: 108.7 KB
Published by Salute Frontend Team
npm install @salutejs/spatial
RepositoryHomepagenpm

Spatial navigation для Canvas Apps

Пространственная навигация (Spatial navigation) — это возможность перемещаться между фокусируемыми элементами в зависимости от их положения в документе. Пространственная навигация часто называется «направленной навигацией», которая обеспечивает четырехнаправленную навигацию: сверху, слева, снизу, справа. Пользователи обычно знакомы с двусторонней навигацией с использованием «клавиш табуляции» для направления вперед, так и «клавиши Shift+Tab» для обратного направления.

Есть спецификация для браузеров, которая пока в статусе "draft".

Мы рекомендуем использовать эту библиотеку для Canvas Apps на наших девайсах: TV, SberBox и др,
а библиотеку считать устаревшей.

Для мобильных устройств или других устройств с сенсорным экраном это не надо.

Документации с аннотацией типов также доступна на сайте - https://plasma.sberdevices.ru/spatial/

Оглавление

- Установка
- " class="text-primary hover:underline" target="_blank" rel="noopener noreferrer">Минимальная настройка приложения для работы с @salutejs/spatial
- Инициализация в родительском компоненте всего приложения
- Добавление секции
- Включение навигации на DOM элементе
- Углубление в @salutejs/spatial
- Варианты инициализации
- Подробнее о секциях
- Настройка параметров секции
- Хуки
- Полезные методы SpatialNavigation
- Оптимизация и ускорение работы
- Intersection и Mutation observer
- Простые секции
- Запуск тестов
- Pitfalls
- Next.js >= 13.0.0
- Next.js < 13.0.0

Установка

``sh
npm install --save @salutejs/spatial
`

Минимальная настройка приложения для работы с @salutejs/spatial

Нужно выполнить три обязательных шага.

$3

`jsx
import { useSpatnavInitialization } from '@salutejs/spatial';

import { Page } from './pages/Page';

const App = () => {
useSpatnavInitialization();

return ;
};
`

$3

Для навигации @salutejs/spatial использует секции. Секцию можно добавить с помощью хука useSection.

`jsx
import { useSection } from '@salutejs/spatial';

const Page = ({ children }) => {
const [sectionProps] = useSection('sectionName');

return

;
};

export default Page;
`

$3

Для того, чтобы браузер имел возможность фокусироваться на DOM элемент, этот элемент должен иметь атрибут tabindex="-1".

Далее для работы внутренних функций @salutejs/spatial необходимо добавить DOM элементу CSS класс "sn-section-item".

`jsx
<>


навигация работает


навигация работает


`

Если убрать класс sn-section-item, то элемент исключается из навигации.

`jsx
<>


навигация работает


навигация НЕ работает


`

Добавим элементы в секцию.

`jsx
import { useEffect, useRef } from 'react';
import { useSection } from '@salutejs/spatial';

const Page = ({ children }) => {
// создание секции
const [sectionProps] = useSection('sectionName');

// установка фокуса на элемент
const ref = useRef(null);

useEffect(() => {
const focusable = ref.current;

if (focusable) {
focusable.focus();
}
}, []);

return (



навигация работает (после выполнения useEffect, фокус будет установлен на этот элемент)


навигация работает

навигация НЕ работает


);
};

export default Page;
`

Готово! Навигация настроена. Но надо подчеркнуть, что после инициализации и добавления секций фокус автоматически не устанавливается ни на один элемент. Это надо делать вручную или с помощью хука useDefaultSectionFocus.

Здесь были рассмотрены только необходимые действия. Для более гибкой настройки секций и навигации читайте далее.

Углубление в @salutejs/spatial

$3

Можно инициализировать @salutejs/spatial без использования хука useSpatnavInitialization, если такое требуется.

`js
import { spatnavInstance } from '@salutejs/spatial';

// вызывать только на клиенте
spatnavInstance.init();
`

Аналогично можно и отменить инициализацию. Например, при переходе на страницу, где пространственная навигация не нужна.

`js
spatnavInstance.unInit();
`

$3

Секция — это элементы навигации, объединённые в группу. У секции есть корневой элемент.
Включение секции в навигацию происходит с помощью хука
useSection. У корневого элемента секции должны быть установлены аттрибуты id="имя секции, переданное в useSection" и className="sn-section-root", которые возвращает хук useSection.
Элементы секции должны быть потомками корневого элемента и иметь аттрибут
className="sn-section-item".

`jsx
import { useSection } from '@salutejs/spatial';

const Page = ({ children }) => {
const [section1] = useSection('section1');
const [section2] = useSection('section2');

return (
<>



принадлежит секции section1


принадлежит секции section1




принадлежит секции section1






принадлежит секции section2


принадлежит секции section2



);
};
`

#### Настройка параметров секции

Также хук useSection возвращает функцию кастомизации. С её помощью можно гибко настроить правила навигации внутри и между секциями. А также включить или выключить секцию целиком.

`jsx
import { useSection } from '@salutejs/spatial';

const Page = ({ children }) => {
const [section1, customize1] = useSection('section1');
const [section2, customize2] = useSection('section2');

useEffect(() => {
// выключаем навигацию в секции section1 целиком
customize1({
disabled: true,
});

customize2({
simpleSectionOptions: { type: 'row' },
// установка элемента по умолчанию для секции
getDefaultElement: (section2Root) => section2Root.firstElementChild,
enterTo: 'default-element',
});
}, [[customize1, customize2]]);

// установка секции по умолчанию и установка фокуса на элемент из этой секции, выбранный по правилам определённым в её конфиге
// https://plasma.sberdevices.ru/spatial/functions/useDefaultSectionFocus.html
useDefaultSectionFocus('section2');

return (
<>



принадлежит секции section1, навигация выключена


принадлежит секции section1, навигация выключена




принадлежит секции section1, навигация выключена






принадлежит секции section2. После выполнения всех хуков, фокус будет установлен на этот элемент


принадлежит секции section2



);
};
`

О всех параметрах секции можно почитать в документации к типу Config. Параметры передаются в функцию customize.

Хуки

- useSpatnavInitialization - инициализация навигации;
-
useSection - создание секции;
-
useSelfSection - создание секции, состоящей только из одного элемента;
-
useDefaultSectionFocus.

Полезные методы SpatialNavigation

У инстанса SpatialNavigation есть ряд методов для упрощения некоторых сценариев:

- Включение и выключение навигации для данной секции или полностью
- Удаление или добавление секции в навигацию
- Изменение глобального конфига или конфига секции
- Фокусирование указанной секции

Например, фокусирование на определенной секции на монтирование компонента.

`jsx
import { useSection, spatnavInstance } from '@salutejs/spatial';

const Page = ({ children }) => {

const [sectionProps] = useSection('suggest');

useEffect(() => {
spatnavInstance.focus('suggest');
}, []);


...

};
`

Полный список методов и их сигнатуры смотрите в коде SpatialNavigation или на советующей странице документации

Оптимизация и ускорение работы

$3

Для ускорения расчётов в @salutejs/spatial используются Intersection и Mutation observer. Первый следит за тем какой элемент находится во вьюпорте браузера. @salutejs/spatial в первую очередь будет пытаться найти подходящий для навигации элемент именно среди видимых элементов.
Mutation observer нужен для того, чтобы при обновлении DOM дерева, новые элементы навигации были обработаны Intersection observer'ом.

$3

@salutejs/spatial делает довольно много расчётов, чтобы понять какой элемент больше подходит для навигации.
Но если в вашей вёрстке есть списки, в которых элементы всегда расположенны в ряд или столбик, то лучше включить режим простых секций. Этот режим переопределяет поведение навигации при выборе следующего или предыдущего элемента.
Вместо расчётов
@salutejs/spatial просто возьмёт нужный элемент из DOM с помощью nextSiblingElement или previousSiblingElement.
Для того, чтобы этот режим работал необходимо передать соответствующую опцию в конфиг секции. И, обратите внимание, что все элементы секции должны быть на одном уровне в DOM.

В обоих примерах ниже режим простых секций будет работать.

`jsx
import { useSection } from '@salutejs/spatial';

const Page = ({ children }) => {
const [section1, customize1] = useSection('section1');
const [section2, customize2] = useSection('section2');

useEffect(() => {
customize1({
simpleSectionOptions: { type: 'column' },
});

customize2({
simpleSectionOptions: { type: 'row' },
});
}, [customize1, customize2]);

return (
<>














);
};
`

Запуск тестов

Для запуска тесов нужно собрать пакет spatial, запустить test-app и cypress.

`sh
npm run build

npm run test-app:start

npm run cypress:open
`

В открывшемся окне Cypress выбрать E2E Testing, тестировать можно как в Chrome так и в Electron.

Pitfalls

@salutejs/spatial не компилируется в CommonJS, поэтому если вы используете Next.js выполните следующее:

$3

В next.config.js вам необходимо добавить свойство transpilePackages.

`js
const config = {
transpilePackages: ['@salutejs/spatial'],
};
``

Документация по transpilePackages.

$3

Воспользуйтесь пакетом next-transpile-modules.

@salutejs/spatial - npm explorer

Dist Tags

latest3.0.14
canary3.0.14--canary.17.6693235005.0