@boobooking/dashboard-ui-components 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -65,10 +65,10 @@ Vue не ниже 3.5, ESM, сборщик, умеющий импорт CSS из
65
65
  Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в CSS приложения
66
66
  пакету не нужны.
67
67
 
68
- Меню `DropdownButtonWithAction` и `HamburgerMenu`, список `SelectSingle`,
68
+ Меню `DropdownButtonWithAction` и `HamburgerMenu`, списки `SelectSingle` и `SelectMultiple`,
69
69
  календари `SelectDateInterval` и подсказка `TextPopover` стоят на Popover API
70
70
  браузера: Safari 17+, Chrome 114+, Firefox 125+. В браузерах старше меню,
71
- список, календари и подсказка видны в потоке всегда.
71
+ списки, календари и подсказка видны в потоке всегда.
72
72
 
73
73
  ## Цвета
74
74
 
@@ -90,8 +90,8 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
90
90
 
91
91
  ## Компоненты
92
92
 
93
- Пакет экспортирует восемнадцать компонентов: `Dot`, `RussianMobileFilter`,
94
- `Search`, `SelectDateInterval`, `SelectSingle`, `InfoPill`,
93
+ Пакет экспортирует девятнадцать компонентов: `Dot`, `RussianMobileFilter`,
94
+ `Search`, `SelectDateInterval`, `SelectSingle`, `SelectMultiple`, `InfoPill`,
95
95
  `ErrorMessages`, `FormInput`, `ActionPill`, `ConfirmationModal`,
96
96
  `DropdownButtonWithAction`, `HamburgerMenu`, `DataTable`,
97
97
  `NavigationMenuElement`, `PageTabs`, `PageCard`, `NotificationMessage`,
@@ -99,13 +99,15 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
99
99
  (`files: ["dist"]`) исходники не попадают, поэтому контракт каждого
100
100
  компонента — здесь и в playground, а не в исходном коде.
101
101
 
102
- Крестики — закрытие `PageCard` и ластики очистки фильтров — при нажатии
103
- коротко «вдавливаются», и действие выполняется после этого, через 150 мс:
104
- иначе нажатия не было бы видно — ластик пропадает сразу после очистки,
105
- крестик уводит со страницы. Так при любом нажатии: мышью, касанием,
106
- Enter, пробелом, расширением клавиатурной навигации. Нажатия во время
107
- анимации не считаются: одно нажатие — одно действие. При «уменьшении
108
- движения» в системе — без анимации и сразу.
102
+ Ластики очистки фильтров идут в порядке Tab сразу после своего поля или
103
+ кнопки, в фокусе с клавиатуры вокруг крестика кольцо; нажимаются Enter и
104
+ пробелом. Крестики — закрытие `PageCard` и ластики очистки фильтров —
105
+ при нажатии коротко «вдавливаются», и действие выполняется после этого,
106
+ через 150 мс: иначе нажатия не было бы видно — ластик пропадает сразу
107
+ после очистки, крестик уводит со страницы. Так при любом нажатии: мышью,
108
+ касанием, Enter, пробелом, расширением клавиатурной навигации. Нажатия
109
+ во время анимации не считаются: одно нажатие — одно действие. При
110
+ «уменьшении движения» в системе — без анимации и сразу.
109
111
 
110
112
  ### Dot
111
113
 
@@ -263,13 +265,14 @@ Enter, пробелом, расширением клавиатурной нав
263
265
  под курсором, поэтому календарь «до» открывается тем же кликом, что
264
266
  закрывает «от».
265
267
 
