@boobooking/dashboard-ui-components 0.19.1 → 0.20.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
@@ -7,7 +7,7 @@
7
7
  npm install @boobooking/dashboard-ui-components
8
8
 
9
9
  ```js
10
- import { RussianMobileFilter, SelectDateInterval } from '@boobooking/dashboard-ui-components'
10
+ import { RussianMobileFilter, SelectDateIntervalFilter } from '@boobooking/dashboard-ui-components'
11
11
  import '@boobooking/dashboard-ui-components/style.css'
12
12
  ```
13
13
 
@@ -65,10 +65,12 @@ Vue не ниже 3.5, ESM, сборщик, умеющий импорт CSS из
65
65
  Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в CSS приложения
66
66
  пакету не нужны.
67
67
 
68
- Меню `DropdownButtonWithAction` и `HamburgerMenu`, списки `SelectSingle` и `SelectMultiple`,
69
- календари `SelectDateInterval` и подсказка `TextPopover` стоят на Popover API
70
- браузера: Safari 17+, Chrome 114+, Firefox 125+. В браузерах старше меню,
71
- списки, календари и подсказка видны в потоке всегда.
68
+ Меню `DropdownButtonWithAction` и `HamburgerMenu`, списки `SelectSingleFilter`,
69
+ `SelectSingleForm`, `SelectMultipleFilter` и `SelectMultipleForm`, календари
70
+ `SelectDateFilter`, `SelectDateForm`, `SelectDateIntervalFilter`,
71
+ `SelectDateIntervalForm` и подсказка `TextPopover`
72
+ стоят на Popover API браузера: Safari 17+, Chrome 114+, Firefox 125+. В браузерах
73
+ старше меню, списки, календари и подсказка видны в потоке всегда.
72
74
 
73
75
  ## Цвета
74
76
 
@@ -82,7 +84,7 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
82
84
  | --- | --- |
83
85
  | `InfoPill`, `ActionPill` | фон `-100`, текст `-800`; у `ActionPill` при наведении текст `-600` |
84
86
  | основная кнопка и стрелка `DropdownButtonWithAction` | фон `-100`, рамка `-300`, текст `-800`, при наведении фон `-200` |
85
- | пункт меню `DropdownButtonWithAction` и `HamburgerMenu` | текст `-800`, в фокусе фон `-100` |
87
+ | пункт меню `DropdownButtonWithAction` и `HamburgerMenu` | фон `-100`, текст `-800`, при наведении и в фокусе фон `-200` |
86
88
  | `Dot`, полоска строки `DataTable` | `-500` |
87
89
 
88
90
  Без цвета кнопка белая с серой рамкой, пункт меню серый, строка таблицы без
@@ -90,10 +92,12 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
90
92
 
91
93
  ## Компоненты
92
94
 
93
- Пакет экспортирует девятнадцать компонентов: `Dot`, `RussianMobileFilter`,
94
- `Search`, `SelectDateInterval`, `SelectSingle`, `SelectMultiple`, `InfoPill`,
95
- `ErrorMessages`, `FormInput`, `ActionPill`, `ConfirmationModal`,
96
- `DropdownButtonWithAction`, `HamburgerMenu`, `DataTable`,
95
+ Пакет экспортирует двадцать четыре компонента: `Dot`, `RussianMobileFilter`,
96
+ `Search`, `SelectDateFilter`, `SelectDateForm`, `SelectDateIntervalFilter`,
97
+ `SelectDateIntervalForm`,
98
+ `SelectSingleFilter`, `SelectSingleForm`, `SelectMultipleFilter`,
99
+ `SelectMultipleForm`, `InfoPill`, `ErrorMessages`, `FormInput`, `ActionPill`,
100
+ `ConfirmationModal`, `DropdownButtonWithAction`, `HamburgerMenu`, `DataTable`,
97
101
  `NavigationMenuElement`, `PageTabs`, `PageCard`, `NotificationMessage`,
98
102
  `TextPopover`, функцию `downloadFile` и плагин `dashboardUi`. В архив пакета
99
103
  (`files: ["dist"]`) исходники не попадают, поэтому контракт каждого
@@ -225,14 +229,77 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
225
229
  `isRequired` только показывает точку: атрибут `required` и `aria-*` полю
226
230
  он не ставит.
227
231
 
