@boobooking/dashboard-ui-components 0.19.1 → 0.21.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,13 @@ 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`, `SelectSingleCards`, `SelectMultipleList`, `InfoPill`,
100
+ `ErrorMessages`, `FormInput`, `ActionPill`,
101
+ `ConfirmationModal`, `DropdownButtonWithAction`, `HamburgerMenu`, `DataTable`,
97
102
  `NavigationMenuElement`, `PageTabs`, `PageCard`, `NotificationMessage`,
98
103
  `TextPopover`, функцию `downloadFile` и плагин `dashboardUi`. В архив пакета
99
104
  (`files: ["dist"]`) исходники не попадают, поэтому контракт каждого
@@ -225,14 +230,77 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
225
230
  `isRequired` только показывает точку: атрибут `required` и `aria-*` полю
226
231
  он не ставит.
227
232
 
228
- ### SelectDateInterval
233
+ ### SelectDateFilter
234
+
235
+ Одно поле даты под заголовком. Дата выбирается в календаре Pikaday,
236
+ у поля — ластик очистки. Подсказки у поля нет. Pikaday загружается
237
+ в браузере при монтировании компонента, а не при загрузке пакета, поэтому
238
+ календарь появляется, когда загрузка закончится.
239
+
240
+ Высота 4.5rem и серая рамка встроены в фильтр, ширина поля 9rem: класс
241
+ `h-18 border border-gray-200` ему не нужен. `class` и остальные атрибуты
242
+ ложатся на корень фильтра.
243
+
244
+ <select-date-filter header="Дата" v-model="day" @changed="reload"/>
245
+
246
+ | Проп | Тип | По умолчанию | Описание |
247
+ | --- | --- | --- | --- |
248
+ | `modelValue` | `String` | `""` | Выбранная дата |
249
+ | `header` | `String` | обязателен | Подпись поля |
250
+ | `isRequired` | `Boolean` | `false` | Пометка обязательности в заголовке |
251
+ | `isLoading` | `Boolean` | `false` | Индикатор загрузки в заголовке |
252
+ | `lang` | `String` | язык плагина | `"ru"` или `"en"`; действует на календарь и на подпись ластика для скринридера (у самого поля текста нет) |
253
+
254
+ События: `update:modelValue` (дата или пустая строка после ластика)
255
+ и `changed` приходят на каждый выбор пользователя: в том числе на повторный
256
+ выбор уже показанной даты, на набранную в поле дату, которая разобралась,
257
+ и на очистку ластиком. Когда значение меняет родитель, ни одно из событий
258
+ не приходит. Поля диапазона `SelectDateIntervalFilter` и
259
+ `SelectDateIntervalForm` устроены иначе: их `changed` приходит, только когда
260
+ новое значение отличается от переданного пропса.
261
+
262
+ Календарь, ластик и клавиатура — как у каждого из двух полей
263
+ `SelectDateIntervalFilter` (см. «SelectDateIntervalFilter»).
264
+
265
+ ### SelectDateForm
266
+
267
+ Одно поле даты в форме, в виде `FormInput`: подпись над полем, рамка поля
268
+ на всю ширину формы, высотой 38px, как у `FormInput`. Рамка скругляет и поле,
269
+ и кольцо фокуса в нём. Подсказки у поля нет.
270
+
271
+ <select-date-form label="Дата" v-model="day" :is-required="markDayRequired"/>
272
+
273
+ | Проп | Тип | По умолчанию | Описание |
274
+ | --- | --- | --- | --- |
275
+ | `modelValue` | `String` | `""` | Выбранная дата |
276
+ | `label` | `String` | обязателен | Подпись над полем |
277
+ | `isRequired` | `Boolean` | `false` | Красная точка у подписи |
278
+ | `lang` | `String` | язык плагина | `"ru"` или `"en"`; действует на календарь и на подпись ластика для скринридера (у самого поля текста нет) |
279
+
280
+ События: `update:modelValue` и `changed` — когда значение выбрал пользователь,
281
+ как у `SelectDateFilter` (см. «SelectDateFilter»); смена значения родителем
282
+ их не вызывает. Календарь, ластик и клавиатура — тоже как у него.
283
+
284
+ Подпись связана с полем для скринридера: кнопка календаря называется
285
+ подписью и датой, поле ввода — подписью. Клик по подписи ничего не делает.
286
+
287
+ `isRequired` только показывает точку, как у `FormInput`. `class`, `style`,
288
+ все остальные атрибуты и слушатели ложатся на корень компонента (у `FormInput`
289
+ остальные атрибуты уходят на поле ввода).
290
+
291
+ ### SelectDateIntervalFilter
229
292
 
230
293
  Два поля даты под одним заголовком — интервал дат «от» и «до». Дата
231
294
  выбирается в календаре Pikaday, у каждого поля — ластик очистки. Pikaday
232
295
  загружается в браузере при монтировании компонента, а не при загрузке
233
296
  пакета, поэтому календари появляются, когда загрузка закончится.
234
297
 
235
- <select-date-interval
298
+ Высота 4.5rem и серая рамка встроены в фильтр: класс
299
+ `h-18 border border-gray-200` ему не нужен. Ширина фильтра 18rem, «от» и «до»
300
+ по половине, между ними вертикальная линия. `class` и остальные атрибуты
301
+ ложатся на корень фильтра.
302
+
303
+ <select-date-interval-filter
236
304
  header="Период"
237
305
  :date-from="dateFrom"
238
306
  :date-to="dateTo"
@@ -253,7 +321,8 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
253
321
  События: `update:dateFrom`, `update:dateTo` — на каждый выбор даты
254
322
  в соответствующем поле и на его очистку ластиком (пустой строкой);
255
323
  `changed` — когда новое значение отличается от переданного пропса
256
- (отдельно для каждой из двух дат).
324
+ (отдельно для каждой из двух дат). Повторный выбор уже показанной даты
325
+ событий не вызывает.
257
326
 
258
327
  Клик по любому месту поля открывает его календарь. Календарь открывается
259
328
  в верхнем слое браузера (Popover API): его не обрезает обёртка
@@ -274,9 +343,42 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
274
343
  же, как клик; Escape закрывает календарь. После закрытия фокус возвращается на
275
344
  поле. В поле можно перейти Tab и набрать дату.
276
345
 
277
- ### SelectSingle
346
+ ### SelectDateIntervalForm
347
+
348
+ Интервал дат в форме, в виде `FormInput`: подпись над полями, под ней «от»
349
+ и «до» одинаковой ширины на всю ширину формы. У каждого поля своя рамка, как
350
+ у `FormInput`, высотой 38px; рамка скругляет и поле, и кольцо фокуса в нём.
278
351
 
279
- <select-single
352
+ <select-date-interval-form
353
+ label="Период"
354
+ v-model:date-from="dateFrom"
355
+ v-model:date-to="dateTo"
356
+ :is-required="markPeriodRequired"
357
+ />
358
+
359
+ | Проп | Тип | По умолчанию | Описание |
360
+ | --- | --- | --- | --- |
361
+ | `dateFrom` | `String` | `""` | Начало интервала |
362
+ | `dateTo` | `String` | `""` | Конец интервала |
363
+ | `label` | `String` | обязателен | Подпись над полями |
364
+ | `isRequired` | `Boolean` | `false` | Красная точка у подписи |
365
+ | `lang` | `String` | язык плагина | `"ru"` или `"en"`; действует и на подсказки полей, и на оба календаря |
366
+
367
+ События те же, что у `SelectDateIntervalFilter`: `update:dateFrom`,
368
+ `update:dateTo` и `changed`. Календари, ластики, подсказки и клавиатура —
369
+ тоже как у него (см. «SelectDateIntervalFilter»).
370
+
371
+ Подпись связана с полями для скринридера: оба поля — группа, названная
372
+ подписью, а каждое поле, как в фильтре, называется своей подсказкой «от» или
373
+ «до» с датой. Клик по подписи ничего не делает.
374
+
375
+ `isRequired` только показывает точку, как у `FormInput`. `class`, `style`,
376
+ все остальные атрибуты и слушатели ложатся на корень компонента (у `FormInput`
377
+ остальные атрибуты уходят на поле ввода).
378
+
379
+ ### SelectSingleFilter
380
+
381
+ <select-single-filter
280
382
  header="Вендор"
281
383
  :items="[{ id: 'a', name: 'Первый' }]"
282
384
  v-model="vendor"
@@ -298,6 +400,11 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
298
400
  События: `update:modelValue` и `changed` — при выборе элемента (повторный
299
401
  клик по уже выбранному снимает выбор) и при очистке через ластик.
300
402
 
403
+ Высота 4.5rem и серая рамка встроены в фильтр: класс
404
+ `h-18 border border-gray-200` ему не нужен. `class` и остальные атрибуты
405
+ ложатся на корень фильтра. Без пунктов кнопки нет, а заголовок, высота и рамка
406
+ остаются.
407
+
301
408
  С клавиатуры: пока список открыт, стрелки вверх и вниз переводят фокус по
302
409
  пунктам и страницу не прокручивают. Отсчёт идёт от выбранного пункта: вниз —
303
410
  следующий за ним, вверх — предыдущий; без выбранного вниз — первый пункт,
@@ -307,9 +414,9 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
307
414
  возвращается на кнопку фильтра. У закрытого списка стрелки прокручивают
308
415
  страницу.
309
416
 
310
- Подсветка пункта — это фокус, и мышь ведёт тот же фокус: движение по пункту
311
- ставит фокус на него, стрелки продолжают от пункта под курсором. Подсвечен
312
- всегда один пункт — тот, на который последними указали клавиатура или мышь.
417
+ Наведение подсвечивает пункт, но фокус не двигает: фокус меняют клавиатура и
418
+ клик. Пункт под мышью и пункт в фокусе с клавиатуры могут быть подсвечены
419
+ одновременно; стрелки продолжают от пункта в фокусе.
313
420
 
314
421
  Список открывается в верхнем слое браузера (Popover API): его не обрезает
315
422
  обёртка с прокруткой. Он открывается под полем, левым краем по левому
@@ -322,18 +429,50 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
322
429
  внутри списка — нет. Открытие другого списка, календаря или меню
323
430
  закрывает предыдущее.
324
431
 
325
- ### SelectMultiple
432
+ ### SelectSingleForm
326
433
 
327
- <select-multiple
434
+ Выбор одного пункта в форме, в виде `FormInput`: подпись над полем, рамка
435
+ поля на всю ширину формы, высотой 38px, как у `FormInput`. В рамке — кнопка
436
+ со списком и ластиком, та же, что у `SelectSingleFilter`.
437
+
438
+ <select-single-form
439
+ label="Вендор"
440
+ :items="vendors"
441
+ v-model="vendor"
442
+ :is-required="markVendorRequired"
443
+ />
444
+
445
+ | Проп | Тип | По умолчанию | Описание |
446
+ | --- | --- | --- | --- |
447
+ | `items` | `Array` | обязателен | Массив `{ id, name }` |
448
+ | `modelValue` | `String \| Number` | `null` | `id` выбранного элемента или `null` |
449
+ | `label` | `String` | обязателен | Подпись над полем |
450
+ | `isRequired` | `Boolean` | `false` | Красная точка у подписи |
451
+
452
+ `items`, `v-model`, события, список и клавиатура — как у `SelectSingleFilter`
453
+ (см. «SelectSingleFilter»). Без пунктов кнопки нет, под подписью остаётся
454
+ пустая рамка.
455
+
456
+ Подпись связана с кнопкой для скринридера: кнопка называется подписью
457
+ и выбранным пунктом, у пустого поля — подписью. Клик по подписи ничего
458
+ не делает.
459
+
460
+ `isRequired` только показывает точку, как у `FormInput`. `class`, `style`,
461
+ все остальные атрибуты и слушатели ложатся на корень компонента (у `FormInput`
462
+ остальные атрибуты уходят на поле ввода).
463
+
464
+ ### SelectMultipleFilter
465
+
466
+ <select-multiple-filter
328
467
  header="Бренд"
329
468
  :items="[{ id: 'rc', name: 'Royal Canin' }, { id: 'eukanuba', name: 'Eukanuba' }]"
330
469
  v-model="brands"
331
470
  @changed="reload"
332
471
  />
333
472
 
334
- <select-multiple header="Мероприятие" :items="events" v-model="eventIds" with-search @changed="reload"/>
473
+ <select-multiple-filter header="Мероприятие" :items="events" v-model="eventIds" with-search @changed="reload"/>
335
474
 
336
- Тот же фильтр, что `SelectSingle`, но выбрать можно несколько пунктов.
475
+ Тот же фильтр, что `SelectSingleFilter`, но выбрать можно несколько пунктов.
337
476
  `items` — массив объектов `{ id, name }`. `v-model` держит массив `id`
338
477
  выбранных пунктов, пустой массив — ничего не выбрано. `id` — строка или число,
339
478
  сравнение строгое.
@@ -367,19 +506,20 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
367
506
  на кнопку фильтра, а запрос поиска сбрасывается. `changed` уходит после
368
507
  каждого выбора, и страница сразу перезапрашивает выдачу.
369
508
 
370
- Список открывается так же, как у `SelectSingle`: в верхнем слое браузера, место,
509
+ Список открывается так же, как у `SelectSingleFilter`: в верхнем слое браузера, место,
371
510
  высота, прокрутка и способы закрытия те же, фокус после закрытия возвращается
372
511
  на кнопку. Отличия: галочка стоит у каждого выбранного пункта; пункт
373
512
  сообщает скринридеру, выбран ли он (`aria-pressed`).
374
- Как и у `SelectSingle`, без пунктов кнопки нет, заголовок остаётся. Пункты
375
- пропали при открытом списке — список закрывается, запрос поиска сбрасывается,
376
- а вернувшиеся пункты появляются с закрытым списком.
513
+ Как и у `SelectSingleFilter`, без пунктов кнопки нет, а заголовок, высота
514
+ и рамка остаются. Пункты пропали при открытом списке — список закрывается,
515
+ запрос поиска сбрасывается, а вернувшиеся пункты появляются с закрытым списком.
377
516
 
378
- С клавиатуры, пока список открыт, всё как у `SelectSingle`: стрелки вверх и вниз
379
- ведут фокус по пунктам по кругу, Enter или пробел переключают пункт и закрывают
380
- список, Escape закрывает его без выбора. Если выбрано несколько пунктов,
381
- отсчёт идёт от первого выбранного среди видимых. Мышь ведёт тот же фокус, что
382
- и стрелки: движение по пункту ставит фокус на него, подсвечен всегда один пункт.
517
+ С клавиатуры, пока список открыт, всё как у `SelectSingleFilter`: стрелки вверх
518
+ и вниз ведут фокус по пунктам по кругу, Enter или пробел переключают пункт и
519
+ закрывают список, Escape закрывает его без выбора. Если выбрано несколько
520
+ пунктов, отсчёт идёт от первого выбранного среди видимых. Наведение подсвечивает
521
+ пункт, но фокус не двигает: фокус меняют клавиатура и клик, пункт под мышью и
522
+ пункт в фокусе могут быть подсвечены одновременно.
383
523
 
384
524
  С `with-search` над пунктами стоит поле поиска: при прокрутке длинного списка
385
525
  оно остаётся на месте. Имя пункта должно содержать запрос, регистр не важен,
@@ -387,21 +527,172 @@ Tailwind, `@tailwindcss/forms`, Inertia и какие-либо токены в C
387
527
  строка «Ничего не найдено». Выбранные пункты, скрытые поиском, остаются
388
528
  выбранными. Запрос не входит в `v-model`; он сбрасывается при каждом закрытии
389
529
  списка, в том числе при выборе пункта. Ластик в поле очищает запрос. При
390
- открытии списка фокус встаёт в поле; при загрузке страницы фокус в поле
391
- не уходит. Без Popover API список виден всегда, и фокус в поле сам
392
- не ставится. Пробел в поле печатает пробел, Enter ничего не делает и форму
393
- не отправляет. Поле — первая остановка стрелок: из него вниз — первый пункт,
394
- вверх — последний, с краёв пунктов — обратно в поле. Без совпадений стрелки
395
- в поле ничего не делают. Пока список открыт, Tab и Shift+Tab ходят по кругу
396
- внутри него: поле, ластик поля, пока запрос не пуст, пункты; наружу, на
397
- страницу, фокус уходит после закрытия списка. Ластик поля входит в Tab, но не
398
- в стрелки. Ластик на кнопке фильтра идёт в Tab сразу после неё.
399
- Печатный символ и Backspace на пункте уходят в поле, поэтому набор не
400
- пропадает, когда мышь увела фокус на пункт. Пока список открыт, панель не
530
+ открытии списка фокус встаёт в поле; при загрузке страницы фокус в поле не
531
+ уходит. Без Popover API список виден всегда, и фокус в поле сам не ставится.
532
+ Пробел в поле печатает пробел, Enter ничего не делает и форму не отправляет.
533
+ Поле — первая остановка стрелок: из него вниз — первый пункт, вверх — последний,
534
+ с краёв пунктов — обратно в поле. Без совпадений стрелки в поле ничего не
535
+ делают. Пока список открыт, Tab и Shift+Tab ходят по кругу внутри него: поле,
536
+ ластик поля, пока запрос не пуст, пункты; наружу, на страницу, фокус уходит
537
+ после закрытия списка. Ластик поля входит в Tab, но не в стрелки. Ластик на
538
+ кнопке фильтра идёт в Tab сразу после неё. Печатный символ и Backspace на
539
+ пункте, куда фокус перевели стрелки или Tab, уходят в поле, поэтому набор не
540
+ пропадает; мышь фокус на пункт не уводит. Пока список открыт, панель не
401
541
  становится уже, чем при открытии, а поле не двигается, сколько бы пунктов ни
402
542
  убрал поиск: открытая вниз панель становится ниже вместе с найденным, открытая
403
543
  вверх не становится ниже, и пустое место остаётся под пунктами, у кнопки.
404
544
 
545
+ ### SelectMultipleForm
546
+
547
+ Выбор нескольких пунктов в форме, в виде `FormInput`: подпись над полем, рамка
548
+ поля на всю ширину формы, высотой 38px, как у `FormInput`. В рамке — кнопка
549
+ со списком, поиском и ластиком, та же, что у `SelectMultipleFilter`.
550
+
551
+ <select-multiple-form label="Бренд" :items="brands" v-model="brandIds"/>
552
+
553
+ <select-multiple-form label="Мероприятие" :items="events" v-model="eventIds" with-search :is-required="markEventsRequired"/>
554
+
555
+ | Проп | Тип | По умолчанию | Описание |
556
+ | --- | --- | --- | --- |
557
+ | `items` | `Array` | обязателен | Массив `{ id, name }` |
558
+ | `modelValue` | `Array` | `[]` | `id` выбранных пунктов |
559
+ | `label` | `String` | обязателен | Подпись над полем |
560
+ | `isRequired` | `Boolean` | `false` | Красная точка у подписи |
561
+ | `withSearch` | `Boolean` | `false` | Поле поиска вверху списка |
562
+ | `lang` | `String` | язык плагина | `"ru"` или `"en"` — надпись, поле поиска, «Ничего не найдено», подписи обоих ластиков |
563
+
564
+ `items`, `v-model`, события, надпись на кнопке, список, поиск и клавиатура —
565
+ как у `SelectMultipleFilter` (см. «SelectMultipleFilter»). Без пунктов кнопки
566
+ нет, под подписью остаётся пустая рамка.
567
+
568
+ Подпись связана с кнопкой для скринридера: кнопка называется подписью
569
+ и надписью на кнопке, у пустого поля — подписью. Клик по подписи ничего
570
+ не делает.
571
+
572
+ `isRequired` только показывает точку, как у `FormInput`. `class`, `style`,
573
+ все остальные атрибуты и слушатели ложатся на корень компонента (у `FormInput`
574
+ остальные атрибуты уходят на поле ввода).
575
+
576
+ ### SelectSingleCards
577
+
578
+ Выбор одного пункта карточками в форме: подпись над карточками, в каждой
579
+ карточке кружок слева и надпись. У выбранной карточки синяя рамка, светло-синий
580
+ фон и точка в кружке. Карточки стоят в несколько колонок на всю ширину формы.
581
+
582
+ <select-single-cards label="Бренд" :items="brands" v-model="brand" :is-required="markBrandRequired"/>
583
+
584
+ | Проп | Тип | По умолчанию | Описание |
585
+ | --- | --- | --- | --- |
586
+ | `items` | `Array` | обязателен | Массив `{ id, name }` |
587
+ | `modelValue` | `String \| Number \| Boolean` | `null` | `id` выбранного пункта или `null` |
588
+ | `label` | `String` | обязателен | Подпись над карточками |
589
+ | `isRequired` | `Boolean` | `false` | Красная точка у подписи |
590
+ | `columns` | `Number` | `2` | Число колонок, целое от 1; иначе — две колонки. Vue предупреждает о нецелом, меньшем 1 и нечисловом значении, но не о `null` |
591
+
592
+ Событий два: `update:modelValue` с `id` выбранного пункта и сразу за ним
593
+ `changed`, после каждого выбора пользователя. `id` уходит в событие как есть,
594
+ без приведения к строке: строки, числа и `true` / `false` сравниваются строго.
595
+ Надпись карточки — `name`.
596
+
597
+ Без пунктов (`items` пуст, `null` или не массив) видна только подпись, сетки нет;
598
+ элементы, не являющиеся объектами, пропускаются.
599
+
600
+ Клик в любом месте карточки выбирает её. Клик по уже выбранной карточке
601
+ ничего не меняет и событий не вызывает: выбор не снимается, «ничего не
602
+ выбрано» бывает только до первого выбора. Если `modelValue` не совпадает
603
+ ни с одним `id`, не выбрана ни одна карточка.
604
+
605
+ Если родитель не принял значение (не обновил `modelValue` в ответ на
606
+ `update:modelValue`), выбранной остаётся карточка, которую задаёт проп.
607
+
608
+ Колонки компонент раскладывает сам: пункты идут по колонкам в порядке массива,
609
+ сначала заполняется первая колонка сверху вниз, потом вторая и так далее.
610
+ Длины колонок различаются не больше чем на один пункт, лишние пункты достаются
611
+ первым колонкам. Для `n` пунктов и `c` колонок:
612
+
613
+ | `n` | `c` | Колонки |
614
+ | --- | --- | --- |
615
+ | 14 | 2 | 7, 7 |
616
+ | 14 | 3 | 5, 5, 4 |
617
+ | 4 | 3 | 2, 1, 1 |
618
+ | 2 | 2 | 1, 1 |
619
+ | 2 | 3 | 1, 1, пустая |
620
+ | 1 | 2 | 1, пустая |
621
+
622
+ Колонки одинаковой ширины, их число всегда равно `columns`: при `n < c`
623
+ пустые колонки остаются местом справа, и ширина карточек от числа пунктов не
624
+ зависит. Карточки одной строки одной высоты, по самой высокой: так надпись,
625
+ перенесённая на две строки, не делает соседнюю карточку ниже. Колонки не
626
+ перестраиваются под узкий экран. Порядок Tab и стрелок — порядок массива, а не
627
+ порядок строк на экране.
628
+
629
+ С клавиатуры карточки ведут себя как родная группа переключателей: Tab входит
630
+ в группу один раз — на выбранную карточку, а если выбранной нет, на первую;
631
+ следующий Tab уходит из группы. Стрелки переходят к соседней карточке в
632
+ порядке массива и выбирают её, пробел выбирает карточку под фокусом. Кольцо
633
+ фокуса — вокруг всей карточки, только при фокусе с клавиатуры.
634
+
635
+ Для скринридера сетка карточек — группа `radiogroup`, названная подписью;
636
+ каждая карточка называется своей надписью. Клик по подписи ничего не делает.
637
+
638
+ В режиме высокой контрастности (`forced-colors: active`) браузер заменяет цвета
639
+ системными, а выбранная карточка остаётся видна: точка в кружке — системным
640
+ цветом текста, кружок — цветом выделения. Кольцо фокуса в этом режиме — одна
641
+ линия, ореол браузер снимает.
642
+
643
+ `isRequired` только показывает точку, как у `FormInput`: атрибутов `required`
644
+ и `aria-required` компонент не ставит. `class`, `style`, все остальные атрибуты
645
+ и слушатели ложатся на корень компонента. Своих надписей у компонента нет,
646
+ поэтому `lang` нет. Вид не зависит от preflight и `@tailwindcss/forms`
647
+ приложения: кружок и точку рисует сам компонент.
648
+
649
+ ### SelectMultipleList
650
+
651
+ Выбор нескольких пунктов списком галочек в форме: подпись над списком, у
652
+ каждого пункта квадрат с галочкой и надпись. Отмеченный квадрат закрашен
653
+ индиго с белой галочкой. Пункты стоят в несколько колонок.
654
+
655
+ <select-multiple-list label="Участники" :items="participantTypes" v-model="participants" :columns="2"/>
656
+
657
+ | Проп | Тип | По умолчанию | Описание |
658
+ | --- | --- | --- | --- |
659
+ | `items` | `Array` | обязателен | Массив `{ id, name }` |
660
+ | `modelValue` | `Array` | `[]` | `id` отмеченных пунктов |
661
+ | `label` | `String` | обязателен | Подпись над списком |
662
+ | `isRequired` | `Boolean` | `false` | Красная точка у подписи |
663
+ | `columns` | `Number` | `2` | Число колонок, целое от 1; иначе — две колонки. Vue предупреждает о нецелом, меньшем 1 и нечисловом значении, но не о `null` |
664
+
665
+ Событий два: `update:modelValue` с новым массивом и сразу за ним `changed`,
666
+ после каждого выбора пользователя. Отметка добавляет `id` в конец массива,
667
+ снятие убирает его; `id`, которых нет среди пунктов, остаются в значении.
668
+ `modelValue`, не являющийся массивом, значит «ничего не отмечено». Клик по
669
+ квадрату и по надписи отмечает или снимает пункт.
670
+
671
+ Без пунктов (`items` пуст, `null` или не массив) видна только подпись, списка нет;
672
+ элементы, не являющиеся объектами, пропускаются.
673
+
674
+ Если родитель не принял значение (не обновил `modelValue`), отметки остаются
675
+ такими, какими их задаёт проп.
676
+
677
+ Раскладка по колонкам, ширина колонок, высота строк и порядок — как у
678
+ `SelectSingleCards` (см. «SelectSingleCards»), в том числе таблица `n` / `c`.
679
+
680
+ С клавиатуры каждая галочка — отдельная остановка Tab в порядке массива,
681
+ пробел отмечает и снимает. Кольцо фокуса — вокруг квадрата, только при фокусе
682
+ с клавиатуры.
683
+
684
+ Для скринридера список — группа `group`, названная подписью; каждая галочка
685
+ называется своей надписью. Клик по подписи ничего не делает.
686
+
687
+ В режиме высокой контрастности (`forced-colors: active`) компонент показывает
688
+ родные галочки браузера в системных цветах: свой закрашенный квадрат браузер
689
+ перекрасил бы в цвет фона, и отмеченный пункт не отличался бы от неотмеченного.
690
+ Кольцо фокуса в этом режиме — одна линия, как у `SelectSingleCards`.
691
+
692
+ `isRequired`, `class`, `style`, остальные атрибуты и слушатели, отсутствие
693
+ `lang` и независимость вида от preflight и `@tailwindcss/forms` — как у
694
+ `SelectSingleCards`.
695
+
405
696
  ### InfoPill
406
697
 
407
698
  Пилюля, которая только показывает текст: статус, счётчик, флаг, пометку.
@@ -623,13 +914,16 @@ exportOrders() {
623
914
  таблицы и изменением размера окна. Открытие другого меню закрывает
624
915
  предыдущее.
625
916
 
626
- Пока меню открыто, стрелки вверх и вниз переводят фокус по пунктам и
627
- страницу не прокручивают: вниз — на первый пункт, вверх — на последний,
628
- дальше — по соседним, с краёв — по кругу. Enter на пункте под фокусом
629
- выбирает его. Подсветка пункта — это фокус, и мышь ведёт тот же фокус:
630
- движение по пункту ставит фокус на него, стрелки продолжают от пункта под
631
- курсором. Подсвечен всегда один пункт — тот, на который последними указали
632
- клавиатура или мышь.
917
+ Пока меню открыто, стрелки вверх и вниз переводят фокус по пунктам и страницу не
918
+ прокручивают: вниз — на первый пункт, вверх — на последний, дальше — по
919
+ соседним, с краёв — по кругу. Enter на пункте под фокусом выбирает его.
920
+ Наведение подсвечивает пункт, но фокус не двигает: фокус меняют клавиатура и
921
+ клик. Пункт под мышью и пункт в фокусе с клавиатуры могут быть подсвечены
922
+ одновременно; стрелки продолжают от пункта в фокусе.
923
+
924
+ После закрытия меню фокус возвращается на стрелку, если он был внутри меню и
925
+ после закрытия потерян. Фокус, который перешёл на другой элемент (например, в
926
+ модалку, открытую пунктом), сохраняется.
633
927
 
634
928
  ### HamburgerMenu
635
929
 
@@ -675,9 +969,15 @@ Escape, клик по пункту, прокрутка и изменение р
675
969
  с `<hamburger-menu>` — `class`, `style`, `data-*` — ложатся на обёртку
676
970
  кнопки.
677
971
 
678
- Клавиатура и мышь — как в меню `DropdownButtonWithAction`: пока меню
679
- открыто, стрелки вверх и вниз переводят фокус по пунктам, Enter выбирает
680
- пункт под фокусом; подсветка пункта — это фокус, и мышь ведёт тот же фокус.
972
+ Клавиатура и мышь — как в меню `DropdownButtonWithAction`: пока меню открыто,
973
+ стрелки вверх и вниз переводят фокус по пунктам, Enter выбирает пункт под
974
+ фокусом; наведение подсвечивает пункт, но фокус не двигает: фокус меняют
975
+ клавиатура и клик, а пункт под мышью и пункт в фокусе могут быть подсвечены
976
+ одновременно.
977
+
978
+ После закрытия меню фокус возвращается на кнопку меню, если он был внутри меню
979
+ и после закрытия потерян. Фокус, который перешёл на другой элемент (например, в
980
+ модалку, открытую пунктом), сохраняется.
681
981
 
682
982
  ### DataTable
683
983
 
@@ -1008,12 +1308,12 @@ rounded-lg`, `box-sizing: border-box`. Отступов у неё нет: фор
1008
1308
  | `ConfirmationModal` — кнопка отмены | Отмена | Cancel |
