@joanroucoux/cairn-ui 0.8.2 → 0.9.1

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 (124) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/fesm2022/joanroucoux-cairn-ui-action-bar.mjs +57 -53
  3. package/fesm2022/joanroucoux-cairn-ui-action-bar.mjs.map +1 -1
  4. package/fesm2022/joanroucoux-cairn-ui-alert.mjs +155 -47
  5. package/fesm2022/joanroucoux-cairn-ui-alert.mjs.map +1 -1
  6. package/fesm2022/joanroucoux-cairn-ui-amount.mjs +220 -110
  7. package/fesm2022/joanroucoux-cairn-ui-amount.mjs.map +1 -1
  8. package/fesm2022/joanroucoux-cairn-ui-async.mjs +392 -216
  9. package/fesm2022/joanroucoux-cairn-ui-async.mjs.map +1 -1
  10. package/fesm2022/joanroucoux-cairn-ui-avatar.mjs +145 -68
  11. package/fesm2022/joanroucoux-cairn-ui-avatar.mjs.map +1 -1
  12. package/fesm2022/joanroucoux-cairn-ui-back-link.mjs +87 -47
  13. package/fesm2022/joanroucoux-cairn-ui-back-link.mjs.map +1 -1
  14. package/fesm2022/joanroucoux-cairn-ui-badge.mjs +83 -43
  15. package/fesm2022/joanroucoux-cairn-ui-badge.mjs.map +1 -1
  16. package/fesm2022/joanroucoux-cairn-ui-button.mjs +184 -104
  17. package/fesm2022/joanroucoux-cairn-ui-button.mjs.map +1 -1
  18. package/fesm2022/joanroucoux-cairn-ui-card.mjs +232 -137
  19. package/fesm2022/joanroucoux-cairn-ui-card.mjs.map +1 -1
  20. package/fesm2022/joanroucoux-cairn-ui-choice-chips.mjs +298 -102
  21. package/fesm2022/joanroucoux-cairn-ui-choice-chips.mjs.map +1 -1
  22. package/fesm2022/joanroucoux-cairn-ui-control.mjs +4 -17
  23. package/fesm2022/joanroucoux-cairn-ui-control.mjs.map +1 -1
  24. package/fesm2022/joanroucoux-cairn-ui-delta.mjs +150 -83
  25. package/fesm2022/joanroucoux-cairn-ui-delta.mjs.map +1 -1
  26. package/fesm2022/joanroucoux-cairn-ui-dialog.mjs +508 -471
  27. package/fesm2022/joanroucoux-cairn-ui-dialog.mjs.map +1 -1
  28. package/fesm2022/joanroucoux-cairn-ui-donut.mjs +255 -157
  29. package/fesm2022/joanroucoux-cairn-ui-donut.mjs.map +1 -1
  30. package/fesm2022/joanroucoux-cairn-ui-drawer.mjs +303 -0
  31. package/fesm2022/joanroucoux-cairn-ui-drawer.mjs.map +1 -0
  32. package/fesm2022/joanroucoux-cairn-ui-empty.mjs +76 -35
  33. package/fesm2022/joanroucoux-cairn-ui-empty.mjs.map +1 -1
  34. package/fesm2022/joanroucoux-cairn-ui-external-link.mjs +40 -31
  35. package/fesm2022/joanroucoux-cairn-ui-external-link.mjs.map +1 -1
  36. package/fesm2022/joanroucoux-cairn-ui-fact.mjs +188 -79
  37. package/fesm2022/joanroucoux-cairn-ui-fact.mjs.map +1 -1
  38. package/fesm2022/joanroucoux-cairn-ui-field.mjs +309 -173
  39. package/fesm2022/joanroucoux-cairn-ui-field.mjs.map +1 -1
  40. package/fesm2022/joanroucoux-cairn-ui-filter-chips.mjs +165 -87
  41. package/fesm2022/joanroucoux-cairn-ui-filter-chips.mjs.map +1 -1
  42. package/fesm2022/joanroucoux-cairn-ui-group-header.mjs +269 -0
  43. package/fesm2022/joanroucoux-cairn-ui-group-header.mjs.map +1 -0
  44. package/fesm2022/joanroucoux-cairn-ui-input.mjs +205 -85
  45. package/fesm2022/joanroucoux-cairn-ui-input.mjs.map +1 -1
  46. package/fesm2022/joanroucoux-cairn-ui-line-chart.mjs +838 -512
  47. package/fesm2022/joanroucoux-cairn-ui-line-chart.mjs.map +1 -1
  48. package/fesm2022/joanroucoux-cairn-ui-menu.mjs +401 -225
  49. package/fesm2022/joanroucoux-cairn-ui-menu.mjs.map +1 -1
  50. package/fesm2022/joanroucoux-cairn-ui-meter.mjs +143 -57
  51. package/fesm2022/joanroucoux-cairn-ui-meter.mjs.map +1 -1
  52. package/fesm2022/joanroucoux-cairn-ui-motion.mjs +367 -399
  53. package/fesm2022/joanroucoux-cairn-ui-motion.mjs.map +1 -1
  54. package/fesm2022/joanroucoux-cairn-ui-nav-item.mjs +73 -44
  55. package/fesm2022/joanroucoux-cairn-ui-nav-item.mjs.map +1 -1
  56. package/fesm2022/joanroucoux-cairn-ui-result-group.mjs +191 -0
  57. package/fesm2022/joanroucoux-cairn-ui-result-group.mjs.map +1 -0
  58. package/fesm2022/joanroucoux-cairn-ui-row.mjs +408 -146
  59. package/fesm2022/joanroucoux-cairn-ui-row.mjs.map +1 -1
  60. package/fesm2022/joanroucoux-cairn-ui-segmented.mjs +183 -81
  61. package/fesm2022/joanroucoux-cairn-ui-segmented.mjs.map +1 -1
  62. package/fesm2022/joanroucoux-cairn-ui-select-pill.mjs +270 -0
  63. package/fesm2022/joanroucoux-cairn-ui-select-pill.mjs.map +1 -0
  64. package/fesm2022/joanroucoux-cairn-ui-select.mjs +121 -67
  65. package/fesm2022/joanroucoux-cairn-ui-select.mjs.map +1 -1
  66. package/fesm2022/joanroucoux-cairn-ui-skeleton.mjs +129 -51
  67. package/fesm2022/joanroucoux-cairn-ui-skeleton.mjs.map +1 -1
  68. package/fesm2022/joanroucoux-cairn-ui-stale-link.mjs +80 -39
  69. package/fesm2022/joanroucoux-cairn-ui-stale-link.mjs.map +1 -1
  70. package/fesm2022/joanroucoux-cairn-ui-stat.mjs +85 -55
  71. package/fesm2022/joanroucoux-cairn-ui-stat.mjs.map +1 -1
  72. package/fesm2022/joanroucoux-cairn-ui-switch.mjs +48 -35
  73. package/fesm2022/joanroucoux-cairn-ui-switch.mjs.map +1 -1
  74. package/fesm2022/joanroucoux-cairn-ui-tab-bar.mjs +113 -69
  75. package/fesm2022/joanroucoux-cairn-ui-tab-bar.mjs.map +1 -1
  76. package/fesm2022/joanroucoux-cairn-ui-table.mjs +1036 -310
  77. package/fesm2022/joanroucoux-cairn-ui-table.mjs.map +1 -1
  78. package/fesm2022/joanroucoux-cairn-ui-toast.mjs +240 -127
  79. package/fesm2022/joanroucoux-cairn-ui-toast.mjs.map +1 -1
  80. package/fesm2022/joanroucoux-cairn-ui.mjs +0 -4
  81. package/package.json +17 -1
  82. package/styles/motion.css +1 -13
  83. package/styles/tokens.css +35 -64
  84. package/types/joanroucoux-cairn-ui-action-bar.d.ts +9 -14
  85. package/types/joanroucoux-cairn-ui-alert.d.ts +29 -15
  86. package/types/joanroucoux-cairn-ui-amount.d.ts +64 -32
  87. package/types/joanroucoux-cairn-ui-async.d.ts +85 -38
  88. package/types/joanroucoux-cairn-ui-avatar.d.ts +34 -22
  89. package/types/joanroucoux-cairn-ui-back-link.d.ts +20 -15
  90. package/types/joanroucoux-cairn-ui-badge.d.ts +22 -14
  91. package/types/joanroucoux-cairn-ui-button.d.ts +36 -18
  92. package/types/joanroucoux-cairn-ui-card.d.ts +48 -23
  93. package/types/joanroucoux-cairn-ui-choice-chips.d.ts +91 -35
  94. package/types/joanroucoux-cairn-ui-control.d.ts +9 -18
  95. package/types/joanroucoux-cairn-ui-delta.d.ts +46 -24
  96. package/types/joanroucoux-cairn-ui-dialog.d.ts +124 -57
  97. package/types/joanroucoux-cairn-ui-donut.d.ts +83 -46
  98. package/types/joanroucoux-cairn-ui-drawer.d.ts +73 -0
  99. package/types/joanroucoux-cairn-ui-empty.d.ts +20 -13
  100. package/types/joanroucoux-cairn-ui-external-link.d.ts +6 -10
  101. package/types/joanroucoux-cairn-ui-fact.d.ts +49 -25
  102. package/types/joanroucoux-cairn-ui-field.d.ts +72 -49
  103. package/types/joanroucoux-cairn-ui-filter-chips.d.ts +35 -20
  104. package/types/joanroucoux-cairn-ui-group-header.d.ts +58 -0
  105. package/types/joanroucoux-cairn-ui-input.d.ts +59 -37
  106. package/types/joanroucoux-cairn-ui-line-chart.d.ts +199 -89
  107. package/types/joanroucoux-cairn-ui-menu.d.ts +81 -44
  108. package/types/joanroucoux-cairn-ui-meter.d.ts +44 -22
  109. package/types/joanroucoux-cairn-ui-motion.d.ts +61 -75
  110. package/types/joanroucoux-cairn-ui-nav-item.d.ts +15 -13
  111. package/types/joanroucoux-cairn-ui-result-group.d.ts +52 -0
  112. package/types/joanroucoux-cairn-ui-row.d.ts +92 -37
  113. package/types/joanroucoux-cairn-ui-segmented.d.ts +51 -27
  114. package/types/joanroucoux-cairn-ui-select-pill.d.ts +59 -0
  115. package/types/joanroucoux-cairn-ui-select.d.ts +28 -18
  116. package/types/joanroucoux-cairn-ui-skeleton.d.ts +35 -18
  117. package/types/joanroucoux-cairn-ui-stale-link.d.ts +23 -16
  118. package/types/joanroucoux-cairn-ui-stat.d.ts +26 -21
  119. package/types/joanroucoux-cairn-ui-switch.d.ts +7 -11
  120. package/types/joanroucoux-cairn-ui-tab-bar.d.ts +20 -17
  121. package/types/joanroucoux-cairn-ui-table.d.ts +251 -89
  122. package/types/joanroucoux-cairn-ui-toast.d.ts +46 -36
  123. package/types/joanroucoux-cairn-ui.d.ts +1 -2
  124. package/fesm2022/joanroucoux-cairn-ui.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,118 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.1