228
- ### SelectDateInterval
232
+ ### SelectDateFilter
233
+
234
+ Одно поле даты под заголовком. Дата выбирается в календаре Pikaday,
235
+ у поля — ластик очистки. Подсказки у поля нет. Pikaday загружается
236
+ в браузере при монтировании компонента, а не при загрузке пакета, поэтому
237
+ календарь появляется, когда загрузка закончится.
238
+
239
+ Высота 4.5rem и серая рамка встроены в фильтр, ширина поля 9rem: класс
240
+ `h-18 border border-gray-200` ему не нужен. `class` и остальные атрибуты
241
+ ложатся на корень фильтра.
242
+
243
+ <select-date-filter header="Дата" v-model="day" @changed="reload"/>
244
+
245
+ | Проп | Тип | По умолчанию | Описание |
246
+ | --- | --- | --- | --- |
247
+ | `modelValue` | `String` | `""` | Выбранная дата |
248
+ | `header` | `String` | обязателен | Подпись поля |
249
+ | `isRequired` | `Boolean` | `false` | Пометка обязательности в заголовке |
250
+ | `isLoading` | `Boolean` | `false` | Индикатор загрузки в заголовке |
251
+ | `lang` | `String` | язык плагина | `"ru"` или `"en"`; действует на календарь и на подпись ластика для скринридера (у самого поля текста нет) |
252
+
253
+ События: `update:modelValue` (дата или пустая строка после ластика)
254
+ и `changed` приходят на каждый выбор пользователя: в том числе на повторный
255
+ выбор уже показанной даты, на набранную в поле дату, которая разобралась,
256
+ и на очистку ластиком. Когда значение меняет родитель, ни одно из событий
257
+ не приходит. Поля диапазона `SelectDateIntervalFilter` и
258
+ `SelectDateIntervalForm` устроены иначе: их `changed` приходит, только когда
259
+ новое значение отличается от переданного пропса.
260
+
261
+ Календарь, ластик и клавиатура — как у каждого из двух полей
262
+ `SelectDateIntervalFilter` (см. «SelectDateIntervalFilter»).
263
+
264
+ ### SelectDateForm
265
+
266
+ Одно поле даты в форме, в виде `FormInput`: подпись над полем, рамка поля
267
+ на всю ширину формы, высотой 38px, как у `FormInput`. Рамка скругляет и поле,
268
+ и кольцо фокуса в нём. Подсказки у поля нет.
269
+
270
+ <select-date-form label="Дата" v-model="day" :is-required="markDayRequired"/>
271
+
272
+ | Проп | Тип | По умолчанию | Описание |
273
+ | --- | --- | --- | --- |
274
+ | `modelValue` | `String` | `""` | Выбранная дата |
275
+ | `label` | `String` | обязателен | Подпись над полем |
276
+ | `isRequired` | `Boolean` | `false` | Красная точка у подписи |
277
+ | `lang` | `String` | язык плагина | `"ru"` или `"en"`; действует на календарь и на подпись ластика для скринридера (у самого поля текста нет) |
278
+
279
+ События: `update:modelValue` и `changed` — когда значение выбрал пользователь,
280
+ как у `SelectDateFilter` (см. «SelectDateFilter»); смена значения родителем
281
+ их не вызывает. Календарь, ластик и клавиатура — тоже как у него.
282
+
283
+ Подпись связана с полем для скринридера: кнопка календаря называется
284
+ подписью и датой, поле ввода — подписью. Клик по подписи ничего не делает.
285
+
286
+ `isRequired` только показывает точку, как у `FormInput`. `class`, `style`,
287
+ все остальные атрибуты и слушатели ложатся на корень компонента (у `FormInput`
288
+ остальные атрибуты уходят на поле ввода).
289
+
290
+ ### SelectDateIntervalFilter
229
291
 
230
292
  Два поля даты под одним заголовком — интервал дат «от» и «до». Дата
231
293
  выбирается в календаре Pikaday, у каждого поля — ластик очистки. Pikaday
232
294
  загружается в браузере при монтировании компонента, а не при загрузке
233
295
  пакета, поэтому календари появляются, когда загрузка закончится.
234
296
 
235
- <select-date-interval
297
+ Высота 4.5rem и серая рамка встроены в фильтр: класс
298
+ `h-18 border border-gray-200` ему не нужен. Ширина фильтра 18rem, «от» и «до»
299
+ по половине, между ними вертикальная линия. `class` и остальные атрибуты
300
+ ложатся на корень фильтра.
301
+
302
+ <select-date-interval-filter
236
303
  header="Период"
237
304
  :date-from="dateFrom"
238
305
  :date-to="dateTo"
@@ -253,7 +320,8 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
253
320
  События: `update:dateFrom`, `update:dateTo` — на каждый выбор даты
254
321
  в соответствующем поле и на его очистку ластиком (пустой строкой);
255
322
  `changed` — когда новое значение отличается от переданного пропса
256
- (отдельно для каждой из двух дат).
323
+ (отдельно для каждой из двух дат). Повторный выбор уже показанной даты
324
+ событий не вызывает.
257
325
 
258
326
  Клик по любому месту поля открывает его календарь. Календарь открывается
259
327
  в верхнем слое браузера (Popover API): его не обрезает обёртка
@@ -274,9 +342,42 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
274
342
  же, как клик; Escape закрывает календарь. После закрытия фокус возвращается на
275
343
  поле. В поле можно перейти Tab и набрать дату.
276
344
 