1009
1309
  | `DropdownButtonWithAction` — подпись стрелки для скринридера | Открыть меню | Open menu |
1010
1310
  | `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 |
1311
+ | `SelectDateFilter`, `SelectDateForm`, `SelectDateIntervalFilter`, `SelectDateIntervalForm` — месяцы, дни недели, кнопки календарей | по-русски | in English |
1312
+ | `SelectDateIntervalFilter`, `SelectDateIntervalForm` — подсказки полей | от / до | from / to |
1313
+ | Ластик `Search`, `RussianMobileFilter`, `SelectSingleFilter` и `SelectSingleForm` (язык плагина), `SelectMultipleFilter` и `SelectMultipleForm` (проп `lang`), `SelectDateFilter`, `SelectDateForm`, `SelectDateIntervalFilter` и `SelectDateIntervalForm` — подпись для скринридера | Очистить | Clear |
1314
+ | `SelectMultipleFilter`, `SelectMultipleForm` — надпись при нескольких выбранных | Выбрано: N | Selected: N |
1315
+ | `SelectMultipleFilter`, `SelectMultipleForm` — подсказка и имя поля поиска | Поиск | Search |
1316
+ | `SelectMultipleFilter`, `SelectMultipleForm` — нет совпадений | Ничего не найдено | Nothing found |
1017
1317
  | `DataTable` — пагинация | Предыдущая / Следующая / Показаны результаты X - Y из Z | Previous / Next / Showing X - Y of Z results |
1018
1318
  | `PageTabs` — имя навигации для скринридера | Закладки | Tabs |
1019
1319
  | `PageCard` — доступное имя крестика | Назад | Back |
@@ -1021,8 +1321,9 @@ rounded-lg`, `box-sizing: border-box`. Отступов у неё нет: фор
1021
1321
  | `TextPopover` — подпись кнопки и имя области | Показать текст / Полный текст | Show text / Full text |