4
+
5
+ ### Fixed
6
+
7
+ - `ui-drawer`, `ui-dialog`: the `<dialog>` element no longer draws the browser's default focus outline when it
8
+ takes focus itself, as it does on a drawer that opens on page load with nothing focused before it. Keyboard focus
9
+ on the controls inside keeps the library ring.
10
+
11
+ ### Added
12
+
13
+ - `uiRowGroup` (`@joanroucoux/cairn-ui/row`): groups link rows (`ui-row` with `trailing="chevron"`) under a
14
+ hairline, with a 4px lead, as the "Produit structuré" and "Saisir à la main" links under a search list.
15
+ - `ui-select-pill`: a `disabled` input. The trigger is `disabled` and `aria-disabled`, nothing opens, the clear cross
16
+ is not drawn (the chevron stays, even when `active`), and the pill is dimmed to 40 % like a disabled button.
17
+
18
+ ## 0.9.0
19
+
20
+ ### Breaking
21
+
22
+ - `ui-dialog`: the `layout` input (`trade`, `form`, `list`, `confirm`) is replaced by `variant` (`default` |
23
+ `confirm`) and `sheet` (`fit` | `full`). `DIALOG_LAYOUTS` and `DialogLayout` become `DIALOG_VARIANTS`,
24
+ `DIALOG_SHEETS`, `DialogVariant` and `DialogSheet`.
25
+ - Migration: `layout="trade"` and `layout="form"` become the default (remove the attribute); `layout="list"` becomes
26
+ `sheet="full"`; `layout="confirm"` becomes `variant="confirm"`. A list dialog was anchored 96px from the top on a
27
+ desktop: it is now centred like every dialog.
28
+ - `ui-filter-chips`: `role="group"` and `aria-label` move from the host to an inner wrapper around the chips, so a
29
+ leading element sits outside the group.
30
+ - Migration: a selector or a test query on `ui-filter-chips[role=group]` targets the inner `div[role=group]` instead;
31
+ `getByRole('group', { name })` keeps working.
32
+ - `styles/motion.css` no longer ships `ui-enter-panel` nor its `cairn-panel-in` keyframes (an 8px slide for a detail
33
+ panel beside a list). The detail now opens in `ui-drawer`, which plays its own motion.
34
+ - Migration: replace the side panel animated with `animate.enter="ui-enter-panel"` by a `ui-drawer`; for any other
35
+ element, use `ui-enter-fade-up` or `ui-enter-fade`.
36
+ - `ui-toaster`: the message text sits in its own `<span>`, beside the icon, inside the surface.
37
+ - Migration: `getByText(message)` now returns that `<span>`, not the surface; a test that checked the surface through
38
+ it (its classes, its position) reads `getByText(message).parentElement` instead.
39
+
40
+ ### Added
41
+
42
+ - `UiToasts.showError(message, closeLabel = 'Fermer')`: an error toast with the same surface, an alert icon, no timer
43
+ and a 28px cross (a 44px hit area on touch, 36px with a fine pointer); it closes only with the cross. One message
44
+ at a time: an error replaces a confirmation and the other way round. `Toast` becomes a union on `kind`: `'success'`, or `'error'` with its `closeLabel`.
45
+ - `ui-drawer` (`@joanroucoux/cairn-ui/drawer`): a modal side panel on the native `<dialog>`, against the right edge at
46
+ full height, 440px wide by default, on `--card` with a shadow on its left edge, 24px of padding and a
47
+ `rgb(0 0 0 / 0.36)` veil. It scrolls on its own with `overscroll-behavior: contain`, without locking the page.
48
+ Escape, the veil and the optional 36px cross close it; `dismissed` and `closed` (`escape`, `backdrop`, `cross`,
49
+ `programmatic`) follow the protocol of `ui-dialog`, and `busy` keeps it open. Without `heading` it draws no header
50
+ and `label` names it; with neither it throws. It enters with opacity and a 24px slide over `--duration-base` on
51
+ `--ease-out` and leaves the reverse way over `--duration-exit`; under reduced motion it only fades. A `ui-dialog`
52
+ opened from it opens over it and the drawer stays underneath: Escape closes the dialog, then the drawer.
53
+ - `ModalClose` (`@joanroucoux/cairn-ui/dialog`): the close protocol `ui-dialog` and `ui-drawer` share (Escape,
54
+ press-and-release on the veil, `busy`, `dismissed`, then `closed` once the exit transition has played). An
55
+ optional `opening` callback runs just before `showModal()`.
56
+ - `ui-select-pill` (`@joanroucoux/cairn-ui/select-pill`): a compact pill that opens a `ui-menu` of exclusive
57
+ choices, to head a row of filter chips. The projected text is its label and the projected `ui-menu` is what it
58
+ opens, as a sheet on a phone like the `…` menus. Outlined with a chevron at rest, solid primary when `active`,
59
+ where a separate 14px cross (44px hit area on touch, 36px with a fine pointer), named by the required `clearLabel`,
60
+ replaces the chevron and emits `cleared`, and focus goes back to the trigger. `contextLabel` is read before the
61
+ label while active. 34px in a 44px target on touch and 32px with a fine pointer, with a 2px focus outline outside
62
+ the pill at every size, a cross ring in the pill's text colour, and a border of its own in forced colors.
63
+ - `button[uiMenuItem]` accepts `checked`: the item becomes a `menuitemradio` with `aria-checked` and a check mark
64
+ after its label, and the menu focuses the checked item when it opens.
65
+ - `ui-filter-chips` projects an element marked `uiChipsLeading` first in its row, followed by a 1 x 20px `--border`
66
+ rule that only shows when something is projected.
67
+ - `td[ui-group-cell]` is collapsible: `collapsible`, `expanded` (a model), `toggleDisabled` and `controls`. The band
68
+ becomes an `h2 > button[aria-expanded]` with an 18px chevron that turns to -90 degrees in `--duration-fast`, a
69
+ `--soft` hover and a focus ring. With `toggleDisabled` it keeps neither the pointer cursor nor the hover. The page
70
+ owns the fold memory.
71
+ - `tbody[uiGroup]` takes `collapsed`: its rows (`tr[uiTr]`) get `hidden` and stay in the DOM, so a `uiFlipList`
72
+ around the table slides nothing when a group folds. A plain `tr` is not hidden.
73
+ - `ui-group-header` (`@joanroucoux/cairn-ui/group-header`): the header of a grouped card on a phone, with name, meta
74
+ and a projected total. Collapsible, with a 20px chevron and a press scale (neither the scale nor the pointer cursor
75
+ with `toggleDisabled`), or static.
76
+ - `ui-result-group` (`@joanroucoux/cairn-ui/result-group`): one source of a search, a two-tone heading over its rows,
77
+ with a two-row skeleton, a message slot (`resultGroupMessage`) and an inline error whose retry has no icon.
78
+ - `ui-alert` `variant="info"`: a `--muted` box with an 18px info icon, `role="note"`.
79
+ - `ui-row` `trailing="chevron"`: a flush link row with a 16px `--subtle-foreground` chevron and a dimming hover. Rows
80
+ without it are unchanged.
81
+ - `ui-back-link` `size="inline"` and the `button[ui-back-link]` selector: a 14px 500 muted back step, 18px chevron,
82
+ 44px high (36px with a mouse). A button host gets `type="button"` unless it sets its own.
83
+ - `ui-async` `retryIcon` input (default true): `false` draws a text-only retry in the `inline` variant.
84
+ - `ui-line-chart` `deltaSuffix`: a text shown after the change in the tooltip (for example "depuis le début"). It
85
+ stays when the amount is masked.
86
+
87
+ ### Changed
88
+
89
+ - `ui-dialog` has one three-zone structure: header `16 16 16 24`, body `20 24` (the only scroller), footer `16 24`;
90
+ on a sheet `0 8 12 16`, `16` and `12 16` plus the safe area, under a handle. A hairline runs under the header and
91
+ above the footer when `closeLabel` draws the cross. The `confirm` variant has one 24px padding and no hairlines,
92
+ and an empty confirm footer has no top padding.
93
+ - `ui-dialog` is centred on a desktop and capped at `calc(100dvh - 96px)`; the cross icon is 22px in every dialog.
94
+ - `ui-dialog` opened while another modal is open (over a `ui-drawer`) draws a lighter `rgb(0 0 0 / 0.24)` veil over
95
+ that one's; alone it keeps `rgb(0 0 0 / 0.36)`. It decides when it opens, with no input.
96
+ - `ui-dialog` width: the default stays `lg` (560px) and `confirm` defaults to 440px; `width` still takes `md`, `lg`
97
+ or any CSS length.
98
+ - `ui-line-chart` shows its tooltip on a tap: `pointerdown` shows it, `pointermove` follows, `pointerleave` and
99
+ `pointercancel` hide it. The plot is `touch-none` (was `touch-pan-y`), so a vertical swipe on the plot no longer
100
+ scrolls the page; the page still scrolls everywhere else.
101
+ - `uiStaleLink` with `chevron`: the gap before the chevron is 4px on touch and 2px with a mouse (was 2px everywhere).
102
+ - `ui-toaster` is an inverted surface (`--primary-foreground` on `--primary`, no contour, menu shadow, 44px minimum
103
+ height, 280 to 400px wide within the viewport minus 32px) with a 16px check icon, and it is centred at the bottom of
104
+ the content area: from `64rem`, 24px from the bottom and centred between `--sidebar-width` (0 when the app does not
105
+ set it) and the right edge; below, centred 8px above the tab bar as before. It was `--elevated`, bottom right.
106
+ - Stories and docs no longer use the Instruments samples: the `ui-table` `Instruments` story is removed, the
107
+ `ui-empty` sample reads "Aucune ligne ne correspond à ...", the `ui-back-link` small story reads "Comptes". The
108
+ Storybook favicon is the Cairn tile.
109
+
110
+ ### Fixed
111
+
112
+ - `ui-toaster` shows above an open `ui-dialog` or `ui-drawer`: it is a `popover="manual"` in the top layer, shown
113
+ again each time a message arrives. A modal that opens afterwards does not raise it again: the toast never covers a
114
+ dialog's button. Behind a modal the page is inert, so the pause and the error cross do not work over an open modal.
115
+
3
116
  ## 0.8.2