277
- ### SelectSingle
345
+ ### SelectDateIntervalForm
346
+
347
+ Интервал дат в форме, в виде `FormInput`: подпись над полями, под ней «от»
348
+ и «до» одинаковой ширины на всю ширину формы. У каждого поля своя рамка, как
349
+ у `FormInput`, высотой 38px; рамка скругляет и поле, и кольцо фокуса в нём.
350
+
351
+ <select-date-interval-form
352
+ label="Период"
353
+ v-model:date-from="dateFrom"
354
+ v-model:date-to="dateTo"
355
+ :is-required="markPeriodRequired"
356
+ />
357
+
358
+ | Проп | Тип | По умолчанию | Описание |
359
+ | --- | --- | --- | --- |
360
+ | `dateFrom` | `String` | `""` | Начало интервала |
361
+ | `dateTo` | `String` | `""` | Конец интервала |
362
+ | `label` | `String` | обязателен | Подпись над полями |
363
+ | `isRequired` | `Boolean` | `false` | Красная точка у подписи |
364
+ | `lang` | `String` | язык плагина | `"ru"` или `"en"`; действует и на подсказки полей, и на оба календаря |
365
+
366
+ События те же, что у `SelectDateIntervalFilter`: `update:dateFrom`,
367
+ `update:dateTo` и `changed`. Календари, ластики, подсказки и клавиатура —
368
+ тоже как у него (см. «SelectDateIntervalFilter»).
369
+
370
+ Подпись связана с полями для скринридера: оба поля — группа, названная
371
+ подписью, а каждое поле, как в фильтре, называется своей подсказкой «от» или
372
+ «до» с датой. Клик по подписи ничего не делает.
278
373
 
279
- <select-single
374
+ `isRequired` только показывает точку, как у `FormInput`. `class`, `style`,
375
+ все остальные атрибуты и слушатели ложатся на корень компонента (у `FormInput`
376
+ остальные атрибуты уходят на поле ввода).
377
+
378
+ ### SelectSingleFilter
379
+
380
+ <select-single-filter
280
381
  header="Вендор"
281
382
  :items="[{ id: 'a', name: 'Первый' }]"
282
383
  v-model="vendor"
@@ -298,6 +399,11 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
298
399
  События: `update:modelValue` и `changed` — при выборе элемента (повторный
299
400
  клик по уже выбранному снимает выбор) и при очистке через ластик.
300
401
 
402
+ Высота 4.5rem и серая рамка встроены в фильтр: класс
403
+ `h-18 border border-gray-200` ему не нужен. `class` и остальные атрибуты
404
+ ложатся на корень фильтра. Без пунктов кнопки нет, а заголовок, высота и рамка
405
+ остаются.
406
+
301
407
  С клавиатуры: пока список открыт, стрелки вверх и вниз переводят фокус по
302
408
  пунктам и страницу не прокручивают. Отсчёт идёт от выбранного пункта: вниз —
303
409
  следующий за ним, вверх — предыдущий; без выбранного вниз — первый пункт,
@@ -307,9 +413,9 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
307
413
  возвращается на кнопку фильтра. У закрытого списка стрелки прокручивают
308
414
  страницу.
309
415
 
310
- Подсветка пункта — это фокус, и мышь ведёт тот же фокус: движение по пункту
311
- ставит фокус на него, стрелки продолжают от пункта под курсором. Подсвечен
312
- всегда один пункт — тот, на который последними указали клавиатура или мышь.
416
+ Наведение подсвечивает пункт, но фокус не двигает: фокус меняют клавиатура и
417
+ клик. Пункт под мышью и пункт в фокусе с клавиатуры могут быть подсвечены
418
+ одновременно; стрелки продолжают от пункта в фокусе.
313
419
 
314
420
  Список открывается в верхнем слое браузера (Popover API): его не обрезает
315
421
  обёртка с прокруткой. Он открывается под полем, левым краем по левому
@@ -322,18 +428,50 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
322
428
  внутри списка — нет. Открытие другого списка, календаря или меню
323
429
  закрывает предыдущее.
324
430
 
325
- ### SelectMultiple
431
+ ### SelectSingleForm
326
432
 
327
- <select-multiple
433
+ Выбор одного пункта в форме, в виде `FormInput`: подпись над полем, рамка
434
+ поля на всю ширину формы, высотой 38px, как у `FormInput`. В рамке — кнопка
435
+ со списком и ластиком, та же, что у `SelectSingleFilter`.
436
+
437
+ <select-single-form
438
+ label="Вендор"
439
+ :items="vendors"
440
+ v-model="vendor"
441
+ :is-required="markVendorRequired"
442
+ />
443
+
444
+ | Проп | Тип | По умолчанию | Описание |
445
+ | --- | --- | --- | --- |
446
+ | `items` | `Array` | обязателен | Массив `{ id, name }` |
447
+ | `modelValue` | `String \| Number` | `null` | `id` выбранного элемента или `null` |
448
+ | `label` | `String` | обязателен | Подпись над полем |
449
+ | `isRequired` | `Boolean` | `false` | Красная точка у подписи |
450
+
451
+ `items`, `v-model`, события, список и клавиатура — как у `SelectSingleFilter`
452
+ (см. «SelectSingleFilter»). Без пунктов кнопки нет, под подписью остаётся
453
+ пустая рамка.
454
+
455
+ Подпись связана с кнопкой для скринридера: кнопка называется подписью
456
+ и выбранным пунктом, у пустого поля — подписью. Клик по подписи ничего
457
+ не делает.
458
+
459
+ `isRequired` только показывает точку, как у `FormInput`. `class`, `style`,
460
+ все остальные атрибуты и слушатели ложатся на корень компонента (у `FormInput`
461
+ остальные атрибуты уходят на поле ввода).
462
+
463
+ ### SelectMultipleFilter
464
+
465
+ <select-multiple-filter
328
466
  header="Бренд"