266
- С клавиатуры: Enter или пробел на поле открывают календарь. Пока он открыт,
267
- стрелки переводят фокус по дням: влево и вправо — на день, вверх и вниз — на
268
- неделю; с края месяца календарь листается, дата при этом не выбирается.
269
- Первая стрелка ставит фокус на выбранный день, без выбранного — на сегодня.
270
- Enter или пробел выбирают день под фокусом и стрелки месяцев — так же, как
271
- клик; Escape закрывает календарь. После закрытия фокус возвращается на поле.
272
- В поле можно перейти Tab и набрать дату.
268
+ С клавиатуры: в поле даты стрелка вниз, Enter и пробел открывают календарь.
269
+ Кнопки календаря и списков в фокусе с клавиатуры обведены кольцом пакета. Пока
270
+ календарь открыт, стрелки переводят фокус по дням: влево и вправо — на день,
271
+ вверх и вниз — на неделю; с края месяца календарь листается, дата при этом не
272
+ выбирается. Первая стрелка ставит фокус на выбранный день, без выбранного — на
273
+ сегодня. Enter или пробел выбирают день под фокусом и стрелки месяцев — так
274
+ же, как клик; Escape закрывает календарь. После закрытия фокус возвращается на
275
+ поле. В поле можно перейти Tab и набрать дату.
273
276
 
274
277
  ### SelectSingle
275
278
 
@@ -298,7 +301,8 @@ Enter или пробел выбирают день под фокусом и с
298
301
  пунктам и страницу не прокручивают. Отсчёт идёт от выбранного пункта: вниз —
299
302
  следующий за ним, вверх — предыдущий; без выбранного вниз — первый пункт,
300
303
  вверх — последний; с краёв — по кругу. Enter или пробел выбирают пункт под
301
- фокусом так же, как клик, Escape закрывает список. После закрытия фокус
304
+ фокусом так же, как клик, Escape закрывает список. Tab и Shift+Tab ходят по
305
+ пунктам по кругу и наружу не выводят, пока список открыт. После закрытия фокус
302
306
  возвращается на кнопку фильтра. У закрытого списка стрелки прокручивают
303
307
  страницу.
304
308
 
@@ -317,6 +321,85 @@ Enter или пробел выбирают день под фокусом и с
317
321
  внутри списка — нет. Открытие другого списка, календаря или меню
318
322
  закрывает предыдущее.
319
323
 