4
117
 
5
118
  ### Changed
@@ -70,6 +183,7 @@ Every symbol that was exported from the root now lives under exactly one subpath
70
183
  - `@joanroucoux/cairn-ui/row`: `ROW_GAPS`, `ROW_PADDINGS`, `ROW_SIZES`, `UiListRow`, `UiRow`, `UiRowItem`, `UiRowTile`, `RowGap`, `RowPadding`, `RowSize`
71
184
  - `@joanroucoux/cairn-ui/segmented`: `SEGMENTED_SIZES`, `UiSegmented`, `SegmentedOption`, `SegmentedSize`
72
185
  - `@joanroucoux/cairn-ui/select`: `UiSelect`
186
+ - `@joanroucoux/cairn-ui/select-pill`: `UiSelectPill`
73
187
  - `@joanroucoux/cairn-ui/skeleton`: `SKELETON_SHAPES`, `UiSkeleton`, `SkeletonShape`
74
188
  - `@joanroucoux/cairn-ui/stale-link`: `STALE_LINK_SIZES`, `UiStaleLink`, `StaleLinkSize`
75
189
  - `@joanroucoux/cairn-ui/stat`: `STAT_SIZES`, `UiStat`, `StatSize`
@@ -1,54 +1,58 @@
1
- import { DOCUMENT } from '@angular/common';
2
- import * as i0 from '@angular/core';
3
- import { inject, ElementRef, DestroyRef, afterNextRender, Component } from '@angular/core';
4
-
5
- const HEIGHT_PROPERTY = '--action-bar-height';
6
- /**
7
- * Bar of actions fixed above the tab bar on iPhone: the primary actions of a detail screen, within
8
- * thumb reach. It sits `--tab-bar-height` (52px plus the safe area) above the bottom edge, so it clears `ui-tab-bar`, and
9
- * it is hidden from `64rem`, where the same actions live in the page itself. Its children share the
10
- * width equally. While it is on the page it publishes its height as `--action-bar-height` on the
11
- * root element, which `ui-toaster` adds to its offset so a confirmation never covers the actions.
12
- *
13
- * @example
14
- * <ui-action-bar>
15
- * <button ui-button variant="outline" size="tall">Sell</button>
16
- * <button ui-button size="tall">Buy</button>
17
- * </ui-action-bar>
18
- */
19
- class UiActionBar {
20
- constructor() {
21
- const host = inject(ElementRef).nativeElement;
22
- const root = inject(DOCUMENT).documentElement;
23
- const destroyRef = inject(DestroyRef);
24
- const publish = () => root.style.setProperty(HEIGHT_PROPERTY, `${host.offsetHeight}px`);
25
- afterNextRender(() => {
26
- publish();
27
- if (typeof ResizeObserver !== 'undefined') {
28
- const observer = new ResizeObserver(publish);
29
- observer.observe(host);
30
- destroyRef.onDestroy(() => observer.disconnect());
31
- }
32
- });
33
- destroyRef.onDestroy(() => root.style.removeProperty(HEIGHT_PROPERTY));
34
- }
35
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiActionBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
36
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.7", type: UiActionBar, isStandalone: true, selector: "ui-action-bar", host: { classAttribute: "fixed inset-x-0 bottom-[var(--tab-bar-height,calc(52px+env(safe-area-inset-bottom)))] z-40 grid grid-flow-col auto-cols-fr gap-2 bg-(--background) px-(--gutter) py-3 shadow-[0_-1px_0_var(--hairline)] lg:hidden" }, ngImport: i0, template: '<ng-content />', isInline: true });
37
- }
38
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiActionBar, decorators: [{
39
- type: Component,
40
- args: [{
41
- selector: 'ui-action-bar',
42
- template: '<ng-content />',
43
- host: {
44
- class: 'fixed inset-x-0 bottom-[var(--tab-bar-height,calc(52px+env(safe-area-inset-bottom)))] z-40 grid grid-flow-col auto-cols-fr gap-2 bg-(--background) px-(--gutter) py-3 shadow-[0_-1px_0_var(--hairline)] lg:hidden',
45
- },
46
- }]
47
- }], ctorParameters: () => [] });
48
-
49
- /**
50
- * Generated bundle index. Do not edit.
51
- */
52
-
1
+ import { DOCUMENT } from "@angular/common";
2
+ import * as i0 from "@angular/core";
3
+ import { Component, DestroyRef, ElementRef, afterNextRender, inject } from "@angular/core";
4
+ const HEIGHT_PROPERTY = "--action-bar-height";
5
+ var UiActionBar = class UiActionBar {
6
+ constructor() {
7
+ const host = inject(ElementRef).nativeElement;
8
+ const root = inject(DOCUMENT).documentElement;
9
+ const destroyRef = inject(DestroyRef);
10
+ const publish = () => root.style.setProperty(HEIGHT_PROPERTY, `${host.offsetHeight}px`);
11
+ afterNextRender(() => {
12
+ publish();
13
+ if (typeof ResizeObserver !== "undefined") {
14
+ const observer = new ResizeObserver(publish);
15
+ observer.observe(host);
16
+ destroyRef.onDestroy(() => observer.disconnect());
17
+ }
18
+ });
19
+ destroyRef.onDestroy(() => root.style.removeProperty(HEIGHT_PROPERTY));
20
+ }
21
+ static ɵfac = i0.ɵɵngDeclareFactory({
22
+ minVersion: "12.0.0",
23
+ version: "22.2.0",
24
+ ngImport: i0,
25
+ type: UiActionBar,
26
+ deps: [],
27
+ target: i0.ɵɵFactoryTarget.Component
28
+ });
29
+ static ɵcmp = i0.ɵɵngDeclareComponent({
30
+ minVersion: "14.0.0",
31
+ version: "22.2.0",
32
+ type: UiActionBar,
33
+ isStandalone: true,
34
+ selector: "ui-action-bar",
35
+ host: { classAttribute: "fixed inset-x-0 bottom-[var(--tab-bar-height,calc(52px+env(safe-area-inset-bottom)))] z-40 grid grid-flow-col auto-cols-fr gap-2 bg-(--background) px-(--gutter) py-3 shadow-[0_-1px_0_var(--hairline)] lg:hidden" },
36
+ ngImport: i0,
37
+ template: "<ng-content />",
38
+ isInline: true
39
+ });
40
+ };
41
+ i0.ɵɵngDeclareClassMetadata({
42
+ minVersion: "12.0.0",
43
+ version: "22.2.0",
44
+ ngImport: i0,
45
+ type: UiActionBar,
46
+ decorators: [{
47
+ type: Component,
48
+ args: [{
49
+ selector: "ui-action-bar",
50
+ template: "<ng-content />",
51
+ host: { class: "fixed inset-x-0 bottom-[var(--tab-bar-height,calc(52px+env(safe-area-inset-bottom)))] z-40 grid grid-flow-col auto-cols-fr gap-2 bg-(--background) px-(--gutter) py-3 shadow-[0_-1px_0_var(--hairline)] lg:hidden" }
52
+ }]
53
+ }],
54
+ ctorParameters: () => []
55
+ });
53
56
  export { UiActionBar };