329
467
  :items="[{ id: 'rc', name: 'Royal Canin' }, { id: 'eukanuba', name: 'Eukanuba' }]"
330
468
  v-model="brands"
331
469
  @changed="reload"
332
470
  />
333
471
 
334
- <select-multiple header="Мероприятие" :items="events" v-model="eventIds" with-search @changed="reload"/>
472
+ <select-multiple-filter header="Мероприятие" :items="events" v-model="eventIds" with-search @changed="reload"/>
335
473
 
336
- Тот же фильтр, что `SelectSingle`, но выбрать можно несколько пунктов.
474
+ Тот же фильтр, что `SelectSingleFilter`, но выбрать можно несколько пунктов.
337
475
  `items` — массив объектов `{ id, name }`. `v-model` держит массив `id`
338
476
  выбранных пунктов, пустой массив — ничего не выбрано. `id` — строка или число,
339
477
  сравнение строгое.
@@ -367,19 +505,20 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
367
505
  на кнопку фильтра, а запрос поиска сбрасывается. `changed` уходит после
368
506
  каждого выбора, и страница сразу перезапрашивает выдачу.
369
507
 
370
- Список открывается так же, как у `SelectSingle`: в верхнем слое браузера, место,
508
+ Список открывается так же, как у `SelectSingleFilter`: в верхнем слое браузера, место,
371
509
  высота, прокрутка и способы закрытия те же, фокус после закрытия возвращается
372
510
  на кнопку. Отличия: галочка стоит у каждого выбранного пункта; пункт
373
511
  сообщает скринридеру, выбран ли он (`aria-pressed`).
374
- Как и у `SelectSingle`, без пунктов кнопки нет, заголовок остаётся. Пункты
375
- пропали при открытом списке — список закрывается, запрос поиска сбрасывается,
376
- а вернувшиеся пункты появляются с закрытым списком.
512
+ Как и у `SelectSingleFilter`, без пунктов кнопки нет, а заголовок, высота
513
+ и рамка остаются. Пункты пропали при открытом списке — список закрывается,
514
+ запрос поиска сбрасывается, а вернувшиеся пункты появляются с закрытым списком.
377
515
 
378
- С клавиатуры, пока список открыт, всё как у `SelectSingle`: стрелки вверх и вниз
379
- ведут фокус по пунктам по кругу, Enter или пробел переключают пункт и закрывают
380
- список, Escape закрывает его без выбора. Если выбрано несколько пунктов,
381
- отсчёт идёт от первого выбранного среди видимых. Мышь ведёт тот же фокус, что
382
- и стрелки: движение по пункту ставит фокус на него, подсвечен всегда один пункт.
516
+ С клавиатуры, пока список открыт, всё как у `SelectSingleFilter`: стрелки вверх
517
+ и вниз ведут фокус по пунктам по кругу, Enter или пробел переключают пункт и
518
+ закрывают список, Escape закрывает его без выбора. Если выбрано несколько
519
+ пунктов, отсчёт идёт от первого выбранного среди видимых. Наведение подсвечивает
520
+ пункт, но фокус не двигает: фокус меняют клавиатура и клик, пункт под мышью и
521
+ пункт в фокусе могут быть подсвечены одновременно.
383
522
 
384
523
  С `with-search` над пунктами стоит поле поиска: при прокрутке длинного списка
385
524
  оно остаётся на месте. Имя пункта должно содержать запрос, регистр не важен,
@@ -387,21 +526,52 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
387
526
  строка «Ничего не найдено». Выбранные пункты, скрытые поиском, остаются
388
527
  выбранными. Запрос не входит в `v-model`; он сбрасывается при каждом закрытии
389
528
  списка, в том числе при выборе пункта. Ластик в поле очищает запрос. При
390
- открытии списка фокус встаёт в поле; при загрузке страницы фокус в поле
391
- не уходит. Без Popover API список виден всегда, и фокус в поле сам
392
- не ставится. Пробел в поле печатает пробел, Enter ничего не делает и форму
393
- не отправляет. Поле — первая остановка стрелок: из него вниз — первый пункт,
394
- вверх — последний, с краёв пунктов — обратно в поле. Без совпадений стрелки
395
- в поле ничего не делают. Пока список открыт, Tab и Shift+Tab ходят по кругу
396
- внутри него: поле, ластик поля, пока запрос не пуст, пункты; наружу, на
397
- страницу, фокус уходит после закрытия списка. Ластик поля входит в Tab, но не
398
- в стрелки. Ластик на кнопке фильтра идёт в Tab сразу после неё.
399
- Печатный символ и Backspace на пункте уходят в поле, поэтому набор не
400
- пропадает, когда мышь увела фокус на пункт. Пока список открыт, панель не
529
+ открытии списка фокус встаёт в поле; при загрузке страницы фокус в поле не
530
+ уходит. Без Popover API список виден всегда, и фокус в поле сам не ставится.
531
+ Пробел в поле печатает пробел, Enter ничего не делает и форму не отправляет.
532
+ Поле — первая остановка стрелок: из него вниз — первый пункт, вверх — последний,
533
+ с краёв пунктов — обратно в поле. Без совпадений стрелки в поле ничего не
534
+ делают. Пока список открыт, Tab и Shift+Tab ходят по кругу внутри него: поле,
535
+ ластик поля, пока запрос не пуст, пункты; наружу, на страницу, фокус уходит
536
+ после закрытия списка. Ластик поля входит в Tab, но не в стрелки. Ластик на
537
+ кнопке фильтра идёт в Tab сразу после неё. Печатный символ и Backspace на
538
+ пункте, куда фокус перевели стрелки или Tab, уходят в поле, поэтому набор не
539
+ пропадает; мышь фокус на пункт не уводит. Пока список открыт, панель не
401
540
  становится уже, чем при открытии, а поле не двигается, сколько бы пунктов ни