1022
1322
 
1023
1323
  Формат даты — `дд.мм.гггг` в обоих языках: это формат значения, а не текст.
1024
- Неделя начинается с понедельника. Календари `SelectDateInterval` берут язык
1025
- при монтировании: смена языка после монтирования в них не отражается.
1324
+ Неделя начинается с понедельника. Календари `SelectDateFilter`, `SelectDateForm`,
1325
+ `SelectDateIntervalFilter` и `SelectDateIntervalForm` берут язык при монтировании: смена языка после
1326
+ монтирования в них не отражается.
1026
1327
 
1027
1328
  ## Клавиатурная навигация
1028
1329
 
@@ -1036,11 +1337,15 @@ Vimium, Vimari, Vimlike — по их подсказкам, как мышью;
1036
1337
 
1037
1338
  Фокус у всех компонентов пакета выглядит одинаково, как у `FormInput`: линия
1038
1339
  1px `blue-300` по краю элемента и ореол 3px `blue-200` с прозрачностью 50%.
1039
- Вид задан одной утилитой `focus-ring` в `src/styles/index.css`, компоненты
1040
- выбирают только момент. Поля, крестик `NotificationMessage`, кнопки
1340
+ В режиме высокой контрастности (`forced-colors: active`) ореола нет, а линия
1341
+ отстоит от края элемента на 2px: на рамке того же системного цвета она бы
1342
+ слилась с ней. Вид задан одной утилитой `focus-ring` в `src/styles/index.css`,
1343
+ компоненты выбирают только момент. Поля, кроме `SelectSingleCards` и
1344
+ `SelectMultipleList`, крестик `NotificationMessage`, кнопки
1041
1345
  `ConfirmationModal` и `DropdownButtonWithAction` показывают фокус при любом