54
- //# sourceMappingURL=joanroucoux-cairn-ui-action-bar.mjs.map
57
+
58
+ //# sourceMappingURL=joanroucoux-cairn-ui-action-bar.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-action-bar.mjs","sources":["../../../projects/ui/action-bar/action-bar.ts","../../../projects/ui/action-bar/joanroucoux-cairn-ui-action-bar.ts"],"sourcesContent":["import { DOCUMENT } from '@angular/common';\nimport { Component, DestroyRef, ElementRef, afterNextRender, inject } from '@angular/core';\n\nconst HEIGHT_PROPERTY = '--action-bar-height';\n\n/**\n * Bar of actions fixed above the tab bar on iPhone: the primary actions of a detail screen, within\n * thumb reach. It sits `--tab-bar-height` (52px plus the safe area) above the bottom edge, so it clears `ui-tab-bar`, and\n * it is hidden from `64rem`, where the same actions live in the page itself. Its children share the\n * width equally. While it is on the page it publishes its height as `--action-bar-height` on the\n * root element, which `ui-toaster` adds to its offset so a confirmation never covers the actions.\n *\n * @example\n * <ui-action-bar>\n * <button ui-button variant=\"outline\" size=\"tall\">Sell</button>\n * <button ui-button size=\"tall\">Buy</button>\n * </ui-action-bar>\n */\n@Component({\n selector: 'ui-action-bar',\n template: '<ng-content />',\n host: {\n class:\n 'fixed inset-x-0 bottom-[var(--tab-bar-height,calc(52px+env(safe-area-inset-bottom)))] z-40 grid grid-flow-col auto-cols-fr gap-2 bg-(--background) px-(--gutter) py-3 shadow-[0_-1px_0_var(--hairline)] lg:hidden',\n },\n})\nexport class UiActionBar {\n constructor() {\n const host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n const root = inject(DOCUMENT).documentElement;\n const destroyRef = inject(DestroyRef);\n const publish = (): void => root.style.setProperty(HEIGHT_PROPERTY, `${host.offsetHeight}px`);\n\n afterNextRender(() => {\n publish();\n\n if (typeof ResizeObserver !== 'undefined') {\n const observer = new ResizeObserver(publish);\n observer.observe(host);\n destroyRef.onDestroy(() => observer.disconnect());\n }\n });\n\n destroyRef.onDestroy(() => root.style.removeProperty(HEIGHT_PROPERTY));\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAGA,MAAM,eAAe,GAAG,qBAAqB;AAE7C;;;;;;;;;;;;AAYG;MASU,WAAW,CAAA;AACtB,IAAA,WAAA,GAAA;QACE,MAAM,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC,CAAC,aAAa;QACtE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,eAAe;AAC7C,QAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AACrC,QAAA,MAAM,OAAO,GAAG,MAAY,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,eAAe,EAAE,CAAA,EAAG,IAAI,CAAC,YAAY,CAAA,EAAA,CAAI,CAAC;QAE7F,eAAe,CAAC,MAAK;AACnB,YAAA,OAAO,EAAE;AAET,YAAA,IAAI,OAAO,cAAc,KAAK,WAAW,EAAE;AACzC,gBAAA,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC;AAC5C,gBAAA,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;gBACtB,UAAU,CAAC,SAAS,CAAC,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;YACnD;AACF,QAAA,CAAC,CAAC;AAEF,QAAA,UAAU,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;IACxE;uGAlBW,WAAW,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAX,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,WAAW,wTANZ,gBAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA;;2FAMf,WAAW,EAAA,UAAA,EAAA,CAAA;kBARvB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,eAAe;AACzB,oBAAA,QAAQ,EAAE,gBAAgB;AAC1B,oBAAA,IAAI,EAAE;AACJ,wBAAA,KAAK,EACH,mNAAmN;AACtN,qBAAA;AACF,iBAAA;;;ACzBD;;AAEG;;;;"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-action-bar.mjs","names":[],"sources":["../../../projects/ui/action-bar/action-bar.ts"],"sourcesContent":["import { DOCUMENT } from '@angular/common';\nimport { Component, DestroyRef, ElementRef, afterNextRender, inject } from '@angular/core';\n\nconst HEIGHT_PROPERTY = '--action-bar-height';\n\n/**\n * Bar of actions fixed above the tab bar on iPhone, hidden from `64rem`, where the same actions\n * live in the page itself. Its children share the width equally. While it is on the page it\n * publishes its height as `--action-bar-height` on the root element, which `ui-toaster` clears.\n *\n * @example\n * <ui-action-bar>\n * <button ui-button variant=\"outline\" size=\"tall\">Sell</button>\n * <button ui-button size=\"tall\">Buy</button>\n * </ui-action-bar>\n */\n@Component({\n selector: 'ui-action-bar',\n template: '<ng-content />',\n host: {\n class:\n 'fixed inset-x-0 bottom-[var(--tab-bar-height,calc(52px+env(safe-area-inset-bottom)))] z-40 grid grid-flow-col auto-cols-fr gap-2 bg-(--background) px-(--gutter) py-3 shadow-[0_-1px_0_var(--hairline)] lg:hidden',\n },\n})\nexport class UiActionBar {\n constructor() {\n const host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n const root = inject(DOCUMENT).documentElement;\n const destroyRef = inject(DestroyRef);\n const publish = (): void => root.style.setProperty(HEIGHT_PROPERTY, `${host.offsetHeight}px`);\n\n afterNextRender(() => {\n publish();\n\n if (typeof ResizeObserver !== 'undefined') {\n const observer = new ResizeObserver(publish);\n observer.observe(host);\n destroyRef.onDestroy(() => observer.disconnect());\n }\n });\n\n destroyRef.onDestroy(() => root.style.removeProperty(HEIGHT_PROPERTY));\n }\n}\n"],"mappings":";;;AAGA,MAAM,kBAAkB;AAqBxB,IAAa,cAAb,MAAa,YAAW;CACtB,cAAA;EACE,MAAM,OAAO,OAAgC,UAAU,CAAC,CAAC;EACzD,MAAM,OAAO,OAAO,QAAQ,CAAC,CAAC;EAC9B,MAAM,aAAa,OAAO,UAAU;EACpC,MAAM,gBAAsB,KAAK,MAAM,YAAY,iBAAiB,GAAG,KAAK,aAAY,GAAI;EAE5F,sBAAqB;GACnB,QAAO;GAEP,IAAI,OAAO,mBAAmB,aAAa;IACzC,MAAM,WAAW,IAAI,eAAe,OAAO;IAC3C,SAAS,QAAQ,IAAI;IACrB,WAAW,gBAAgB,SAAS,WAAU,CAAE;GAClD;EACF,CAAC;EAED,WAAW,gBAAgB,KAAK,MAAM,eAAe,eAAe,CAAC;CACvE;CAlBW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAW,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAX,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAW,cAAA;EAAA,UAAA;EAAA,MAAA,EAAA,gBAAA,oNAAA;EAAA,UAAA;EAAA,UANZ;EAAgB,UAAA;CAAA,CAAA;;AAMf,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAW,YAAA,CAAA;EARvB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,UAAU;GACV,MAAM,EACJ,OACE,oNACH;EACF,CAAA"}
@@ -1,31 +1,93 @@
1
- import * as i0 from '@angular/core';
2
- import { input, booleanAttribute, computed, Component } from '@angular/core';
3
-
4
- const ALERT_VARIANTS = ['error', 'warning'];
5
- const BASE_CLASSES = 'flex items-start gap-2.5 text-left text-label';
1
+ import * as i0 from "@angular/core";
2
+ import { Component, booleanAttribute, computed, input } from "@angular/core";
3
+ const ALERT_VARIANTS = [
4
+ "error",
5
+ "warning",
6
+ "info"
7
+ ];
8
+ const BASE_CLASSES = "flex items-start gap-2.5 text-left text-label";
6
9
  const VARIANT_CLASSES = {
7
- error: 'rounded-control bg-(--card) px-3.5 py-3 shadow-[inset_0_0_0_1px_var(--border)]',
8
- warning: 'text-(--foreground)',
10
+ error: "rounded-control bg-(--card) px-3.5 py-3 shadow-[inset_0_0_0_1px_var(--border)]",
11
+ warning: "text-(--foreground)",
12
+ info: "rounded-control bg-(--muted) p-3 text-(--foreground)"
13
+ };
14
+ const ROLES = {
15
+ error: "alert",
16
+ warning: "status",
17
+ info: "note"
9
18
  };