402
541
  убрал поиск: открытая вниз панель становится ниже вместе с найденным, открытая
403
542
  вверх не становится ниже, и пустое место остаётся под пунктами, у кнопки.
404
543
 
544
+ ### SelectMultipleForm
545
+
546
+ Выбор нескольких пунктов в форме, в виде `FormInput`: подпись над полем, рамка
547
+ поля на всю ширину формы, высотой 38px, как у `FormInput`. В рамке — кнопка
548
+ со списком, поиском и ластиком, та же, что у `SelectMultipleFilter`.
549
+
550
+ <select-multiple-form label="Бренд" :items="brands" v-model="brandIds"/>
551
+
552
+ <select-multiple-form label="Мероприятие" :items="events" v-model="eventIds" with-search :is-required="markEventsRequired"/>
553
+
554
+ | Проп | Тип | По умолчанию | Описание |
555
+ | --- | --- | --- | --- |
556
+ | `items` | `Array` | обязателен | Массив `{ id, name }` |
557
+ | `modelValue` | `Array` | `[]` | `id` выбранных пунктов |
558
+ | `label` | `String` | обязателен | Подпись над полем |
559
+ | `isRequired` | `Boolean` | `false` | Красная точка у подписи |
560
+ | `withSearch` | `Boolean` | `false` | Поле поиска вверху списка |
561
+ | `lang` | `String` | язык плагина | `"ru"` или `"en"` — надпись, поле поиска, «Ничего не найдено», подписи обоих ластиков |
562
+
563
+ `items`, `v-model`, события, надпись на кнопке, список, поиск и клавиатура —
564
+ как у `SelectMultipleFilter` (см. «SelectMultipleFilter»). Без пунктов кнопки
565
+ нет, под подписью остаётся пустая рамка.
566
+
567
+ Подпись связана с кнопкой для скринридера: кнопка называется подписью
568
+ и надписью на кнопке, у пустого поля — подписью. Клик по подписи ничего
569
+ не делает.
570
+
571
+ `isRequired` только показывает точку, как у `FormInput`. `class`, `style`,
572
+ все остальные атрибуты и слушатели ложатся на корень компонента (у `FormInput`
573
+ остальные атрибуты уходят на поле ввода).
574
+
405
575
  ### InfoPill
406
576
 
407
577
  Пилюля, которая только показывает текст: статус, счётчик, флаг, пометку.