1042
- его появлении, в том числе после клика мышью; остальные кнопки и ссылки —
1043
- только с клавиатуры. Стрелки месяцев и подпись месяца в календаре `PickDay`
1346
+ его появлении, в том числе после клика мышью. Карточки `SelectSingleCards`,
1347
+ галочки `SelectMultipleList`, остальные кнопки и ссылки показывают фокус
1348
+ только с клавиатуры. Стрелки месяцев и подпись месяца в календаре поля даты
1044
1349
  берут тот же вид, когда фокус в них с клавиатуры.
1045
1350
 
1046
1351
  Vimlike (Safari на iPhone, iPad и Mac) считает кнопкой любой элемент
@@ -1050,17 +1355,23 @@ Vimlike (Safari на iPhone, iPad и Mac) считает кнопкой любо
1050
1355
  бы тексту, иконке, у которой нет `click()`, и скрытой подписи, которую Vimlike
1051
1356
  считает невидимой. Поэтому содержимое кнопок и ссылок пакета — текст, иконки,
1052
1357
  скрытые подписи — с курсором `default` и не ловит указатель: мышь над ним
1053
- видит руку самой кнопки. По той же причине поле даты `SelectDateInterval`
1054
- лежит не внутри кнопки календаря, а под ней: поле внутри кнопки Vimlike
1055
- считал бы кнопкой вместо неё. В поле по-прежнему можно перейти Tab и набрать
1056
- дату.
1057
-
1058
- Подсказки Vimlike в открытых меню, списках `SelectSingle` и `SelectMultiple` и календарях
1059
- `SelectDateInterval` не видны: Vimlike рисует их под верхним слоем браузера,
1060
- в котором открываются эти панели. Vimium выводит свои подсказки в верхний
1061
- слой, и у него такой проблемы нет. В Vimlike панель открывают подсказкой её
1062
- кнопки, а дальше выбирают стрелками и Enter: пункт списка или меню, день
1063
- календаря.
1358
+ видит руку самой кнопки. По той же причине поле даты `SelectDateFilter`, `SelectDateForm`,
1359
+ `SelectDateIntervalFilter` и `SelectDateIntervalForm` лежит не внутри кнопки календаря, а под ней: поле
1360
+ внутри кнопки Vimlike считал бы кнопкой вместо неё. В поле по-прежнему можно
1361
+ перейти Tab и набрать дату.
1362
+
1363
+ У карточки `SelectSingleCards` одна подсказка расширения на всей карточке,
1364
+ у галочки `SelectMultipleList` — одна на пункт. Safari на Mac без настройки
1365
+ Tab по всем объектам пропускает переключатели и галочки, как и кнопки пакета.
1366
+
1367
+ Подсказки Vimlike в открытых меню, списках `SelectSingleFilter`,
1368
+ `SelectSingleForm`, `SelectMultipleFilter` и `SelectMultipleForm` и календарях
1369
+ `SelectDateFilter`, `SelectDateForm`, `SelectDateIntervalFilter`
1370
+ и `SelectDateIntervalForm` не видны: Vimlike рисует
1371
+ их под верхним слоем браузера, в котором открываются эти панели. Vimium
1372
+ выводит свои подсказки в верхний слой, и у него такой проблемы нет. В Vimlike
1373
+ панель открывают подсказкой её кнопки, а дальше выбирают стрелками и Enter:
1374
+ пункт списка или меню, день календаря.
1064
1375
 
