@blackcube/aurelia-kit 1.0.0-rc4 → 1.0.0-rc6

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.
Files changed (56) hide show
  1. package/README.md +176 -44
  2. package/dist/index.es.js +1197 -757
  3. package/dist/index.es.js.map +1 -1
  4. package/dist/types/abstracts/components/abstract-dialog.d.ts +40 -0
  5. package/dist/types/abstracts/components/abstract-dialog.d.ts.map +1 -0
  6. package/dist/types/abstracts/components/abstract-dropdown.d.ts +105 -0
  7. package/dist/types/abstracts/components/abstract-dropdown.d.ts.map +1 -0
  8. package/dist/types/abstracts/components/abstract-pager.d.ts +51 -0
  9. package/dist/types/abstracts/components/abstract-pager.d.ts.map +1 -0
  10. package/dist/types/abstracts/components/abstract-toaster.d.ts +42 -0
  11. package/dist/types/abstracts/components/abstract-toaster.d.ts.map +1 -0
  12. package/dist/types/abstracts/components/index.d.ts +7 -0
  13. package/dist/types/abstracts/components/index.d.ts.map +1 -0
  14. package/dist/types/attributes/ajaxify-trigger.d.ts.map +1 -1
  15. package/dist/types/attributes/alert.d.ts.map +1 -1
  16. package/dist/types/attributes/badge.d.ts.map +1 -1
  17. package/dist/types/attributes/burger.d.ts.map +1 -1
  18. package/dist/types/attributes/dropdown.d.ts.map +1 -1
  19. package/dist/types/attributes/focus.d.ts.map +1 -1
  20. package/dist/types/attributes/menu.d.ts.map +1 -1
  21. package/dist/types/attributes/modal-trigger.d.ts +0 -1
  22. package/dist/types/attributes/modal-trigger.d.ts.map +1 -1
  23. package/dist/types/attributes/overlay.d.ts.map +1 -1
  24. package/dist/types/attributes/pager.d.ts.map +1 -1
  25. package/dist/types/attributes/password.d.ts.map +1 -1
  26. package/dist/types/attributes/popover-trigger.d.ts.map +1 -1
  27. package/dist/types/attributes/popover.d.ts.map +1 -1
  28. package/dist/types/attributes/profile.d.ts.map +1 -1
  29. package/dist/types/attributes/tabs.d.ts.map +1 -1
  30. package/dist/types/attributes/toast.d.ts +2 -2
  31. package/dist/types/attributes/toast.d.ts.map +1 -1
  32. package/dist/types/attributes/toaster-trigger.d.ts +3 -3
  33. package/dist/types/attributes/toaster-trigger.d.ts.map +1 -1
  34. package/dist/types/attributes/toaster.d.ts +2 -2
  35. package/dist/types/attributes/toaster.d.ts.map +1 -1
  36. package/dist/types/components/bleet-ajaxify.d.ts.map +1 -1
  37. package/dist/types/components/bleet-dialog.d.ts +13 -35
  38. package/dist/types/components/bleet-dialog.d.ts.map +1 -1
  39. package/dist/types/components/index.d.ts +0 -2
  40. package/dist/types/components/index.d.ts.map +1 -1
  41. package/dist/types/enums/event-aggregator.d.ts +6 -6
  42. package/dist/types/enums/event-aggregator.d.ts.map +1 -1
  43. package/dist/types/index.d.ts +6 -5
  44. package/dist/types/index.d.ts.map +1 -1
  45. package/dist/types/interfaces/dialog.d.ts +1 -2
  46. package/dist/types/interfaces/dialog.d.ts.map +1 -1
  47. package/dist/types/interfaces/event-aggregator.d.ts +4 -4
  48. package/dist/types/interfaces/event-aggregator.d.ts.map +1 -1
  49. package/dist/types/services/storage-service.d.ts.map +1 -1
  50. package/dist/types/services/transition-service.d.ts.map +1 -1
  51. package/dist/types/services/trap-focus-service.d.ts +17 -1
  52. package/dist/types/services/trap-focus-service.d.ts.map +1 -1
  53. package/dist/types/utils/toaster.d.ts +2 -2
  54. package/package.json +1 -1
  55. package/dist/types/components/bleet-toaster.d.ts +0 -43
  56. package/dist/types/components/bleet-toaster.d.ts.map +0 -1