@@ -623,13 +793,16 @@ exportOrders() {
623
793
  таблицы и изменением размера окна. Открытие другого меню закрывает
624
794
  предыдущее.
625
795
 
626
- Пока меню открыто, стрелки вверх и вниз переводят фокус по пунктам и
627
- страницу не прокручивают: вниз — на первый пункт, вверх — на последний,
628
- дальше — по соседним, с краёв — по кругу. Enter на пункте под фокусом
629
- выбирает его. Подсветка пункта — это фокус, и мышь ведёт тот же фокус:
630
- движение по пункту ставит фокус на него, стрелки продолжают от пункта под
631
- курсором. Подсвечен всегда один пункт — тот, на который последними указали
632
- клавиатура или мышь.
796
+ Пока меню открыто, стрелки вверх и вниз переводят фокус по пунктам и страницу не
797
+ прокручивают: вниз — на первый пункт, вверх — на последний, дальше — по
798
+ соседним, с краёв — по кругу. Enter на пункте под фокусом выбирает его.
799
+ Наведение подсвечивает пункт, но фокус не двигает: фокус меняют клавиатура и
800
+ клик. Пункт под мышью и пункт в фокусе с клавиатуры могут быть подсвечены
801
+ одновременно; стрелки продолжают от пункта в фокусе.
802
+
803
+ После закрытия меню фокус возвращается на стрелку, если он был внутри меню и
804
+ после закрытия потерян. Фокус, который перешёл на другой элемент (например, в
805
+ модалку, открытую пунктом), сохраняется.
633
806
 
634
807
  ### HamburgerMenu
635
808
 
@@ -675,9 +848,15 @@ Escape, клик по пункту, прокрутка и изменение р
675
848
  с `<hamburger-menu>` — `class`, `style`, `data-*` — ложатся на обёртку
676
849
  кнопки.
677
850
 
678
- Клавиатура и мышь — как в меню `DropdownButtonWithAction`: пока меню
679
- открыто, стрелки вверх и вниз переводят фокус по пунктам, Enter выбирает
680
- пункт под фокусом; подсветка пункта — это фокус, и мышь ведёт тот же фокус.
851
+ Клавиатура и мышь — как в меню `DropdownButtonWithAction`: пока меню открыто,
852
+ стрелки вверх и вниз переводят фокус по пунктам, Enter выбирает пункт под
853
+ фокусом; наведение подсвечивает пункт, но фокус не двигает: фокус меняют
854
+ клавиатура и клик, а пункт под мышью и пункт в фокусе могут быть подсвечены
855
+ одновременно.
856
+
857
+ После закрытия меню фокус возвращается на кнопку меню, если он был внутри меню
858
+ и после закрытия потерян. Фокус, который перешёл на другой элемент (например, в
859
+ модалку, открытую пунктом), сохраняется.
681
860
 
682
861
  ### DataTable
683
862
 
@@ -1008,12 +1187,12 @@ rounded-lg`, `box-sizing: border-box`. Отступов у неё нет: фор
1008
1187
  | `ConfirmationModal` — кнопка отмены | Отмена | Cancel |
1009
1188
  | `DropdownButtonWithAction` — подпись стрелки для скринридера | Открыть меню | Open menu |
1010
1189
  | `HamburgerMenu` — подпись кнопки для скринридера | Открыть меню | Open menu |
1011
- | `SelectDateInterval` — месяцы, дни недели, кнопки календарей | по-русски | in English |
1012
- | `SelectDateInterval` — подсказки полей | от / до | from / to |
1013
- | Ластик `Search`, `RussianMobileFilter`, `SelectSingle` (язык плагина), `SelectMultiple` (проп `lang`) и `SelectDateInterval` — подпись для скринридера | Очистить | Clear |
1014
- | `SelectMultiple` — надпись при нескольких выбранных | Выбрано: N | Selected: N |
1015
- | `SelectMultiple` — подсказка и имя поля поиска | Поиск | Search |
1016
- | `SelectMultiple` — нет совпадений | Ничего не найдено | Nothing found |
1190
+ | `SelectDateFilter`, `SelectDateForm`, `SelectDateIntervalFilter`, `SelectDateIntervalForm` — месяцы, дни недели, кнопки календарей | по-русски | in English |
1191
+ | `SelectDateIntervalFilter`, `SelectDateIntervalForm` — подсказки полей | от / до | from / to |
1192
+ | Ластик `Search`, `RussianMobileFilter`, `SelectSingleFilter` и `SelectSingleForm` (язык плагина), `SelectMultipleFilter` и `SelectMultipleForm` (проп `lang`), `SelectDateFilter`, `SelectDateForm`, `SelectDateIntervalFilter` и `SelectDateIntervalForm` — подпись для скринридера | Очистить | Clear |
1193
+ | `SelectMultipleFilter`, `SelectMultipleForm` — надпись при нескольких выбранных | Выбрано: N | Selected: N |
1194
+ | `SelectMultipleFilter`, `SelectMultipleForm` — подсказка и имя поля поиска | Поиск | Search |
1195
+ | `SelectMultipleFilter`, `SelectMultipleForm` — нет совпадений | Ничего не найдено | Nothing found |
1017
1196
  | `DataTable` — пагинация | Предыдущая / Следующая / Показаны результаты X - Y из Z | Previous / Next / Showing X - Y of Z results |
1018
1197
  | `PageTabs` — имя навигации для скринридера | Закладки | Tabs |
1019
1198
  | `PageCard` — доступное имя крестика | Назад | Back |
@@ -1021,8 +1200,9 @@ rounded-lg`, `box-sizing: border-box`. Отступов у неё нет: фор
1021
1200
  | `TextPopover` — подпись кнопки и имя области | Показать текст / Полный текст | Show text / Full text |
1022
1201
 
1023
1202
  Формат даты — `дд.мм.гггг` в обоих языках: это формат значения, а не текст.
1024
- Неделя начинается с понедельника. Календари `SelectDateInterval` берут язык
1025
- при монтировании: смена языка после монтирования в них не отражается.
1203
+ Неделя начинается с понедельника. Календари `SelectDateFilter`, `SelectDateForm`,
1204
+ `SelectDateIntervalFilter` и `SelectDateIntervalForm` берут язык при монтировании: смена языка после
1205
+ монтирования в них не отражается.
1026
1206
 
1027
1207
  ## Клавиатурная навигация
1028
1208
 
@@ -1040,7 +1220,7 @@ Vimium, Vimari, Vimlike — по их подсказкам, как мышью;
1040
1220
  выбирают только момент. Поля, крестик `NotificationMessage`, кнопки
1041
1221
  `ConfirmationModal` и `DropdownButtonWithAction` показывают фокус при любом
1042
1222
  его появлении, в том числе после клика мышью; остальные кнопки и ссылки —
1043
- только с клавиатуры. Стрелки месяцев и подпись месяца в календаре `PickDay`
1223
+ только с клавиатуры. Стрелки месяцев и подпись месяца в календаре поля даты
1044
1224
  берут тот же вид, когда фокус в них с клавиатуры.
1045
1225
 
1046
1226
  Vimlike (Safari на iPhone, iPad и Mac) считает кнопкой любой элемент
@@ -1050,17 +1230,19 @@ Vimlike (Safari на iPhone, iPad и Mac) считает кнопкой любо
1050
1230
  бы тексту, иконке, у которой нет `click()`, и скрытой подписи, которую Vimlike
1051
1231
  считает невидимой. Поэтому содержимое кнопок и ссылок пакета — текст, иконки,
1052
1232
  скрытые подписи — с курсором `default` и не ловит указатель: мышь над ним
1053
- видит руку самой кнопки. По той же причине поле даты `SelectDateInterval`
1054
- лежит не внутри кнопки календаря, а под ней: поле внутри кнопки Vimlike
1055
- считал бы кнопкой вместо неё. В поле по-прежнему можно перейти Tab и набрать
1056
- дату.
1057
-
1058
- Подсказки Vimlike в открытых меню, списках `SelectSingle` и `SelectMultiple` и календарях
1059
- `SelectDateInterval` не видны: Vimlike рисует их под верхним слоем браузера,
1060
- в котором открываются эти панели. Vimium выводит свои подсказки в верхний
1061
- слой, и у него такой проблемы нет. В Vimlike панель открывают подсказкой её
1062
- кнопки, а дальше выбирают стрелками и Enter: пункт списка или меню, день
1063
- календаря.
1233
+ видит руку самой кнопки. По той же причине поле даты `SelectDateFilter`, `SelectDateForm`,
1234
+ `SelectDateIntervalFilter` и `SelectDateIntervalForm` лежит не внутри кнопки календаря, а под ней: поле
1235
+ внутри кнопки Vimlike считал бы кнопкой вместо неё. В поле по-прежнему можно
1236
+ перейти Tab и набрать дату.
1237
+
1238
+ Подсказки Vimlike в открытых меню, списках `SelectSingleFilter`,
1239
+ `SelectSingleForm`, `SelectMultipleFilter` и `SelectMultipleForm` и календарях
1240
+ `SelectDateFilter`, `SelectDateForm`, `SelectDateIntervalFilter`
1241
+ и `SelectDateIntervalForm` не видны: Vimlike рисует
1242
+ их под верхним слоем браузера, в котором открываются эти панели. Vimium
1243
+ выводит свои подсказки в верхний слой, и у него такой проблемы нет. В Vimlike
1244
+ панель открывают подсказкой её кнопки, а дальше выбирают стрелками и Enter:
1245
+ пункт списка или меню, день календаря.
1064
1246
 
1065
1247
  ## SSR
1066
1248
 
@@ -1071,8 +1253,10 @@ Inertia SSR), а серверная разметка гидратируется
1071
1253
  - `PageCard` на сервере рисует крестик, только если задан `fallback-url`:
1072
1254
  адрес возврата известен только в браузере, и крестик, ведущий на него,
1073
1255
  появляется после монтирования;
1074
- - `SelectDateInterval` загружает Pikaday в браузере при монтировании:
1075
- календари появляются, когда загрузка закончится;
1256
+ - `SelectDateFilter`, `SelectDateForm`, `SelectDateIntervalFilter`
1257
+ и `SelectDateIntervalForm` загружают Pikaday в браузере при монтировании:
1258
+ календари появляются, когда загрузка
1259
+ закончится;
1076
1260
  - остальные компоненты рендерятся на сервере так же, как в браузере.
1077
1261
 
1078
1262
  ## Правила API пакета
@@ -1083,12 +1267,13 @@ Inertia SSR), а серверная разметка гидратируется
1083
1267
  - Значение компонента передаётся через `v-model` (проп `modelValue` и
1084
1268
  событие `update:modelValue`) и не обязательно: компонент обязан
1085
1269
  отрисовываться без переданного значения. `required: true` оставляют
1086
- только там, без чего компонент бессмыслен, — например, у `items` в
1087
- `SelectSingle` или у `header` во всех фильтрах.
1270
+ только там, без чего компонент бессмыслен, — например, у `items`
1271
+ в `SelectSingleFilter` и `SelectSingleForm`, у `header` во всех фильтрах
1272
+ или у `label` полей формы.
1088
1273
  - Именованные модели (`v-model:date-from`, `v-model:date-to`, как у
1089
- `SelectDateInterval`) — исключение для компонентов с несколькими
1090
- значениями. У компонента с одним значением именованная модель не нужна:
1091
- для него это и есть обычный `v-model`.
1274
+ `SelectDateIntervalFilter` и `SelectDateIntervalForm`) — исключение для
1275
+ компонентов с несколькими значениями. У компонента с одним значением
1276
+ именованная модель не нужна: для него это и есть обычный `v-model`.
1092
1277
  - Булев проп называется `is*`, если описывает состояние компонента
1093
1278
  (`isRequired`, `isLoading`), и `with*`, если описывает необязательную
1094
1279
  возможность (`withPulse` у `Dot`).
@@ -1144,10 +1329,10 @@ Inertia SSR), а серверная разметка гидратируется
1144
1329
 
1145
1330
  Правило пакета — значение через `v-model` — относится к состоянию, которое
1146
1331
  компонент меняет сам: меню `DropdownButtonWithAction` закрывается по клику