1065
1376
  ## SSR
1066
1377
 
@@ -1071,8 +1382,10 @@ Inertia SSR), а серверная разметка гидратируется
1071
1382
  - `PageCard` на сервере рисует крестик, только если задан `fallback-url`:
1072
1383
  адрес возврата известен только в браузере, и крестик, ведущий на него,
1073
1384
  появляется после монтирования;
1074
- - `SelectDateInterval` загружает Pikaday в браузере при монтировании:
1075
- календари появляются, когда загрузка закончится;
1385
+ - `SelectDateFilter`, `SelectDateForm`, `SelectDateIntervalFilter`
1386
+ и `SelectDateIntervalForm` загружают Pikaday в браузере при монтировании:
1387
+ календари появляются, когда загрузка
1388
+ закончится;
1076
1389
  - остальные компоненты рендерятся на сервере так же, как в браузере.
1077
1390
 
1078
1391
  ## Правила API пакета
@@ -1083,12 +1396,13 @@ Inertia SSR), а серверная разметка гидратируется
1083
1396
  - Значение компонента передаётся через `v-model` (проп `modelValue` и
1084
1397
  событие `update:modelValue`) и не обязательно: компонент обязан
1085
1398
  отрисовываться без переданного значения. `required: true` оставляют
1086
- только там, без чего компонент бессмыслен, — например, у `items` в
1087
- `SelectSingle` или у `header` во всех фильтрах.
1399
+ только там, без чего компонент бессмыслен, — например, у `items`
1400
+ в `SelectSingleFilter` и `SelectSingleForm`, у `header` во всех фильтрах
1401
+ или у `label` полей формы.
1088
1402
  - Именованные модели (`v-model:date-from`, `v-model:date-to`, как у
1089
- `SelectDateInterval`) — исключение для компонентов с несколькими
1090
- значениями. У компонента с одним значением именованная модель не нужна:
1091
- для него это и есть обычный `v-model`.
1403
+ `SelectDateIntervalFilter` и `SelectDateIntervalForm`) — исключение для
1404
+ компонентов с несколькими значениями. У компонента с одним значением
1405
+ именованная модель не нужна: для него это и есть обычный `v-model`.
1092
1406
  - Булев проп называется `is*`, если описывает состояние компонента