324
+ ### SelectMultiple
325
+
326
+ <select-multiple
327
+ header="Бренд"
328
+ :items="[{ id: 'rc', name: 'Royal Canin' }, { id: 'eukanuba', name: 'Eukanuba' }]"
329
+ v-model="brands"
330
+ @changed="reload"
331
+ />
332
+
333
+ <select-multiple header="Мероприятие" :items="events" v-model="eventIds" with-search @changed="reload"/>
334
+
335
+ Тот же фильтр, что `SelectSingle`, но выбрать можно несколько пунктов.
336
+ `items` — массив объектов `{ id, name }`. `v-model` держит массив `id`
337
+ выбранных пунктов, пустой массив — ничего не выбрано. `id` — строка или число,
338
+ сравнение строгое.
339
+
340
+ | Проп | Тип | По умолчанию | Описание |
341
+ | --- | --- | --- | --- |
342
+ | `items` | `Array` | обязателен | Массив `{ id, name }` |
343
+ | `modelValue` | `Array` | `[]` | `id` выбранных пунктов |
344
+ | `header` | `String` | обязателен | Подпись поля |
345
+ | `isRequired` | `Boolean` | `false` | Пометка обязательности в заголовке |
346
+ | `isLoading` | `Boolean` | `false` | Индикатор загрузки в заголовке |
347
+ | `withSearch` | `Boolean` | `false` | Поле поиска вверху списка |
348
+ | `lang` | `String` | язык плагина | `"ru"` или `"en"` — надпись, поле поиска, «Ничего не найдено», подписи обоих ластиков |
349
+
350
+ События: `update:modelValue` — новый массив `id`; `changed` — после каждого
351
+ изменения выбора кликом по пункту или ластиком.
352
+
353
+ Клик по невыбранному пункту добавляет его `id` в конец массива, по выбранному —
354
+ убирает. Массив из пропа компонент не меняет: он отдаёт новый, порядок `id` не
355
+ сортирует. `id`, которых нет среди пунктов, при переключении других пунктов
356
+ остаются в массиве, в надписи не считаются и ластик сами не показывают;
357
+ ластик отдаёт `[]` — уходят и они. `null` и `undefined` в `items` — пустой
358
+ список, в `modelValue` — ничего не выбрано.
359
+
360
+ На кнопке: пока выбранных среди `items` нет — пусто; один — его название;
361
+ несколько — «Выбрано: 3». Считаются все пункты, а не только найденные поиском.
362
+ Ластик виден, когда выбран хотя бы один пункт и список закрыт.
363
+
364
+ Выбор пункта — клик, Enter или пробел — закрывает список, фокус возвращается
365
+ на кнопку фильтра, а запрос поиска сбрасывается. `changed` уходит после
366
+ каждого выбора, и страница сразу перезапрашивает выдачу.
367
+
368
+ Список открывается так же, как у `SelectSingle`: в верхнем слое браузера, место,
369
+ высота, прокрутка и способы закрытия те же, фокус после закрытия возвращается
370
+ на кнопку. Отличия: галочка стоит у каждого выбранного пункта; пункт
371
+ сообщает скринридеру, выбран ли он (`aria-pressed`).
372
+ Как и у `SelectSingle`, без пунктов кнопки нет, заголовок остаётся. Пункты
373
+ пропали при открытом списке — список закрывается, запрос поиска сбрасывается,
374
+ а вернувшиеся пункты появляются с закрытым списком.
375
+
376
+ С клавиатуры, пока список открыт, всё как у `SelectSingle`: стрелки вверх и вниз
377
+ ведут фокус по пунктам по кругу, Enter или пробел переключают пункт и закрывают
378
+ список, Escape закрывает его без выбора. Если выбрано несколько пунктов,
379
+ отсчёт идёт от первого выбранного среди видимых. Мышь ведёт тот же фокус, что
380
+ и стрелки: движение по пункту ставит фокус на него, подсвечен всегда один пункт.
381
+
382
+ С `with-search` над пунктами стоит поле поиска: при прокрутке длинного списка
383
+ оно остаётся на месте. Имя пункта должно содержать запрос, регистр не важен,
384
+ пробелы по краям запроса отбрасываются. Если совпадений нет, вместо пунктов
385
+ строка «Ничего не найдено». Выбранные пункты, скрытые поиском, остаются
386
+ выбранными. Запрос не входит в `v-model`; он сбрасывается при каждом закрытии
387
+ списка, в том числе при выборе пункта. Ластик в поле очищает запрос. При
388
+ открытии списка фокус встаёт в поле; при загрузке страницы фокус в поле
389
+ не уходит. Без Popover API список виден всегда, и фокус в поле сам
390
+ не ставится. Пробел в поле печатает пробел, Enter ничего не делает и форму
391
+ не отправляет. Поле — первая остановка стрелок: из него вниз — первый пункт,
392
+ вверх — последний, с краёв пунктов — обратно в поле. Без совпадений стрелки
393
+ в поле ничего не делают. Пока список открыт, Tab и Shift+Tab ходят по кругу
394
+ внутри него: поле, ластик поля, пока запрос не пуст, пункты; наружу, на
395
+ страницу, фокус уходит после закрытия списка. Ластик поля входит в Tab, но не
396
+ в стрелки. Ластик на кнопке фильтра идёт в Tab сразу после неё.
397
+ Печатный символ и Backspace на пункте уходят в поле, поэтому набор не
398
+ пропадает, когда мышь увела фокус на пункт. Пока список открыт, панель не
399
+ становится уже, чем при открытии, а поле не двигается, сколько бы пунктов ни
400
+ убрал поиск: открытая вниз панель становится ниже вместе с найденным, открытая
401
+ вверх не становится ниже, и пустое место остаётся под пунктами, у кнопки.
402
+
320
403
  ### InfoPill
321
404
 
322
405
  Пилюля, которая только показывает текст: статус, счётчик, флаг, пометку.