package/README.md CHANGED
@@ -61,7 +61,35 @@ An element that must leave the layout when hidden also carries the HTML `hidden`
61
61
  (Tailwind's preflight turns it into `display: none`); the attribute toggles it, never a class.
62
62
 
63
63
  Attribute options use the Aurelia multi-binding syntax, as written by the PHP widgets:
64
- `bleet-toaster-trigger="color: success; title: Saved; content: Done; duration: 3000"`.
64
+ `bleet-toaster-trigger="level: success; title: Saved; content: Done; duration: 3000"`.
65
+
66
+ ## Abstract components
67
+
68
+ For a SPA, where the application renders its own markup, the kit gives the behavior of a component as an abstract
69
+ class, without markup: the application's element extends it and gives its template — its markup, its classes, its
70
+ texts, its icons. The abstract classes are not registered; the element that extends them is, by the application.
71
+
72
+ ```typescript
73
+ import { customElement } from 'aurelia';
74
+ import { AbstractDialog } from '@blackcube/aurelia-kit';
75
+
76
+ @customElement('app-drawer')
77
+ export class AppDrawer extends AbstractDialog {}
78
+ ```
79
+
80
+ - The bindables and the lifecycle of the abstract class are inherited: Aurelia reads the bindables along the prototype
81
+ chain. An element that overrides `attached()` or `detaching()` calls `super`.
82
+ - The template binds the members of the instance directly (`${title}`, `toast of toasts`) and gives the refs the names
83
+ the class reads (`ref="dialogElement"`).
84
+ - The state classes of the host (`data-<name>-show`, `data-<name>-hide`) and its attributes (`popover`) go on the root
85
+ `<template>` of the template: Aurelia carries them to the host.
86
+
87
+ | Class | Component |
88
+ |---|---|
89
+ | `AbstractDialog` | a dialog: modal, drawer — see [Dialogs](#dialogs) |
90
+ | `AbstractDropdown` | a dropdown: searchable, multiple — see [`AbstractDropdown`](#abstractdropdown-spa) |
91
+ | `AbstractPager` | the pagination of a list — see [`AbstractPager`](#abstractpager-spa) |
92
+ | `AbstractToaster` | the toaster — see [Toasts](#toasts) |
65
93
 
66
94
  ## Overlay
67
95
 
@@ -157,7 +185,6 @@ Behavior:
157
185
  ```typescript
158
186
  interface IDialogResponse {
159
187
  content?: string; // the whole HTML of the dialog
160
- color?: UiColor; // not used by the element: the server HTML carries its own colors
161
188
  icon?: string | null; // not used by the element: the server HTML carries its own icon
162
189
  action?: DialogAction; // Close closes the dialog, RefreshAndClose closes it and reloads the page
163
190
  toast?: IToast; // published on Channels.Toaster
@@ -167,30 +194,43 @@ interface IDialogResponse {
167
194
  }
168
195
  ```
169
196
 
170
- PHP side, `AureliaCommunication::dialogContent($content, $color)` builds the `content` / `color` part of it.
197
+ PHP side, `AureliaCommunication::dialogContent($content)` builds the `content` part of it: the look of the dialog is
198
+ in its HTML.
171
199
 
172
- **In a SPA**, the content is the application's: its frame and its view go in the default slot of `<bleet-dialog>`,
173
- written once in the shell, and the dialog is opened without `url`:
200
+ **In a SPA**, the frame is the application's: its element extends `AbstractDialog` (see
201
+ [Abstract components](#abstract-components)), its template holds the `<dialog ref="dialogElement">`, and the dialog is
202
+ opened without `url`:
203
+
204
+ ```typescript
205
+ @customElement('app-drawer')
206
+ export class AppDrawer extends AbstractDialog {}
207
+ ```
174
208
 
175
209
  ```html
176
- <bleet-dialog id="drawer"
177
- data-dialog-class="… translate-x-full"
178
- data-dialog-show="translate-x-0"
179
- data-dialog-hide="translate-x-full">
180
- <header …>${$host.title} <button type="button" data-dialog="close">…</button></header>
181
- <au-viewport name="drawer"></au-viewport>
182
- </bleet-dialog>
210
+ <template data-dialog-show="translate-x-0" data-dialog-hide="translate-x-full">
211
+ <dialog ref="dialogElement" class="… translate-x-full" aria-label.bind="title || null">
212
+ <header …>${title} <button type="button" data-dialog="close">…</button></header>
213
+ <au-slot></au-slot>
214
+ </dialog>
215
+ </template>
183
216
  ```
184
217
 
185
218
  ```typescript
186
- resolve(IEventAggregator).publish(Channels.Modal, <IModal>{ action: ModalAction.Open, id: 'drawer', title: 'Edit user', color: UiColor.Primary });
219
+ resolve(IEventAggregator).publish(Channels.Modal, <IModal>{ action: ModalAction.Open, id: 'drawer', title: 'Edit user' });
187
220
  ```
188
221
 
189
- - `Open` (or `Toggle` when closed) with neither `url` nor `content` opens the dialog on its default slot; its `title`
190
- and `color` are kept on the element for the frame (`$host.title`, `$host.color`) until it is closed. The `title` is
191
- also the accessible name of the `<dialog>` (`aria-label`).
192
- - A form of the default slot is not posted by the element: it belongs to the page that projects it.
222
+ | `AbstractDialog` | Meaning |
223
+ |---|---|
224
+ | `id` (bindable) | the id of the dialog on `Channels.Modal` |
225
+ | `title` | the one of the opening, kept until the dialog is closed |
226
+ | `dialogElement` | the `<dialog>` of the template (`ref`) |
227
+ | `show(data)`, `close()`, `clear()` | protected, to extend: an opening, a closing, what to clear once closed |
228
+
229
+ - `Open` (or `Toggle` when closed) opens the dialog; Escape, any `[data-dialog="close"]`, `Close` and `Toggle` close it
230
+ through the hide transition — a menu open inside (`aria-expanded`) is closed first.
231
+ - What the slot holds belongs to the page that projects it, its forms included.
193
232
  - `ModalStatus.Closed` with the `id` tells the page the dialog is closed (its route can be left).
233
+ - `<bleet-dialog>` itself extends `AbstractDialog`, with the server HTML on top of it.
194
234
 
195
235
  ## Ajaxify
196
236
 
@@ -245,7 +285,7 @@ Markup it expects:
245
285
  <div bleet-toaster popover="manual"
246
286
  class="fixed inset-auto top-4 right-0 z-70 m-0 p-0 pr-4 border-0 bg-transparent overflow-visible flex flex-col gap-4 pointer-events-none">
247
287
 
248
- <!-- one template per UiColor: primary, secondary, success, danger, warning, info, accent -->
288
+ <!-- one template per UiLevel: info, success, warning, danger -->
249
289
  <template data-toaster="success">
250
290
  <div class="… translate-x-full opacity-0 transition-all duration-500"
251
291
  data-toaster-show="translate-x-0 opacity-100"
@@ -271,24 +311,24 @@ box of a popover (`inset`, `margin`, `padding`, `border`, `background`, `overflo
271
311
 
272
312
  Behavior:
273
313
 
274
- - `ToasterAction.Add`: clones `template[data-toaster=<color>]`, puts the icon of
314
+ - `ToasterAction.Add`: clones `template[data-toaster=<level>]`, puts the icon of
275
315
  `template[data-toaster=icon-<icon>]` in the `icon` slot, fills `title` and `content`, appends the card to the
276
316
  container, then swaps its hide classes for its show classes. With `duration` > 0 the toast closes itself after
277
317
  `duration` ms; `0` keeps it until it is closed.
278
318
  - `ToasterAction.Remove` (or a click on `close`): swaps the show classes for the hide classes, waits for the end
279
319
  of the transition, removes the card.
280
- - A toast whose `id` is already displayed is ignored. A color without template is logged and ignored.
320
+ - A toast whose `id` is already displayed is ignored. A level without template is logged and ignored.
281
321
 
282
322
  Publishing a toast from TypeScript:
283
323
 
284
324
  ```typescript
285
325
  import { resolve, IEventAggregator } from 'aurelia';
286
- import { Channels, IToaster, ToasterAction, UiColor, UiToastIcon } from '@blackcube/aurelia-kit';
326
+ import { Channels, IToaster, ToasterAction, UiLevel, UiToastIcon } from '@blackcube/aurelia-kit';
287
327
 
288
328
  resolve(IEventAggregator).publish(Channels.Toaster, <IToaster>{
289
329
  action: ToasterAction.Add,
290
330
  toast: {
291
- color: UiColor.Success,
331
+ level: UiLevel.Success,
292
332
  icon: UiToastIcon.Success,
293
333
  title: 'Saved',
294
334
  content: 'The page has been saved.',
@@ -305,7 +345,7 @@ interface IToaster {
305
345
 
306
346
  interface IToast {
307
347
  id?: string; // generated when absent
308
- color: UiColor; // default Info
348
+ level: UiLevel; // default Info
309
349
  icon?: UiToastIcon; // default Info
310
350
  title?: string;
311
351
  content: string; // HTML
@@ -319,51 +359,55 @@ Publishes one toast when the page loads (after `DOMContentLoaded`). Rendered by
319
359
  as a hidden element:
320
360
 
321
361
  ```html
322
- <div hidden bleet-toast="color: success; icon: check-circle; title: Saved; content: Done; duration: 3000"></div>
362
+ <div hidden bleet-toast="level: success; icon: check-circle; title: Saved; content: Done; duration: 3000"></div>
323
363
  ```
324
364
 
325
- Options: `id`, `color`, `icon`, `title`, `content`, `duration` (same meaning as `IToast`).
365
+ Options: `id`, `level`, `icon`, `title`, `content`, `duration` (same meaning as `IToast`).
326
366
 
327
367
  ### `bleet-toaster-trigger`
328
368
 
329
369
  Publishes one toast on click. Rendered by `Bleet::toast()->…->trigger()` as attributes of another element:
330
370
 
331
371
  ```html
332
- <button bleet-toaster-trigger="color: success; content: Saved!">Save</button>
372
+ <button bleet-toaster-trigger="level: success; content: Saved!">Save</button>
333
373
  ```
334
374
 
335
- Options: `id`, `color`, `icon`, `title`, `content`, `duration`.
375
+ Options: `id`, `level`, `icon`, `title`, `content`, `duration`.
376
+
377
+ ### `AbstractToaster` (SPA)
336
378
 
337
- ### `<bleet-toaster>` (SPA)
379
+ The toaster of a SPA, where the application renders the markup: the same channel, the same payload and the same state
380
+ classes as the `bleet-toaster` attribute, each toast rendered by the template of the application's element, which
381
+ extends `AbstractToaster` (see [Abstract components](#abstract-components)). The host is the stack.
338
382
 
339
- The toaster of a SPA, where the application's templates render the markup: the same channel, the same payload and the
340
- same state classes as the `bleet-toaster` attribute, but each toast is rendered by Aurelia from the markup the
341
- application projects into the element. The element holds no markup and no class of its own: its template only repeats
342
- its default slot, once per toast, the toast exposed as `$host`.
383
+ ```typescript
384
+ @customElement('app-toaster')
385
+ export class AppToaster extends AbstractToaster {}
386
+ ```
343
387
 
344
388
  ```html
345
- <bleet-toaster popover="manual" class="fixed inset-auto top-4 right-0 … flex flex-col gap-4 pointer-events-none">
346
- <div data-toaster-id.bind="$host.id"
389
+ <template popover="manual" class="fixed inset-auto top-4 right-0 … flex flex-col gap-4 pointer-events-none">
390
+ <div repeat.for="toast of toasts" data-toaster-id.bind="toast.id"
347
391
  class="… translate-x-full opacity-0 transition-all duration-500"
348
392
  data-toaster-show="translate-x-0 opacity-100"
349
393
  data-toaster-hide="translate-x-full opacity-0">
350
- … ${$host.title} … <div innerhtml.bind="$host.content"></div> …
351
- <button type="button" click.trigger="$host.close($event)">…</button>
394
+ … ${toast.title} … <div innerhtml.bind="toast.content"></div> …
395
+ <button type="button" click.trigger="onClickClose($event, toast.id)">…</button>
352
396
  </div>
353
- </bleet-toaster>
397
+ </template>
354
398
  ```
355
399
 
356
- | `$host` (`IToastView`) | Meaning |
400
+ | `AbstractToaster` | Meaning |
357
401
  |---|---|
358
- | `id`, `color`, `icon`, `title`, `content`, `duration` | the published toast, with the defaults of the attribute |
359
- | `close(event)` | closes the toast (its button) |
402
+ | `toasts` | the toasts shown: `id`, `level`, `icon`, `title`, `content`, `duration`, with the defaults of the attribute |
403
+ | `onClickClose(event, id)` | closes the toast (its button) |
360
404
 
361
405
  Behavior:
362
406
 
363
- - The root of the projected toast carries `data-toaster-id="${$host.id}"`: once rendered, its hide classes are
364
- swapped for its show classes; `close()`, `ToasterAction.Remove` or the end of its `duration` swap them back, then the
407
+ - The root of each rendered toast carries `data-toaster-id="${toast.id}"`: once rendered, its hide classes are
408
+ swapped for its show classes; its button, `ToasterAction.Remove` or the end of its `duration` swap them back, then the
365
409
  toast leaves the list once the transition ends.
366
- - With `popover="manual"` on the element, it is shown again on each toast and hidden once the last one is gone, as the
410
+ - With `popover="manual"` on the host, it is shown again on each toast and hidden once the last one is gone, as the
367
411
  attribute's container.
368
412
  - The texts, the icons and the classes are the application's: its i18n, its icon component, its theme.
369
413
 
@@ -521,6 +565,43 @@ Behavior:
521
565
  select to `N`.
522
566
  - Changing the select clicks the matching button.
523
567
 
568
+ ### `AbstractPager` (SPA)
569
+
570
+ The pagination of a list in a SPA — yii-bleet's `Pager` widget with buttons instead of links: the application's element
571
+ extends `AbstractPager` (see [Abstract components](#abstract-components)) and renders the window of numbers around the
572
+ current page. The pagination is `@blackcube/aurelia-api`'s (`IPagination`), given as it is by the page; a page chosen is
573
+ announced on the host (`PagerEvent.Change`, `bleet-page`, its `detail` an `IPagerDetail`): the page writes it in its URL
574
+ and reloads its list, whose new pagination comes back.
575
+
576
+ ```typescript
577
+ @customElement('app-pager')
578
+ export class AppPager extends AbstractPager {}
579
+ ```
580
+
581
+ ```html
582
+ <template>
583
+ <nav if.bind="pagination.totalPages > 1">
584
+ <button if.bind="page > 1" type="button" click.trigger="onClickPage($event, page - 1)">…</button>
585
+ <button repeat.for="number of numbers" type="button" aria-current.bind="number === page ? 'page' : null"
586
+ click.trigger="onClickPage($event, number)">${number}</button>
587
+ <button if.bind="page < pagination.totalPages" type="button" click.trigger="onClickPage($event, page + 1)">…</button>
588
+ </nav>
589
+ </template>
590
+ ```
591
+
592
+ ```html
593
+ <app-pager pagination.bind="pagination" bleet-page.trigger="onChangePage($event)"></app-pager>
594
+ ```
595
+
596
+ | `AbstractPager` | Meaning |
597
+ |---|---|
598
+ | `pagination` | `IPagination`: `limit`, `currentPage`, `totalPages`, `totalCount` |
599
+ | `maxButtonCount` | how many numbers at most (10) |
600
+ | `page`, `numbers`, `begin`, `end` | the page shown, the window of numbers around it, the range of the items shown |
601
+ | `selectedPage` | two-way with a dropdown of the pages (a narrow screen): a choice in it goes to that page |
602
+ | `onClickPage(event, number)` | a number, previous, next |
603
+ | `refreshed()` | protected, to extend: what the element adds once the pages are computed again |
604
+
524
605
  ## Forms
525
606
 
526
607
  ### `bleet-password`
@@ -600,6 +681,56 @@ Behavior:
600
681
  is selected, the `count` template text beyond.
601
682
  - The panel does not open while the native select is disabled.
602
683
 
684
+ ### `AbstractDropdown` (SPA)
685
+
686
+ The dropdown of a SPA, driven by its data rather than by a native select: the application's element extends
687
+ `AbstractDropdown` (see [Abstract components](#abstract-components)) and renders its rows; the values are typed — an
688
+ id, an enum — and bound both ways.
689
+
690
+ ```typescript
691
+ @customElement('app-select')
692
+ export class AppSelect<T> extends AbstractDropdown<T> {}
693
+ ```
694
+
695
+ ```html
696
+ <template>
697
+ <button ref="button" type="button" aria-expanded.bind="open ? 'true' : 'false'" click.trigger="onClickToggle($event)">
698
+ ${selection.length > 0 ? selection[0].label : placeholder}
699
+ </button>
700
+ <div ref="panel" hidden.bind="open === false" role="listbox">
701
+ <input ref="search" value.bind="query">
702
+ <template repeat.for="group of groups">
703
+ <div if.bind="group.label">${group.label}</div>
704
+ <button repeat.for="row of group.rows" type="button" role="option" aria-selected.bind="row.selected ? 'true' : 'false'"
705
+ disabled.bind="row.disabled" click.trigger="onClickItem($event, row)">${row.label}</button>
706
+ </template>
707
+ <div if.bind="empty">…</div>
708
+ </div>
709
+ </template>
710
+ ```
711
+
712
+ ```html
713
+ <app-select options.bind="schools" value.two-way="model.schoolId" placeholder="Choose"></app-select>
714
+ <app-select multiple.bind="true" options.bind="roles" values.two-way="model.roles"></app-select>
715
+ ```
716
+
717
+ | `AbstractDropdown` | Meaning |
718
+ |---|---|
719
+ | `options` | `IDropdownOption[]`: `value`, `label`, `group`, `disabled` |
720
+ | `value`, `values` | two-way: the choice, or the choices with `multiple` |
721
+ | `multiple`, `disabled`, `placeholder` | bindables |
722
+ | `open`, `query`, `empty` | the panel is open; the text searched (the search field binds it); nothing matches |
723
+ | `groups`, `selection` | the rows matching the query by group (`IDropdownRow`: `value`, `label`, `disabled`, `selected`); the rows chosen |
724
+ | `button`, `panel`, `search` | the button, the panel and the optional search field of the template (`ref`) |
725
+ | `onClickToggle(event)`, `onClickItem(event, row)`, `onClickRemove(event, row)` | the button, a row, the remove control of a tag |
726
+
727
+ - A single choice sets `value` and closes the panel; with a `placeholder`, a first row sets it back to `null`. A
728
+ multiple one toggles in `values`, the panel staying open.
729
+ - The rows are built once per set of options; a choice changes their state in place, the rendered rows stay.
730
+ - Open, the focus is trapped in the panel (`ITrapFocusService`): Tab loops, the arrows move, Escape and a click outside
731
+ close it. It opens on the search field, else on its selection, scrolled into view.
732
+ - A remove control inside the button is not a `<button>`: the HTML parser closes a button at the next one.
733
+
603
734
  ### `bleet-focus`
604
735
 
605
736
  An element that takes the focus as it appears — a field or a message shown later (a condition of the page, a fragment
@@ -623,7 +754,8 @@ resolve(IEventAggregator).publish(Channels.Upload, <IUpload>{ action: UploadActi
623
754
  ## Exports
624
755
 
625
756
  Attributes: `BleetToasterCustomAttribute`, `BleetToastCustomAttribute`, `BleetToasterTriggerCustomAttribute`,
626
- and the attributes of the other widgets. Enums: `Channels`, `ToasterAction`, `ToasterStatus`, `UiColor`,
757
+ and the attributes of the other widgets. Abstract components: `AbstractDialog`, `AbstractDropdown`, `AbstractPager` (its `PagerEvent`, `IPagerDetail`),
758
+ `AbstractToaster`. Enums: `Channels`, `ToasterAction`, `ToasterStatus`, `UiLevel`,
627
759
  `UiToastIcon`, `UiIcon`, and the actions and statuses of the other channels. Interfaces: `IToaster`, `IToast`,
628
760
  and the payloads of the other channels. Services: `IStorageService`, `ITransitionService`, `ITrapFocusService`.
629
761