1093
1407
  (`isRequired`, `isLoading`), и `with*`, если описывает необязательную
1094
1408
  возможность (`withPulse` у `Dot`).
@@ -1144,10 +1458,10 @@ Inertia SSR), а серверная разметка гидратируется
1144
1458
 
1145
1459
  Правило пакета — значение через `v-model` — относится к состоянию, которое
1146
1460
  компонент меняет сам: меню `DropdownButtonWithAction` закрывается по клику
1147
- вне, `SelectSingle` меняет выбор. `ConfirmationModal` свою видимость не меняет
1148
- никогда. Обе кнопки и Escape только сообщают родителю решение пользователя,
1149
- а закрыть модалку, оставить её открытой на время запроса или открыть
1150
- следующую — решает родитель.
1461
+ вне, `SelectSingleFilter` меняет выбор. `ConfirmationModal` свою видимость
1462
+ не меняет никогда. Обе кнопки и Escape только сообщают родителю решение
1463
+ пользователя, а закрыть модалку, оставить её открытой на время запроса или
1464
+ открыть следующую — решает родитель.
1151
1465
 
1152
1466
  `v-model` обещал бы двустороннюю связь, которой нет, поэтому видимость
1153
1467
  передаётся пропом `isOpen`.
@@ -1166,12 +1480,24 @@ Inertia SSR), а серверная разметка гидратируется
1166
1480
 
