@boobooking/dashboard-ui-components 0.12.0 → 0.13.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
@@ -15,16 +15,19 @@ import '@boobooking/dashboard-ui-components/style.css'
15
15
 
16
16
  ### Подключение к приложению
17
17
 
18
- Плагин `dashboardUi` задаёт язык и переход по ссылкам пакета. Оба параметра
19
- необязательны; без плагина компоненты русскоязычные, а ссылки — обычные `<a>`.
18
+ Плагин `dashboardUi` задаёт язык, переход по ссылкам пакета и адрес
19
+ страницы на экране. Все параметры необязательны; без плагина компоненты
20
+ русскоязычные, ссылки — обычные `<a>`, а `PageCard` закрывается только на
21
+ `fallback-url`.
20
22
 
21
23
  ```js
22
24
  import { dashboardUi } from '@boobooking/dashboard-ui-components'
23
- import { router } from '@inertiajs/vue3'
25
+ import { router, usePage } from '@inertiajs/vue3'
24
26
 
25
27
  createApp(App).use(dashboardUi, {
26
28
  lang: 'en',
27
29
  navigate: (href) => router.visit(href),
30
+ currentUrl: () => usePage().url,
28
31
  })
29
32
  ```
30
33
 
@@ -35,6 +38,18 @@ createApp(App).use(dashboardUi, {
35
38
  настоящий `<a href>` и отдают `navigate` только обычный клик левой кнопкой;
36
39
  клики с Ctrl/Cmd/Shift/Alt, средней кнопкой и ссылки с `target` остаются
37
40
  браузеру. Без `navigate` браузер идёт по ссылке сам.
41
+ - `currentUrl()` — адрес страницы на экране, по нему `PageCard` знает,
42
+ откуда его открыли. Для Inertia — `() => usePage().url` (проверено на
43
+ `@inertiajs/vue3` 3.6.1). Договор для другого роутера: функция читает
44
+ реактивное состояние роутера; её значение меняется при каждом показе
45
+ страницы с новым адресом, в том числе при замене записи истории,
46
+ «Назад»/«Вперёд» и первой загрузке, и меняется до создания компонентов
47
+ новой страницы; неуспешный или отменённый переход значения не меняет;
48
+ пока роутер не готов, функция возвращает `null` или `undefined`.
49
+ У Vue Router, например, до первой навигации `currentRoute` —
50
+ `START_LOCATION` с `fullPath === '/'`, и его надо отдавать как `null`.
51
+ Плагин следит за адресом только в браузере и перестаёт при
52
+ размонтировании приложения.
38
53
 
39
54
  `navigate` получает адрес ровно таким, каким он лежит в компоненте:
40
55
  пагинация `DataTable` отдаёт `links` Laravel как есть, а это абсолютные URL. С Vue
@@ -421,64 +436,137 @@ ConfirmationModal нет v-model».
421
436
 
422
437
  ### PageCard
423
438
 
424
- Карточка отдельной страницы — формы или просмотра записи — по центру с
425
- крестиком «назад по истории».
439
+ Карточка отдельной страницы — формы или просмотра записи — по центру
440
+ с крестиком, который ведёт туда, откуда карточку открыли.
426
441
 
427
- <page-card class="px-4 pt-4 sm:px-6 sm:pt-6">
442
+ <page-card class="px-4 pt-4 sm:px-6 sm:pt-6" :fallback-url="route('users')">
428
443
  <h3 class="pr-(--bb-closer-space) text-lg font-medium">Создание администратора</h3>
429
444
  …поля формы…
430
445
  </page-card>
431
446
 
432
447
  Страница просмотра, у секций которой свои отступы:
433
448
 
434
- <page-card>
449
+ <page-card :fallback-url="route('payments')">
435
450
  <div class="px-4 py-5 border-b border-gray-200 sm:px-6">
436
451
  <h3 class="pr-(--bb-closer-space) text-lg font-medium">{{ name }}</h3>
437
452
  </div>
438
453
  <div class="overflow-hidden sm:rounded-b-lg">…строки…</div>
439
454
  </page-card>
440
455
 
441
- Карточка — `relative my-6 mx-auto bg-white shadow-xl sm:max-w-xl
442
- sm:rounded-lg`, `box-sizing: border-box`. Отступов у неё нет: форма передаёт
443
- их классом на корень, страница просмотра — не передаёт. Классы и атрибуты
444
- приложения попадают на корень и сильнее классов пакета. Ресет пакета на
445
- карточку и её содержимое не распространяется: разметка страницы, в том числе
446
- поля `@tailwindcss/forms`, выглядит так же, как вне карточки.
447
-
448
- Крестик показан, если в истории вкладки больше одной записи
449
- (`history.length > 1`, значение читается один раз после монтирования), и по
450
- клику возвращает назад (`history.back()`). При серверном рендеринге (SSR)
451
- сервер историю вкладки не знает и отдаёт карточку без крестика: крестик
452
- появляется сразу после гидратации, и на экранах уже `md` заголовок в этот
453
- момент сдвигается, освобождая под него место. Без SSR крестик появляется до
454
- первой отрисовки. `history.length` считает и записи впереди текущей, поэтому
455
- это не гарантия, что назад есть куда. От `md` крестик стоит
456
- снаружи карточки, на `1rem` правее её края; ниже `md` — в её правом верхнем
457
- углу. Порог рассчитан на карточку по центру области на всю ширину страницы: в
458
- узкой колонке или рядом с боковой панелью места снаружи может не хватить. Он
459
- рассчитан и на ширину карточки по умолчанию (`max-w-xl`, 36rem): если передать
460
- классом на корень более широкую, места снаружи тоже может не хватить.
456
+ **Куда ведёт крестик.** Плагин `dashboardUi` с `currentUrl` (см.
457
+ «Подключение к приложению») помнит адрес страницы, которая была на экране
458
+ перед карточкой, со всеми её фильтрами и номером страницы, и крестик
459
+ ведёт ровно туда. Адрес не попадает ни в адрес страницы, ни в хранилища
460
+ браузера, ни в историю: он живёт в памяти приложения. «Как было» — это
461
+ адрес: прокрутку, несохранённый ввод и раскрытые элементы
462
+ страницы-источника карточка не возвращает.
463
+
464
+ Если адреса нет — карточку открыли в новой вкладке, прямой ссылкой, после
465
+ F5 или в приложении без `currentUrl`, — крестик ведёт на `fallback-url`.
466
+ Без `fallback-url` крестика нет. Истории браузера карточка не касается.
467
+
468
+ **Окна.** Открытая карточка — окно. Карточка, открытая со страницы
469
+ другой карточки (например, форма с таба), — вложенное окно: её крестик
470
+ ведёт на страницу, с которой её открыли, а крестик внешней карточки —
471
+ по-прежнему туда, откуда открыли её. Окно закрывается, когда показана
472
+ страница, куда оно возвращает: крестиком, «Отменой», после успешного
473
+ действия или кнопкой «Назад» браузера.
474
+
475
+ **Карточка из нескольких страниц** (табы) — постоянный макет этих страниц
476
+ Inertia с общим ключом окна:
477
+
478
+ export default {
479
+ layout: (props) => [PageCard, {
480
+ width: '7xl',
481
+ windowKey: `group:${props.group.data.uuid}`,
482
+ fallbackUrl: route('groups'),
483
+ class: 'px-4 py-4 sm:px-6 sm:py-6',
484
+ }],
485
+ }
486
+
487
+ `layout` — стрелочная функция одного аргумента или кортеж: обычную
488
+ функцию Inertia примет за компонент. Пока соседние страницы объявляют тот
489
+ же макет, карточка не пересоздаётся, и смена таба, фильтров и страницы
490
+ таблицы окна не меняет. Ключ окна по умолчанию — путь страницы без query:
491
+ отдельной странице-карточке его задавать не нужно, а если роутер
492
+ переиспользовал её для другой записи (`/users/1/edit` → `/users/2/edit`),
493
+ у неё новое окно. Ключ меняется только вместе со сменой страницы: смена
494
+ без неё оставляет карточку в прежнем окне и пишет предупреждение
495
+ в консоль. Рецепт проверен на `@inertiajs/vue3` 3.6.1.
496
+
497
+ **«Отмена» и закрытие из кода.** `close()` делает то же, что крестик.
498
+ Он доступен пропом слота по умолчанию и методом компонента:
499
+
500
+ <page-card ref="card" v-slot="{ close }" :fallback-url="route('users')">
501
+ …
502
+ <button type="button" @click="close">Отмена</button>
503
+ </page-card>
504
+
505
+ // после успешного сохранения
506
+ this.$refs.card.close()
507
+
508
+ `close()` переходит через `navigate` плагина, без него — полной загрузкой
509
+ страницы. Без адреса возврата и `fallback-url` он ничего не делает.
510
+
511
+ **Ширина и крестик.** От `width` зависят ширина карточки и порог, от
512
+ которого крестик стоит снаружи, на `1rem` правее её края; ниже порога —
513
+ в правом верхнем углу:
514
+
515
+ | `width` | Ширина от `sm` | Крестик снаружи |
516
+ | --- | --- | --- |
517
+ | `xl` (по умолчанию) | `max-w-xl` (36rem) | от `md` |
518
+ | `4xl` | `max-w-4xl` (56rem) | от `lg` |
519
+ | `7xl` | `max-w-7xl` (80rem) | от `2xl` |
520
+
521
+ Пороги рассчитаны на карточку по центру области на всю ширину страницы:
522
+ в узкой колонке или рядом с боковой панелью места снаружи может не
523
+ хватить.
461
524
 
462
525
  Заголовок оставляет место под крестик правым отступом из переменной
463
- `--bb-closer-space`: `3.5rem`, пока крестик в углу, `0` — когда он снаружи или
464
- его нет. В Tailwind это `pr-(--bb-closer-space)`; без Tailwind 4 — обычный CSS
465
- `padding-right: var(--bb-closer-space)`, а в Tailwind 3 —
526
+ `--bb-closer-space`: `3.5rem`, пока крестик в углу, `0` — когда он снаружи
527
+ или его нет. В Tailwind это `pr-(--bb-closer-space)`; без Tailwind 4 —
528
+ обычный CSS `padding-right: var(--bb-closer-space)`, а в Tailwind 3 —
466
529
  `pr-[var(--bb-closer-space)]`. Вне `PageCard` отступ равен нулю.
467
530
 
468
- Карточка не обрезает содержимое, как у `ConfirmationModal`: выпадающие списки
469
- и календари могут выходить за её край. Блок со своим фоном у края карточки
470
- скругляет свои углы сам — например, нижний блок строк:
531
+ **Атрибуты.** Карточка — `relative my-6 mx-auto bg-white shadow-xl
532
+ sm:rounded-lg`, `box-sizing: border-box`. Отступов у неё нет: форма
533
+ передаёт их классом на корень, страница просмотра — не передаёт. На корень
534
+ попадают `class`, `style`, `data-*` и `aria-*` приложения; классы
535
+ приложения сильнее классов пакета. Остальные атрибуты, в том числе `id`,
536
+ не переносятся: в роли макета карточка получает атрибутами пропы
537
+ страницы. Пропы страницы с именами пропов карточки — `lang`, `width`,
538
+ `fallbackUrl`, `windowKey` — приходят ей пропами, а не атрибутами; кортеж
539
+ макета перекрывает только те, что задаёт сам. Ресет пакета на карточку и её содержимое не распространяется:
540
+ разметка страницы, в том числе поля `@tailwindcss/forms`, выглядит так же,
541
+ как вне карточки.
542
+
543
+ Карточка не обрезает содержимое, как у `ConfirmationModal`: выпадающие
544
+ списки и календари могут выходить за её край. Блок со своим фоном у края
545
+ карточки скругляет свои углы сам — например, нижний блок строк:
471
546
  `overflow-hidden sm:rounded-b-lg`.
472
547
 
473
- Крестик доступен с клавиатуры: Tab, Enter, пробел; в порядке табуляции крестик
474
- идёт после содержимого карточки; при фокусе с клавиатуры
475
- вокруг него кольцо. Доступное имя — «Назад» / «Back».
548
+ Крестик доступен с клавиатуры: Tab, Enter, пробел; в порядке табуляции
549
+ крестик идёт после содержимого карточки; при фокусе с клавиатуры вокруг
550
+ него кольцо. Доступное имя — «Назад» / «Back».
476
551
 
477
552
  | Проп | Тип | По умолчанию | Описание |
478
553
  | --- | --- | --- | --- |
554
+ | `width` | `String` | `"xl"` | `"xl"`, `"4xl"` или `"7xl"` |
555
+ | `fallback-url` | `String` | `null` | куда закрываться без адреса возврата; `""` — как `null` |
556
+ | `window-key` | `String` | путь страницы | общий ключ окна карточки из нескольких страниц |
479
557
  | `lang` | `String` | язык плагина | `"ru"` или `"en"` |
480
558
 
481
- Событий нет.
559
+ Событий нет. Проп слота по умолчанию — `close`.
560
+
561
+ Ограничения:
562
+
563
+ - память плагина не переживает F5 и новую вкладку: тогда работает
564
+ `fallback-url`;
565
+ - адреса сравниваются строкой: равнозначный адрес с другим порядком
566
+ параметров или с лишним `page=1` — другой адрес;
567
+ - если вернуться в карточку «Назад» или «Вперёд» после ухода из неё не
568
+ через крестик, адрес возврата — страница, с которой пришли в этот раз;
569
+ - на одной странице — одна карточка.
482
570
 
483
571
  ### NotificationMessage
484
572
 
@@ -549,8 +637,9 @@ sm:rounded-lg`, `box-sizing: border-box`. Отступов у неё нет: ф
549
637
  Inertia SSR), а серверная разметка гидратируется без расхождений. К API
550
638
  браузера компоненты обращаются только после монтирования, поэтому:
551
639
 
552
- - `PageCard` на сервере рисует карточку без крестика: история вкладки
553
- известна только в браузере. Крестик появляется сразу после гидратации;
640
+ - `PageCard` на сервере рисует крестик, только если задан `fallback-url`:
641
+ адрес возврата известен только в браузере, и крестик, ведущий на него,
642
+ появляется после монтирования;
554
643
  - `PickDay` загружает Pikaday в браузере при монтировании: календарь
555
644
  появляется, когда загрузка закончится;
556
645
  - остальные компоненты рендерятся на сервере так же, как в браузере.
@@ -650,6 +739,15 @@ Tailwind, `@tailwindcss/forms` и типографикой, как у потре
650
739
  Правила номера телефона в `RussianMobileFilter` — российские; язык текстов
651
740
  задаётся, см. «Языки».
652
741
 
742
+ ## Обновление с 0.12
743
+
744
+ - Крестик `PageCard` больше не ходит по истории: подключите `currentUrl`
745
+ к плагину и дайте карточкам `fallback-url`. Без них крестика нет.
746
+ - На корень `PageCard` переносятся только `class`, `style`, `data-*`
747
+ и `aria-*`.
748
+ - Карточка из нескольких страниц объявляет `PageCard` постоянным макетом
749
+ с `window-key` (см. раздел `PageCard`).
750
+
653
751
  ## Обновление с 0.11
654
752
 
655
753
  - `Pagination` больше не экспортируется. Страница, импортирующая её