10
- /**
11
- * Inline message explaining a failure or a consequence: an icon, an optional heading and a text.
12
- * It fades in when it appears; set `[fadeIn]="false"` on an alert that is part of the page as it
13
- * opens (an error state after a load), which shows without motion.
14
- *
15
- * @example
16
- * <ui-alert heading="Sign-in failed">Try again.</ui-alert>
17
- */
18
- class UiAlert {
19
- variant = input('error', /* @ts-ignore */
20
- ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
21
- heading = input(/* @ts-ignore */
22
- ...(ngDevMode ? [undefined, { debugName: "heading" }] : /* istanbul ignore next */ []));
23
- fadeIn = input(true, { ...(ngDevMode ? { debugName: "fadeIn" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
24
- classes = computed(() => `${BASE_CLASSES} ${VARIANT_CLASSES[this.variant()]}${this.fadeIn() ? ' ui-enter-fade' : ''}`, /* @ts-ignore */
25
- ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
26
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiAlert, deps: [], target: i0.ɵɵFactoryTarget.Component });
27
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: UiAlert, isStandalone: true, selector: "ui-alert", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, fadeIn: { classPropertyName: "fadeIn", publicName: "fadeIn", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "animate.leave": "ui-leave-fade" }, properties: { "class": "classes()", "attr.role": "variant() === 'warning' ? 'status' : 'alert'" } }, ngImport: i0, template: `
28
- @if (variant() === 'warning') {
19
+ var UiAlert = class UiAlert {
20
+ variant = input("error", ...ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []);
21
+ heading = input(...ngDevMode ? [void 0, { debugName: "heading" }] : /* istanbul ignore next */ []);
22
+ fadeIn = input(true, {
23
+ ...ngDevMode ? { debugName: "fadeIn" } : /* istanbul ignore next */ {},
24
+ transform: booleanAttribute
25
+ });
26
+ role = computed(() => ROLES[this.variant()], ...ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []);
27
+ classes = computed(() => `${BASE_CLASSES} ${VARIANT_CLASSES[this.variant()]}${this.fadeIn() ? " ui-enter-fade" : ""}`, ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
28
+ static ɵfac = i0.ɵɵngDeclareFactory({
29
+ minVersion: "12.0.0",
30
+ version: "22.2.0",
31
+ ngImport: i0,
32
+ type: UiAlert,
33
+ deps: [],
34
+ target: i0.ɵɵFactoryTarget.Component
35
+ });
36
+ static ɵcmp = i0.ɵɵngDeclareComponent({
37
+ minVersion: "17.0.0",
38
+ version: "22.2.0",
39
+ type: UiAlert,
40
+ isStandalone: true,
41
+ selector: "ui-alert",
42
+ inputs: {
43
+ variant: {
44
+ classPropertyName: "variant",
45
+ publicName: "variant",
46
+ isSignal: true,
47
+ isRequired: false,
48
+ transformFunction: null
49
+ },
50
+ heading: {
51
+ classPropertyName: "heading",
52
+ publicName: "heading",
53
+ isSignal: true,
54
+ isRequired: false,
55
+ transformFunction: null
56
+ },
57
+ fadeIn: {
58
+ classPropertyName: "fadeIn",
59
+ publicName: "fadeIn",
60
+ isSignal: true,
61
+ isRequired: false,
62
+ transformFunction: null
63
+ }
64
+ },
65
+ host: {
66
+ attributes: { "animate.leave": "ui-leave-fade" },
67
+ properties: {
68
+ "class": "classes()",
69
+ "attr.role": "role()"
70
+ }
71
+ },
72
+ ngImport: i0,
73
+ template: `
74
+ @if (variant() === 'info') {
75
+ <svg
76
+ aria-hidden="true"
77
+ class="mt-px block flex-none stroke-current"
78
+ fill="none"
79
+ height="18"
80
+ stroke-linecap="round"
81
+ stroke-linejoin="round"
82
+ stroke-width="1.75"
83
+ viewBox="0 0 24 24"
84
+ width="18"
85
+ >
86
+ <circle cx="12" cy="12" r="10" />
87
+ <path d="M12 16v-4" />
88
+ <path d="M12 8h.01" />
89
+ </svg>
90
+ } @else if (variant() === 'warning') {
29
91
  <svg
30
92
  aria-hidden="true"
31
93
  class="mt-px block flex-none stroke-(--negative)"
@@ -65,14 +127,37 @@ class UiAlert {
65
127
  }
66
128
  <span class="text-pretty" [class.text-(--muted-foreground)]="heading()"><ng-content /></span>
67
129
  </div>
68
- `, isInline: true });
69
- }
70
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiAlert, decorators: [{
71
- type: Component,
72
- args: [{
73
- selector: 'ui-alert',
74
- template: `
75
- @if (variant() === 'warning') {
130
+ `,
131
+ isInline: true
132
+ });
133
+ };
134
+ i0.ɵɵngDeclareClassMetadata({
135
+ minVersion: "12.0.0",
136
+ version: "22.2.0",
137
+ ngImport: i0,
138
+ type: UiAlert,
139
+ decorators: [{
140
+ type: Component,
141
+ args: [{
142
+ selector: "ui-alert",
143
+ template: `
144
+ @if (variant() === 'info') {
145
+ <svg
146
+ aria-hidden="true"
147
+ class="mt-px block flex-none stroke-current"
148
+ fill="none"
149
+ height="18"
150
+ stroke-linecap="round"
151
+ stroke-linejoin="round"
152
+ stroke-width="1.75"
153
+ viewBox="0 0 24 24"
154
+ width="18"
155
+ >
156
+ <circle cx="12" cy="12" r="10" />
157
+ <path d="M12 16v-4" />
158
+ <path d="M12 8h.01" />
159
+ </svg>
160
+ } @else if (variant() === 'warning') {
76
161
  <svg
77
162
  aria-hidden="true"
78
163
  class="mt-px block flex-none stroke-(--negative)"
@@ -113,17 +198,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
113
198
  <span class="text-pretty" [class.text-(--muted-foreground)]="heading()"><ng-content /></span>
114
199
  </div>
115
200
  `,
116
- host: {
117
- 'animate.leave': 'ui-leave-fade',
118
- '[class]': 'classes()',
119
- '[attr.role]': "variant() === 'warning' ? 'status' : 'alert'",
120
- },
121
- }]
122
- }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], fadeIn: [{ type: i0.Input, args: [{ isSignal: true, alias: "fadeIn", required: false }] }] } });
123
-
124
- /**
125
- * Generated bundle index. Do not edit.
126
- */
127
-
201
+ host: {
202
+ "animate.leave": "ui-leave-fade",
203
+ "[class]": "classes()",
204
+ "[attr.role]": "role()"
205
+ }
206
+ }]
207
+ }],
208
+ propDecorators: {
209
+ variant: [{
210
+ type: i0.Input,
211
+ args: [{
212
+ isSignal: true,
213
+ alias: "variant",
214
+ required: false
215
+ }]
216
+ }],
217
+ heading: [{
218
+ type: i0.Input,
219
+ args: [{
220
+ isSignal: true,
221
+ alias: "heading",
222
+ required: false
223
+ }]
224
+ }],
225
+ fadeIn: [{
226
+ type: i0.Input,
227
+ args: [{
228
+ isSignal: true,
229
+ alias: "fadeIn",
230
+ required: false
231
+ }]
232
+ }]
233
+ }
234
+ });
128
235
  export { ALERT_VARIANTS, UiAlert };
129
- //# sourceMappingURL=joanroucoux-cairn-ui-alert.mjs.map
236
+
237
+ //# sourceMappingURL=joanroucoux-cairn-ui-alert.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-alert.mjs","sources":["../../../projects/ui/alert/alert.ts","../../../projects/ui/alert/joanroucoux-cairn-ui-alert.ts"],"sourcesContent":["import { Component, booleanAttribute, computed, input } from '@angular/core';\n\nexport const ALERT_VARIANTS = ['error', 'warning'] as const;\nexport type AlertVariant = (typeof ALERT_VARIANTS)[number];\n\nconst BASE_CLASSES = 'flex items-start gap-2.5 text-left text-label';\n\nconst VARIANT_CLASSES: Record<AlertVariant, string> = {\n error: 'rounded-control bg-(--card) px-3.5 py-3 shadow-[inset_0_0_0_1px_var(--border)]',\n warning: 'text-(--foreground)',\n};\n\n/**\n * Inline message explaining a failure or a consequence: an icon, an optional heading and a text.\n * It fades in when it appears; set `[fadeIn]=\"false\"` on an alert that is part of the page as it\n * opens (an error state after a load), which shows without motion.\n *\n * @example\n * <ui-alert heading=\"Sign-in failed\">Try again.</ui-alert>\n */\n@Component({\n selector: 'ui-alert',\n template: `\n @if (variant() === 'warning') {\n <svg\n aria-hidden=\"true\"\n class=\"mt-px block flex-none stroke-(--negative)\"\n fill=\"none\"\n height=\"18\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n width=\"18\"\n >\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n } @else {\n <svg\n aria-hidden=\"true\"\n class=\"block flex-none stroke-(--negative)\"\n fill=\"none\"\n height=\"18\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n width=\"18\"\n [class.mt-px]=\"heading()\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n }\n <div class=\"flex flex-col gap-0.5\">\n @if (heading()) {\n <span class=\"font-medium\">{{ heading() }}</span>\n }\n <span class=\"text-pretty\" [class.text-(--muted-foreground)]=\"heading()\"><ng-content /></span>\n </div>\n `,\n host: {\n 'animate.leave': 'ui-leave-fade',\n '[class]': 'classes()',\n '[attr.role]': \"variant() === 'warning' ? 'status' : 'alert'\",\n },\n})\nexport class UiAlert {\n readonly variant = input<AlertVariant>('error');\n readonly heading = input<string>();\n readonly fadeIn = input(true, { transform: booleanAttribute });\n\n protected readonly classes = computed(\n () => `${BASE_CLASSES} ${VARIANT_CLASSES[this.variant()]}${this.fadeIn() ? ' ui-enter-fade' : ''}`,\n );\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;MAEa,cAAc,GAAG,CAAC,OAAO,EAAE,SAAS;AAGjD,MAAM,YAAY,GAAG,+CAA+C;AAEpE,MAAM,eAAe,GAAiC;AACpD,IAAA,KAAK,EAAE,gFAAgF;AACvF,IAAA,OAAO,EAAE,qBAAqB;CAC/B;AAED;;;;;;;AAOG;MAmDU,OAAO,CAAA;IACT,OAAO,GAAG,KAAK,CAAe,OAAO;gFAAC;AACtC,IAAA,OAAO,GAAG,KAAK;2FAAU;IACzB,MAAM,GAAG,KAAK,CAAC,IAAI,8EAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;AAE3C,IAAA,OAAO,GAAG,QAAQ,CACnC,MAAM,CAAA,EAAG,YAAY,CAAA,CAAA,EAAI,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA,EAAG,IAAI,CAAC,MAAM,EAAE,GAAG,gBAAgB,GAAG,EAAE,CAAA,CAAE;gFACnG;uGAPU,OAAO,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAP,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,OAAO,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,eAAA,EAAA,eAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,WAAA,EAAA,WAAA,EAAA,8CAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAhDR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA;;2FAOU,OAAO,EAAA,UAAA,EAAA,CAAA;kBAlDnB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,UAAU;AACpB,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCT,EAAA,CAAA;AACD,oBAAA,IAAI,EAAE;AACJ,wBAAA,eAAe,EAAE,eAAe;AAChC,wBAAA,SAAS,EAAE,WAAW;AACtB,wBAAA,aAAa,EAAE,8CAA8C;AAC9D,qBAAA;AACF,iBAAA;;;ACrED;;AAEG;;;;"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-alert.mjs","names":[],"sources":["../../../projects/ui/alert/alert.ts"],"sourcesContent":["import { Component, booleanAttribute, computed, input } from '@angular/core';\n\nexport const ALERT_VARIANTS = ['error', 'warning', 'info'] as const;\nexport type AlertVariant = (typeof ALERT_VARIANTS)[number];\n\nconst BASE_CLASSES = 'flex items-start gap-2.5 text-left text-label';\n\nconst VARIANT_CLASSES: Record<AlertVariant, string> = {\n error: 'rounded-control bg-(--card) px-3.5 py-3 shadow-[inset_0_0_0_1px_var(--border)]',\n warning: 'text-(--foreground)',\n info: 'rounded-control bg-(--muted) p-3 text-(--foreground)',\n};\n\nconst ROLES: Record<AlertVariant, string> = { error: 'alert', warning: 'status', info: 'note' };\n\n/**\n * Inline message explaining a failure or a consequence, or static help with `info`: an icon, an optional heading and a text.\n * It fades in when it appears; set `[fadeIn]=\"false\"` on an alert that is part of the page as it\n * opens.\n *\n * @example\n * <ui-alert heading=\"Sign-in failed\">Try again.</ui-alert>\n */\n@Component({\n selector: 'ui-alert',\n template: `\n @if (variant() === 'info') {\n <svg\n aria-hidden=\"true\"\n class=\"mt-px block flex-none stroke-current\"\n fill=\"none\"\n height=\"18\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n width=\"18\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 16v-4\" />\n <path d=\"M12 8h.01\" />\n </svg>\n } @else if (variant() === 'warning') {\n <svg\n aria-hidden=\"true\"\n class=\"mt-px block flex-none stroke-(--negative)\"\n fill=\"none\"\n height=\"18\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n width=\"18\"\n >\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n } @else {\n <svg\n aria-hidden=\"true\"\n class=\"block flex-none stroke-(--negative)\"\n fill=\"none\"\n height=\"18\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n width=\"18\"\n [class.mt-px]=\"heading()\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n }\n <div class=\"flex flex-col gap-0.5\">\n @if (heading()) {\n <span class=\"font-medium\">{{ heading() }}</span>\n }\n <span class=\"text-pretty\" [class.text-(--muted-foreground)]=\"heading()\"><ng-content /></span>\n </div>\n `,\n host: {\n 'animate.leave': 'ui-leave-fade',\n '[class]': 'classes()',\n '[attr.role]': 'role()',\n },\n})\nexport class UiAlert {\n readonly variant = input<AlertVariant>('error');\n readonly heading = input<string>();\n readonly fadeIn = input(true, { transform: booleanAttribute });\n\n protected readonly role = computed(() => ROLES[this.variant()]);\n\n protected readonly classes = computed(\n () => `${BASE_CLASSES} ${VARIANT_CLASSES[this.variant()]}${this.fadeIn() ? ' ui-enter-fade' : ''}`,\n );\n}\n"],"mappings":";;AAEA,MAAa,iBAAiB;CAAC;CAAS;CAAW;AAAM;AAGzD,MAAM,eAAe;AAErB,MAAM,kBAAgD;CACpD,OAAO;CACP,SAAS;CACT,MAAM;AACP;AAED,MAAM,QAAsC;CAAE,OAAO;CAAS,SAAS;CAAU,MAAM;AAAM;AA4E7F,IAAa,UAAb,MAAa,QAAO;CACT,UAAU,MAAoB,SAAQ,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACtC,UAAU,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACzB,SAAS,MAAM,MAAI;EAAA,GAAA,YAAA,EAAA,WAAA,SAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CAExC,OAAO,eAAe,MAAM,KAAK,QAAO,IAAI,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAE5C,UAAU,eACrB,GAAG,aAAY,GAAI,gBAAgB,KAAK,QAAO,KAAM,KAAK,OAAM,IAAK,mBAAmB,MAC/F,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CATU,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAO,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAP,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAO,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,MAAA;GAAA,YAAA,EAAA,iBAAA,gBAAA;GAAA,YAAA;IAAA,SAAA;IAAA,aAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UAhER;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyDT,UAAA;CAAA,CAAA;;AAOU,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAO,YAAA,CAAA;EAlEnB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DV,MAAM;IACJ,iBAAiB;IACjB,WAAW;IACX,eAAe;GAChB;EACF,CAAA"}