1167
1481
  npm run playground
1168
1482
 
1169
- Поднимает демо-страницы со всеми девятнадцатью компонентами в двух окружениях:
1483
+ Поднимает демо-страницы со всеми двадцатью шестью компонентами в двух окружениях:
1170
1484
  голом (без Tailwind и стилей приложения) и в окружении приложения (с
1171
1485
  Tailwind, `@tailwindcss/forms` и типографикой, как у потребителя). Это
1172
1486
  основной способ посмотреть, как компоненты выглядят и ведут себя, а не
1173
1487
  угадывать по исходникам или по этому README.
1174
1488
 
1489
+ ### Браузерные тесты
1490
+
1491
+ npm run test:browser
1492
+
1493
+ Собирает пакет и прогоняет Playground в Chromium и WebKit — движке Safari.
1494
+ Установленный Safari тесты не запускают. Запускать на macOS: WebKit на Linux
1495
+ фокусирует кнопки по клику иначе, чем Safari. Перед первым запуском:
1496
+
1497
+ npx playwright install chromium webkit
1498
+
1499
+ Тесты только локальные, в GitHub Actions они не входят.
1500
+
1175
1501
  ## Что пакет берёт у приложения
1176
1502
 
1177
1503
  Базовую типографику — семейство шрифта, размер, `line-height`. Он наследует её