1147
- вне, `SelectSingle` меняет выбор. `ConfirmationModal` свою видимость не меняет
1148
- никогда. Обе кнопки и Escape только сообщают родителю решение пользователя,
1149
- а закрыть модалку, оставить её открытой на время запроса или открыть
1150
- следующую — решает родитель.
1332
+ вне, `SelectSingleFilter` меняет выбор. `ConfirmationModal` свою видимость
1333
+ не меняет никогда. Обе кнопки и Escape только сообщают родителю решение
1334
+ пользователя, а закрыть модалку, оставить её открытой на время запроса или
1335
+ открыть следующую — решает родитель.
1151
1336
 
1152
1337
  `v-model` обещал бы двустороннюю связь, которой нет, поэтому видимость
1153
1338
  передаётся пропом `isOpen`.
@@ -1166,12 +1351,24 @@ Inertia SSR), а серверная разметка гидратируется
1166
1351
 
1167
1352
  npm run playground
1168
1353
 
1169
- Поднимает демо-страницы со всеми девятнадцатью компонентами в двух окружениях:
1354
+ Поднимает демо-страницы со всеми двадцатью четырьмя компонентами в двух окружениях:
1170
1355
  голом (без Tailwind и стилей приложения) и в окружении приложения (с
1171
1356
  Tailwind, `@tailwindcss/forms` и типографикой, как у потребителя). Это
1172
1357
  основной способ посмотреть, как компоненты выглядят и ведут себя, а не
1173
1358
  угадывать по исходникам или по этому README.
1174
1359
 
1360
+ ### Браузерные тесты
1361
+
1362
+ npm run test:browser
1363
+
1364
+ Собирает пакет и прогоняет Playground в Chromium и WebKit — движке Safari.
1365
+ Установленный Safari тесты не запускают. Запускать на macOS: WebKit на Linux
1366
+ фокусирует кнопки по клику иначе, чем Safari. Перед первым запуском:
1367
+
1368
+ npx playwright install chromium webkit
1369
+
1370
+ Тесты только локальные, в GitHub Actions они не входят.
1371
+
1175
1372
  ## Что пакет берёт у приложения
1176
1373
 
1177
1374
  Базовую типографику — семейство шрифта, размер, `line-height`. Он наследует её
@@ -1182,6 +1379,43 @@ Tailwind, `@tailwindcss/forms` и типографикой, как у потре
1182
1379
  Правила номера телефона в `RussianMobileFilter` — российские; язык текстов
1183
1380
  задаётся, см. «Языки».
1184
1381
 
1382
+ ## Обновление с 0.19
1383
+
1384
+ | Было | Стало |
1385
+ | --- | --- |
1386
+ | `<select-single class="h-18 border border-gray-200" header="…">` | `<select-single-filter header="…">` — высота и рамка встроены |
1387
+ | `<select-multiple class="h-18 border border-gray-200" header="…">` | `<select-multiple-filter header="…">` |
1388
+ | `<select-date-interval class="h-18 border border-gray-200" header="…">` | `<select-date-interval-filter header="…">` |
1389
+ | `"select-source": SelectSingle` (проект регистрирует компонент под своим именем тега) | `"select-source": SelectSingleFilter`; так же для `SelectMultiple` и `SelectDateInterval` |
1390
+ | `SelectSingle` в форме рядом с `FormInput` | `<select-single-form label="…">` |
1391
+ | `SelectMultiple` в форме | `<select-multiple-form label="…">` |
1392
+ | `SelectDateInterval` в форме | `<select-date-interval-form label="…">` |
1393
+
1394
+ `import { SelectSingle }` больше не работает: имена `SelectSingle`,
1395
+ `SelectMultiple` и `SelectDateInterval` из пакета убраны. Остальные классы
1396
+ на фильтрах (`ml-2` и т. п.) переносятся как есть.
1397
+
1398
+ В формах меняются и пропы: `header` становится `label`, `class="border
1399
+ border-gray-200"` убирается (на корне формы он обвёл бы подпись вместе с полем),
1400
+ а `isLoading` у форм нет.
1401
+
1402
+ Наведение мыши в списках и меню больше не двигает фокус: оно только подсвечивает
1403
+ пункт, фокус меняют клавиатура и клик.
1404
+
1405
+ Цветные пункты меню `DropdownButtonWithAction` и `HamburgerMenu` теперь всегда
1406
+ с фоном своего цвета: например, красный пункт «Удалить» / «Delete» в меню
1407
+ строки получает светло-красный фон.
1408
+
1409
+ В Safari фокус после закрытия меню `DropdownButtonWithAction` и `HamburgerMenu`
1410
+ — Escape, если фокус был в меню, выбор пункта мышью или клавиатурой, закрытие
1411
+ модалки, открытой пунктом, — возвращается на кнопку меню, как в Chrome.
1412
+
1413
+ `SelectDateFilter` и `SelectDateForm` — новые компоненты одной даты, у них
1414
+ нет предшественника: в таблице их нет.
1415
+
1416
+ `0.20.0` не подтянется по `^0.19.x`: для версий `0.x` знак `^` пропускает
1417
+ только патчи. Обновление — `npm install @boobooking/dashboard-ui-components@^0.20.0`.
1418
+
1185
1419
  ## Обновление с 0.15
1186
1420
 
1187
1421
  | Было | Стало |