@@ -925,7 +1008,10 @@ rounded-lg`, `box-sizing: border-box`. Отступов у неё нет: фор
925
1008
  | `HamburgerMenu` — подпись кнопки для скринридера | Открыть меню | Open menu |
926
1009
  | `SelectDateInterval` — месяцы, дни недели, кнопки календарей | по-русски | in English |
927
1010
  | `SelectDateInterval` — подсказки полей | от / до | from / to |
928
- | Ластик `Search`, `RussianMobileFilter`, `SelectSingle` (язык плагина) и `SelectDateInterval` — подпись для скринридера | Очистить | Clear |
1011
+ | Ластик `Search`, `RussianMobileFilter`, `SelectSingle` (язык плагина), `SelectMultiple` (проп `lang`) и `SelectDateInterval` — подпись для скринридера | Очистить | Clear |
1012
+ | `SelectMultiple` — надпись при нескольких выбранных | Выбрано: N | Selected: N |
1013
+ | `SelectMultiple` — подсказка и имя поля поиска | Поиск | Search |
1014
+ | `SelectMultiple` — нет совпадений | Ничего не найдено | Nothing found |
929
1015
  | `DataTable` — пагинация | Предыдущая / Следующая / Показаны результаты X - Y из Z | Previous / Next / Showing X - Y of Z results |
930
1016
  | `PageTabs` — имя навигации для скринридера | Закладки | Tabs |
931
1017
  | `PageCard` — доступное имя крестика | Назад | Back |
@@ -940,7 +1026,20 @@ rounded-lg`, `box-sizing: border-box`. Отступов у неё нет: фор
940
1026
 
941
1027
  Кнопки и ссылки компонентов нажимаются расширениями клавиатурной навигации —
942
1028
  Vimium, Vimari, Vimlike — по их подсказкам, как мышью; подсказка у каждой
943
- кнопки одна и стоит на всей кнопке.
1029
+ кнопки одна и стоит на всей кнопке. Ластики фильтров входят в порядок Tab
1030
+ и нажимаются Enter и пробелом; кольцо фокуса — вокруг крестика.
1031
+ После ластика, нажатого с клавиатуры, фокус переходит на поле или кнопку
1032
+ этого фильтра: ластик пропадает, и без этого фокус упал бы на страницу.
1033
+ При касании и клике мышью фокус остаётся как раньше.
1034
+
1035
+ Фокус у всех компонентов пакета выглядит одинаково, как у `FormInput`: линия
1036
+ 1px `blue-300` по краю элемента и ореол 3px `blue-200` с прозрачностью 50%.
1037
+ Вид задан одной утилитой `focus-ring` в `src/styles/index.css`, компоненты
1038
+ выбирают только момент. Поля, крестик `NotificationMessage`, кнопки
1039
+ `ConfirmationModal` и `DropdownButtonWithAction` показывают фокус при любом
1040
+ его появлении, в том числе после клика мышью; остальные кнопки и ссылки —
1041
+ только с клавиатуры. Стрелки месяцев и подпись месяца в календаре `PickDay`
1042
+ берут тот же вид, когда фокус в них с клавиатуры.
944
1043
 
945
1044
  Vimlike (Safari на iPhone, iPad и Mac) считает кнопкой любой элемент
946
1045
  с `cursor: pointer` и из вложенных таких элементов оставляет самый глубокий.
@@ -954,7 +1053,7 @@ Vimlike (Safari на iPhone, iPad и Mac) считает кнопкой любо
954
1053
  считал бы кнопкой вместо неё. В поле по-прежнему можно перейти Tab и набрать
955
1054
  дату.
956
1055
 
957
- Подсказки Vimlike в открытых меню, списке `SelectSingle` и календарях
1056
+ Подсказки Vimlike в открытых меню, списках `SelectSingle` и `SelectMultiple` и календарях
958
1057
  `SelectDateInterval` не видны: Vimlike рисует их под верхним слоем браузера,
959
1058
  в котором открываются эти панели. Vimium выводит свои подсказки в верхний
960
1059
  слой, и у него такой проблемы нет. В Vimlike панель открывают подсказкой её
@@ -1065,7 +1164,7 @@ Inertia SSR), а серверная разметка гидратируется
1065
1164
 
1066
1165
  npm run playground
1067
1166
 
1068
- Поднимает демо-страницы со всеми восемнадцатью компонентами в двух окружениях:
1167
+ Поднимает демо-страницы со всеми девятнадцатью компонентами в двух окружениях:
1069
1168
  голом (без Tailwind и стилей приложения) и в окружении приложения (с
1070
1169
  Tailwind, `@tailwindcss/forms` и типографикой, как у потребителя). Это
1071
1170
  основной способ посмотреть, как компоненты выглядят и ведут себя, а не