@@ -1182,6 +1508,43 @@ Tailwind, `@tailwindcss/forms` и типографикой, как у потре
1182
1508
  Правила номера телефона в `RussianMobileFilter` — российские; язык текстов
1183
1509
  задаётся, см. «Языки».
1184
1510
 
1511
+ ## Обновление с 0.19
1512
+
1513
+ | Было | Стало |
1514
+ | --- | --- |
1515
+ | `<select-single class="h-18 border border-gray-200" header="…">` | `<select-single-filter header="…">` — высота и рамка встроены |
1516
+ | `<select-multiple class="h-18 border border-gray-200" header="…">` | `<select-multiple-filter header="…">` |
1517
+ | `<select-date-interval class="h-18 border border-gray-200" header="…">` | `<select-date-interval-filter header="…">` |
1518
+ | `"select-source": SelectSingle` (проект регистрирует компонент под своим именем тега) | `"select-source": SelectSingleFilter`; так же для `SelectMultiple` и `SelectDateInterval` |
1519
+ | `SelectSingle` в форме рядом с `FormInput` | `<select-single-form label="…">` |
1520
+ | `SelectMultiple` в форме | `<select-multiple-form label="…">` |
1521
+ | `SelectDateInterval` в форме | `<select-date-interval-form label="…">` |
1522
+
1523
+ `import { SelectSingle }` больше не работает: имена `SelectSingle`,
1524
+ `SelectMultiple` и `SelectDateInterval` из пакета убраны. Остальные классы
1525
+ на фильтрах (`ml-2` и т. п.) переносятся как есть.
1526
+
1527
+ В формах меняются и пропы: `header` становится `label`, `class="border
1528
+ border-gray-200"` убирается (на корне формы он обвёл бы подпись вместе с полем),
1529
+ а `isLoading` у форм нет.
1530
+
1531
+ Наведение мыши в списках и меню больше не двигает фокус: оно только подсвечивает
1532
+ пункт, фокус меняют клавиатура и клик.
1533
+
1534
+ Цветные пункты меню `DropdownButtonWithAction` и `HamburgerMenu` теперь всегда
1535
+ с фоном своего цвета: например, красный пункт «Удалить» / «Delete» в меню
1536
+ строки получает светло-красный фон.
1537
+
1538
+ В Safari фокус после закрытия меню `DropdownButtonWithAction` и `HamburgerMenu`
1539
+ — Escape, если фокус был в меню, выбор пункта мышью или клавиатурой, закрытие
1540
+ модалки, открытой пунктом, — возвращается на кнопку меню, как в Chrome.
1541
+
1542
+ `SelectDateFilter` и `SelectDateForm` — новые компоненты одной даты, у них
1543
+ нет предшественника: в таблице их нет.
1544
+
1545
+ `0.20.0` не подтянется по `^0.19.x`: для версий `0.x` знак `^` пропускает
1546
+ только патчи. Обновление — `npm install @boobooking/dashboard-ui-components@^0.20.0`.
1547
+
1185
1548
  ## Обновление с 0.15
1186
1549
 
1187
1550
  | Было | Стало |