@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
@@ -1,469 +1,417 @@
1
- import * as i0 from '@angular/core';
2
- import { input, booleanAttribute, output, signal, computed, inject, ElementRef, DestroyRef, afterNextRender, afterRenderEffect, Component } from '@angular/core';
3
-
1
+ import * as i0 from "@angular/core";
2
+ import { Component, DestroyRef, ElementRef, afterNextRender, afterRenderEffect, booleanAttribute, computed, inject, input, output, signal } from "@angular/core";
4
3
  const GRACE = 50;
5
4
  function afterExit(element, done) {
6
- const style = getComputedStyle(element);
7
- const wait = longest(style.transitionDuration) + longest(style.transitionDelay);
8
- if (wait === 0) {
9
- done();
10
- return () => undefined;
11
- }
12
- const onEnd = (event) => {
13
- if (event.target === element && !event.pseudoElement) {
14
- cancel();
15
- done();
16
- }
17
- };
18
- const timer = setTimeout(() => {
19
- cancel();
20
- done();
21
- }, wait + GRACE);
22
- const cancel = () => {
23
- clearTimeout(timer);
24
- element.removeEventListener('transitionend', onEnd);
25
- };
26
- element.addEventListener('transitionend', onEnd);
27
- return cancel;
5
+ const style = getComputedStyle(element);
6
+ const wait = longest(style.transitionDuration) + longest(style.transitionDelay);
7
+ if (wait === 0) {
8
+ done();
9
+ return () => void 0;
10
+ }
11
+ const onEnd = (event) => {
12
+ if (event.target === element && !event.pseudoElement) {
13
+ cancel();
14
+ done();
15
+ }
16
+ };
17
+ const timer = setTimeout(() => {
18
+ cancel();
19
+ done();
20
+ }, wait + GRACE);
21
+ const cancel = () => {
22
+ clearTimeout(timer);
23
+ element.removeEventListener("transitionend", onEnd);
24
+ };
25
+ element.addEventListener("transitionend", onEnd);
26
+ return cancel;
28
27
  }
29
28
  function longest(list) {
30
- return Math.max(0, ...list.split(',').map(toMs));
29
+ return Math.max(0, ...list.split(",").map(toMs));
31
30
  }
32
31
  function toMs(value) {
33
- const amount = Number.parseFloat(value);
34
- if (Number.isNaN(amount)) {
35
- return 0;
36
- }
37
- return value.trim().endsWith('ms') ? amount : amount * 1000;
38
- }
39
-
40
- const DIALOG_STYLES = `
41
- dialog {
42
- --dialog-ease: var(--ease-sheet);
43
- transition:
44
- transform var(--duration-base) var(--dialog-ease),
45
- overlay var(--duration-base) allow-discrete,
46
- display var(--duration-base) allow-discrete;
47
- transform: translateY(var(--drag-y, 0px));
48
- }
49
-
50
- dialog:not([open]) {
51
- transform: translateY(100%);
52
- transition-duration: var(--duration-exit);
53
- }
54
-
55
- @starting-style {
56
- dialog[open] {
57
- transform: translateY(100%);
58
- }
59
- }
60
-
61
- dialog[data-dragging] {
62
- transition: none;
63
- }
64
-
65
- @media (prefers-reduced-motion: reduce) {
66
- dialog {
67
- transition:
68
- opacity var(--duration-base) var(--dialog-ease),
69
- overlay var(--duration-base) allow-discrete,
70
- display var(--duration-base) allow-discrete;
71
- opacity: 1;
72
- }
73
-
74
- dialog:not([open]) {
75
- opacity: 0;
76
- transform: translateY(var(--drag-y, 0px));
77
- }
78
-
79
- @starting-style {
80
- dialog[open] {
81
- opacity: 0;
82
- transform: translateY(0);
83
- }
84
- }
85
- }
86
-
87
- @media (min-width: 64rem) {
88
- dialog {
89
- --dialog-ease: var(--ease-out);
90
- transition:
91
- opacity var(--duration-base) var(--dialog-ease),
92
- transform var(--duration-base) var(--dialog-ease),
93
- overlay var(--duration-base) allow-discrete,
94
- display var(--duration-base) allow-discrete;
95
- opacity: 1;
96
- transform: scale(1);
97
- }
98
-
99
- dialog:not([open]) {
100
- opacity: 0;
101
- transform: scale(var(--enter-scale));
102
- }
103
-
104
- @starting-style {
105
- dialog[open] {
106
- opacity: 0;
107
- transform: scale(var(--enter-scale));
108
- }
109
- }
110
- }
111
-
112
- dialog::backdrop {
113
- transition: opacity var(--duration-base) var(--ease-out);
114
- opacity: 1;
32
+ const amount = Number.parseFloat(value);
33
+ if (Number.isNaN(amount)) return 0;
34
+ return value.trim().endsWith("ms") ? amount : amount * 1e3;
115
35
  }
116
-
117
- dialog:not([open])::backdrop {
118
- opacity: 0;
119
- transition-duration: var(--duration-exit);
120
- }
121
-
122
- @starting-style {
123
- dialog[open]::backdrop {
124
- opacity: 0;
125
- }
126
- }
127
- `;
128
-
129
- const DISMISS_RATIO = 0.3;
130
- const DISMISS_SPEED = 0.5;
36
+ var ModalClose = class {
37
+ #host = inject(ElementRef);
38
+ #config;
39
+ #pressedOnBackdrop = false;
40
+ #reason = null;
41
+ #cancelExit = () => void 0;
42
+ constructor(config) {
43
+ this.#config = config;
44
+ inject(DestroyRef).onDestroy(() => this.#cancelExit());
45
+ afterRenderEffect(() => {
46
+ const dialog = this.#dialog;
47
+ if (config.open() && !dialog.open) {
48
+ this.#cancelExit();
49
+ config.reset?.();
50
+ config.opening?.();
51
+ dialog.showModal();
52
+ } else if (!config.open() && dialog.open) this.close("programmatic");
53
+ });
54
+ }
55
+ close(reason) {
56
+ if (this.#dialog.open) {
57
+ this.#reason = reason;
58
+ this.#dialog.close();
59
+ }
60
+ }
61
+ onCancel(event) {
62
+ if (event.target !== event.currentTarget) return;
63
+ event.preventDefault();
64
+ if (!this.#config.busy()) this.close("escape");
65
+ }
66
+ onKeydown(event) {
67
+ if (event.key === "Escape" && this.#config.busy() && event.target.closest("dialog") === this.#dialog) event.preventDefault();
68
+ }
69
+ onPointerDown(event) {
70
+ this.#pressedOnBackdrop = event.target === this.#dialog && this.#outside(event);
71
+ }
72
+ onClick(event) {
73
+ if (this.#pressedOnBackdrop && !this.#config.busy() && event.target === this.#dialog && this.#outside(event)) this.close("backdrop");
74
+ this.#pressedOnBackdrop = false;
75
+ }
76
+ onNativeClose() {
77
+ const asked = this.#reason;
78
+ this.#reason = null;
79
+ if (this.#dialog.open) return;
80
+ if (asked === null && this.#config.busy()) {
81
+ this.#dialog.showModal();
82
+ return;
83
+ }
84
+ const reason = asked ?? "escape";
85
+ if (reason !== "programmatic") this.#config.dismissed.emit();
86
+ this.#cancelExit();
87
+ this.#cancelExit = afterExit(this.#dialog, () => {
88
+ this.#cancelExit = () => void 0;
89
+ this.#config.reset?.();
90
+ this.#config.closed.emit(reason);
91
+ });
92
+ }
93
+ get #dialog() {
94
+ return this.#host.nativeElement.querySelector("dialog");
95
+ }
96
+ #outside(event) {
97
+ const rect = this.#dialog.getBoundingClientRect();
98
+ return event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom;
99
+ }
100
+ };
101
+ const DISMISS_RATIO = .3;
102
+ const DISMISS_SPEED = .5;
131
103
  const SPEED_WINDOW = 100;
132
104
  const SLOP = 6;
133
- const CONTROLS = 'button, a, input, select, textarea, [role="button"]';
134
- class SheetDrag {
135
- #panel;
136
- #grips;
137
- #dismiss;
138
- #enabled;
139
- #gesture = null;
140
- constructor(panel, grips, dismiss, enabled) {
141
- this.#panel = panel;
142
- this.#grips = grips;
143
- this.#dismiss = dismiss;
144
- this.#enabled = enabled;
145
- for (const grip of grips) {
146
- grip.addEventListener('pointerdown', this.#onDown);
147
- grip.addEventListener('pointermove', this.#onMove);
148
- grip.addEventListener('pointerup', this.#onUp);
149
- grip.addEventListener('pointercancel', this.#onCancel);
150
- }
151
- }
152
- reset() {
153
- this.#gesture = null;
154
- this.#panel.removeAttribute('data-dragging');
155
- this.#panel.style.removeProperty('--drag-y');
156
- }
157
- destroy() {
158
- for (const grip of this.#grips) {
159
- grip.removeEventListener('pointerdown', this.#onDown);
160
- grip.removeEventListener('pointermove', this.#onMove);
161
- grip.removeEventListener('pointerup', this.#onUp);
162
- grip.removeEventListener('pointercancel', this.#onCancel);
163
- }
164
- }
165
- #onDown = (event) => {
166
- const grip = event.currentTarget;
167
- if (event.button !== 0 || !this.#enabled() || !isSheet() || event.target.closest(CONTROLS)) {
168
- return;
169
- }
170
- grip.setPointerCapture(event.pointerId);
171
- this.#gesture = {
172
- id: event.pointerId,
173
- startX: event.clientX,
174
- startY: event.clientY,
175
- dragging: false,
176
- height: 0,
177
- offset: 0,
178
- samples: [{ y: event.clientY, at: event.timeStamp }],
179
- };
180
- };
181
- #onMove = (event) => {
182
- const gesture = this.#current(event);
183
- if (!gesture) {
184
- return;
185
- }
186
- const dx = event.clientX - gesture.startX;
187
- const dy = event.clientY - gesture.startY;
188
- if (!gesture.dragging) {
189
- if (Math.max(Math.abs(dx), Math.abs(dy)) < SLOP) {
190
- return;
191
- }
192
- if (Math.abs(dx) > Math.abs(dy)) {
193
- this.#gesture = null;
194
- return;
195
- }
196
- gesture.dragging = true;
197
- gesture.height = this.#panel.getBoundingClientRect().height;
198
- this.#panel.setAttribute('data-dragging', '');
199
- }
200
- gesture.offset = Math.max(0, dy);
201
- gesture.samples.push({ y: event.clientY, at: event.timeStamp });
202
- this.#panel.style.setProperty('--drag-y', `${gesture.offset}px`);
203
- };
204
- #onUp = (event) => {
205
- const gesture = this.#current(event);
206
- if (!gesture) {
207
- return;
208
- }
209
- this.#gesture = null;
210
- if (!gesture.dragging) {
211
- return;
212
- }
213
- this.#panel.removeAttribute('data-dragging');
214
- const release = { y: event.clientY, at: event.timeStamp };
215
- if (gesture.offset > gesture.height * DISMISS_RATIO || releaseSpeed(gesture.samples, release) > DISMISS_SPEED) {
216
- this.#dismiss();
217
- }
218
- else {
219
- this.reset();
220
- }
221
- };
222
- #onCancel = (event) => {
223
- if (this.#current(event)) {
224
- this.#gesture = null;
225
- this.#panel.removeAttribute('data-dragging');
226
- this.reset();
227
- }
228
- };
229
- #current(event) {
230
- return this.#gesture?.id === event.pointerId ? this.#gesture : null;
231
- }
232
- }
105
+ const CONTROLS = "button, a, input, select, textarea, [role=\"button\"]";
106
+ var SheetDrag = class {
107
+ #panel;
108
+ #grips;
109
+ #dismiss;
110
+ #enabled;
111
+ #gesture = null;
112
+ constructor(panel, grips, dismiss, enabled) {
113
+ this.#panel = panel;
114
+ this.#grips = grips;
115
+ this.#dismiss = dismiss;
116
+ this.#enabled = enabled;
117
+ for (const grip of grips) {
118
+ grip.addEventListener("pointerdown", this.#onDown);
119
+ grip.addEventListener("pointermove", this.#onMove);
120
+ grip.addEventListener("pointerup", this.#onUp);
121
+ grip.addEventListener("pointercancel", this.#onCancel);
122
+ }
123
+ }
124
+ reset() {
125
+ this.#gesture = null;
126
+ this.#panel.removeAttribute("data-dragging");
127
+ this.#panel.style.removeProperty("--drag-y");
128
+ }
129
+ destroy() {
130
+ for (const grip of this.#grips) {
131
+ grip.removeEventListener("pointerdown", this.#onDown);
132
+ grip.removeEventListener("pointermove", this.#onMove);
133
+ grip.removeEventListener("pointerup", this.#onUp);
134
+ grip.removeEventListener("pointercancel", this.#onCancel);
135
+ }
136
+ }
137
+ #onDown = (event) => {
138
+ const grip = event.currentTarget;
139
+ if (event.button !== 0 || !this.#enabled() || !isSheet() || event.target.closest(CONTROLS)) return;
140
+ grip.setPointerCapture(event.pointerId);
141
+ this.#gesture = {
142
+ id: event.pointerId,
143
+ startX: event.clientX,
144
+ startY: event.clientY,
145
+ dragging: false,
146
+ height: 0,
147
+ offset: 0,
148
+ samples: [{
149
+ y: event.clientY,
150
+ at: event.timeStamp
151
+ }]
152
+ };
153
+ };
154
+ #onMove = (event) => {
155
+ const gesture = this.#current(event);
156
+ if (!gesture) return;
157
+ const dx = event.clientX - gesture.startX;
158
+ const dy = event.clientY - gesture.startY;
159
+ if (!gesture.dragging) {
160
+ if (Math.max(Math.abs(dx), Math.abs(dy)) < SLOP) return;
161
+ if (Math.abs(dx) > Math.abs(dy)) {
162
+ this.#gesture = null;
163
+ return;
164
+ }
165
+ gesture.dragging = true;
166
+ gesture.height = this.#panel.getBoundingClientRect().height;
167
+ this.#panel.setAttribute("data-dragging", "");
168
+ }
169
+ gesture.offset = Math.max(0, dy);
170
+ gesture.samples.push({
171
+ y: event.clientY,
172
+ at: event.timeStamp
173
+ });
174
+ this.#panel.style.setProperty("--drag-y", `${gesture.offset}px`);
175
+ };
176
+ #onUp = (event) => {
177
+ const gesture = this.#current(event);
178
+ if (!gesture) return;
179
+ this.#gesture = null;
180
+ if (!gesture.dragging) return;
181
+ this.#panel.removeAttribute("data-dragging");
182
+ const release = {
183
+ y: event.clientY,
184
+ at: event.timeStamp
185
+ };
186
+ if (gesture.offset > gesture.height * DISMISS_RATIO || releaseSpeed(gesture.samples, release) > DISMISS_SPEED) this.#dismiss();
187
+ else this.reset();
188
+ };
189
+ #onCancel = (event) => {
190
+ if (this.#current(event)) {
191
+ this.#gesture = null;
192
+ this.#panel.removeAttribute("data-dragging");
193
+ this.reset();
194
+ }
195
+ };
196
+ #current(event) {
197
+ return this.#gesture?.id === event.pointerId ? this.#gesture : null;
198
+ }
199
+ };
233
200
  function isSheet() {
234
- return typeof matchMedia === 'function' && !matchMedia('(min-width: 64rem)').matches;
201
+ return typeof matchMedia === "function" && !matchMedia("(min-width: 64rem)").matches;
235
202
  }
236
203
  function releaseSpeed(samples, last) {
237
- const first = samples.find((sample) => sample.at >= last.at - SPEED_WINDOW) ?? last;
238
- const elapsed = last.at - first.at;
239
- return elapsed > 0 ? (last.y - first.y) / elapsed : 0;
204
+ const first = samples.find((sample) => sample.at >= last.at - SPEED_WINDOW) ?? last;
205
+ const elapsed = last.at - first.at;
206
+ return elapsed > 0 ? (last.y - first.y) / elapsed : 0;
240
207
  }
241
-
242
- /** Named dialog widths; any other CSS length is accepted as is. `DialogWidth` is derived from this tuple. */
243
- const DIALOG_WIDTHS = ['md', 'lg'];
208
+ const DIALOG_WIDTHS = ["md", "lg"];
244
209
  const WIDTH_VALUES = {
245
- md: '28rem',
246
- lg: '560px',
210
+ md: "28rem",
211
+ lg: "560px"
247
212
  };
248
- /** Spacing presets. `DialogLayout` is derived from this tuple. */
249
- const DIALOG_LAYOUTS = ['trade', 'form', 'list', 'confirm'];
250
- const LAYOUTS = {
251
- trade: {
252
- dialog: '',
253
- header: 'items-start lg:pt-6',
254
- title: 'pt-1 lg:pt-0',
255
- cross: 'lg:-mt-1.5',
256
- icon: 'lg:size-5',
257
- handle: 'pt-[7.5px]',
258
- body: 'pt-3 pb-4 lg:pt-5 lg:pb-5',
259
- footer: 'max-lg:pb-[calc(8px+env(safe-area-inset-bottom))] lg:pb-6',
260
- },
261
- form: {
262
- dialog: '',
263
- header: 'items-center lg:pt-6',
264
- title: '',
265
- cross: '',
266
- icon: 'lg:size-[22px]',
267
- handle: 'pt-[7.5px]',
268
- body: 'pt-2 pb-5 lg:pt-4 lg:pb-5',
269
- footer: 'max-lg:pb-[calc(12px+env(safe-area-inset-bottom))] lg:pb-5',
270
- },
271
- list: {
272
- dialog: 'max-lg:h-[calc(100dvh-58px)] lg:mt-24 lg:mb-auto lg:max-h-[min(760px,calc(100dvh-96px-32px))]',
273
- header: 'items-center lg:pt-5',
274
- title: '',
275
- cross: '',
276
- icon: 'lg:size-[22px]',
277
- handle: 'pt-[7.5px]',
278
- body: 'pt-2 pb-4 lg:pt-4 lg:pb-5',
279
- footer: 'pt-3 shadow-[0_-1px_0_var(--hairline)] max-lg:pb-[calc(8px+env(safe-area-inset-bottom))] lg:pt-4 lg:pb-4',
280
- },
281
- confirm: {
282
- dialog: '',
283
- header: 'items-center pt-3 lg:pt-6',
284
- title: '',
285
- cross: '',
286
- icon: 'lg:size-[22px]',
287
- handle: 'pt-[11.5px]',
288
- body: 'pt-3 pb-5 lg:pt-3 lg:pb-6',
289
- footer: 'max-lg:pb-[calc(8px+env(safe-area-inset-bottom))] lg:pb-6',
290
- },
213
+ const DIALOG_VARIANTS = ["default", "confirm"];
214
+ const DIALOG_SHEETS = ["fit", "full"];
215
+ const VARIANTS = {
216
+ default: {
217
+ handle: "pt-[7.5px]",
218
+ header: "pb-3 lg:py-4 lg:pl-6",
219
+ body: "py-4 lg:py-5",
220
+ footer: "pt-3 empty:hidden lg:py-4"
221
+ },
222
+ confirm: {
223
+ handle: "pt-[11.5px]",
224
+ header: "pt-3 lg:pt-6 lg:pl-6",
225
+ body: "pt-3",
226
+ footer: "not-empty:pt-5 lg:pb-6 lg:not-empty:pt-6"
227
+ }
291
228
  };
292
- /** What started a close, as `closed` reports it. `DialogCloseReason` is derived from this tuple. */
293
- const DIALOG_CLOSE_REASONS = ['escape', 'backdrop', 'cross', 'drag', 'programmatic'];
229
+ const DEFAULT_WIDTHS = {
230
+ default: "lg",
231
+ confirm: "440px"
232
+ };
233
+ const DIALOG_CLOSE_REASONS = [
234
+ "escape",
235
+ "backdrop",
236
+ "cross",
237
+ "drag",
238
+ "programmatic"
239
+ ];
294
240
  const nextId = (() => {
295
- let count = 0;
296
- return () => `ui-dialog-${++count}`;
241
+ let count = 0;
242
+ return () => `ui-dialog-${++count}`;
297
243
  })();
298
- /**
299
- * Modal dialog on the native <dialog>: a bottom sheet under `64rem`, centered above it.
300
- *
301
- * `busy` keeps it open while its action runs: Escape, a click on the backdrop and a drag of the sheet do
302
- * nothing and the cross is disabled. The owner disables its own buttons and still closes it through `open`.
303
- *
304
- * @example
305
- * <ui-dialog heading="Buy" description="Ferrari" closeLabel="Close" width="528px" [open]="buying()" (dismissed)="buying.set(false)">
306
- * <p>Body</p>
307
- * <button dialogActions ui-button variant="outline" class="max-lg:hidden" (click)="buying.set(false)">Cancel</button>
308
- * <button dialogActions ui-button>Buy 40 shares</button>
309
- * </ui-dialog>
310
- */
311
- class UiDialog {
312
- heading = input.required(/* @ts-ignore */
313
- ...(ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []));
314
- description = input(/* @ts-ignore */
315
- ...(ngDevMode ? [undefined, { debugName: "description" }] : /* istanbul ignore next */ []));
316
- closeLabel = input(/* @ts-ignore */
317
- ...(ngDevMode ? [undefined, { debugName: "closeLabel" }] : /* istanbul ignore next */ []));
318
- layout = input('trade', /* @ts-ignore */
319
- ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
320
- truncateDescription = input(false, { ...(ngDevMode ? { debugName: "truncateDescription" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
321
- width = input('lg', /* @ts-ignore */
322
- ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
323
- open = input(false, { ...(ngDevMode ? { debugName: "open" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
324
- busy = input(false, { ...(ngDevMode ? { debugName: "busy" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
325
- dismissed = output();
326
- closed = output();
327
- headingId = nextId();
328
- descriptionId = `${this.headingId}-description`;
329
- bodyId = `${this.headingId}-body`;
330
- scrollable = signal(false, /* @ts-ignore */
331
- ...(ngDevMode ? [{ debugName: "scrollable" }] : /* istanbul ignore next */ []));
332
- describedBy = computed(() => {
333
- if (this.description()) {
334
- return this.descriptionId;
335
- }
336
- return this.layout() === 'confirm' ? this.bodyId : null;
337
- }, /* @ts-ignore */
338
- ...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
339
- widthValue = computed(() => {
340
- const width = this.width();
341
- return Object.hasOwn(WIDTH_VALUES, width) ? WIDTH_VALUES[width] : width;
342
- }, /* @ts-ignore */
343
- ...(ngDevMode ? [{ debugName: "widthValue" }] : /* istanbul ignore next */ []));
344
- spec = computed(() => LAYOUTS[this.layout()], /* @ts-ignore */
345
- ...(ngDevMode ? [{ debugName: "spec" }] : /* istanbul ignore next */ []));
346
- headerClasses = computed(() => `flex gap-2 pl-4 max-lg:touch-none lg:gap-3 lg:pl-6 ${this.spec().header} ${this.closeLabel() ? 'pr-2 lg:pr-4' : 'pr-4 lg:pr-6'}`, /* @ts-ignore */
347
- ...(ngDevMode ? [{ debugName: "headerClasses" }] : /* istanbul ignore next */ []));
348
- titleClasses = computed(() => this.spec().title, /* @ts-ignore */
349
- ...(ngDevMode ? [{ debugName: "titleClasses" }] : /* istanbul ignore next */ []));
350
- crossClasses = computed(() => `rounded-pill lg:rounded-control grid size-11 flex-none cursor-pointer place-items-center text-(--muted-foreground) transition-[scale,background-color,color] [transition-duration:var(--duration-press),var(--duration-fast),var(--duration-fast)] ease-out outline-none focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-(--ring) active:scale-(--press-scale) active:bg-(--soft) disabled:pointer-events-none disabled:opacity-40 lg:size-9 lg:hover:bg-(--glow) lg:hover:text-(--foreground) ${this.spec().cross}`, /* @ts-ignore */
351
- ...(ngDevMode ? [{ debugName: "crossClasses" }] : /* istanbul ignore next */ []));
352
- iconClasses = computed(() => this.spec().icon, /* @ts-ignore */
353
- ...(ngDevMode ? [{ debugName: "iconClasses" }] : /* istanbul ignore next */ []));
354
- footerClasses = computed(() => `max-lg:[&>[ui-button]]:text-body flex justify-end gap-2 px-4 empty:hidden max-lg:flex-col-reverse max-lg:[&>[ui-button]]:h-[50px] max-lg:[&>[ui-button]]:w-full lg:px-6 ${this.spec().footer}`, /* @ts-ignore */
355
- ...(ngDevMode ? [{ debugName: "footerClasses" }] : /* istanbul ignore next */ []));
356
- classes = computed(() => `open:flex w-full flex-col overflow-hidden m-auto mt-auto max-h-[calc(100dvh-2rem)] max-lg:mb-0 max-lg:max-w-none max-lg:rounded-b-none lg:max-w-(--dialog-width) rounded-container bg-(--card) text-(--foreground) shadow-[0_0_0_1px_var(--border),0_24px_64px_rgb(0_0_0/0.24)] max-lg:shadow-[0_-1px_0_var(--border),0_-12px_32px_rgb(0_0_0/0.16)] backdrop:bg-black/[0.36] ${this.spec().dialog}`, /* @ts-ignore */
357
- ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
358
- #host = inject(ElementRef);
359
- constructor() {
360
- const destroyRef = inject(DestroyRef);
361
- afterNextRender(() => {
362
- const host = this.#host.nativeElement;
363
- const grips = ['[data-dialog-handle]', '[data-dialog-header]'].map((grip) => host.querySelector(grip));
364
- this.#drag = new SheetDrag(this.#dialog, grips, () => this.close('drag'), () => !this.busy());
365
- destroyRef.onDestroy(() => {
366
- this.#drag?.destroy();
367
- this.#cancelExit();
368
- });
369
- if (typeof ResizeObserver === 'undefined') {
370
- return;
371
- }
372
- const body = this.#host.nativeElement.querySelector('[data-dialog-body]');
373
- const observer = new ResizeObserver(() => this.scrollable.set(body.scrollHeight > body.clientHeight));
374
- observer.observe(body);
375
- observer.observe(body.firstElementChild);
376
- destroyRef.onDestroy(() => observer.disconnect());
377
- });
378
- afterRenderEffect(() => {
379
- // viewChild.required can't target a #private field (NG1053); safe because the template has exactly one <dialog>.
380
- const dialog = this.#host.nativeElement.querySelector('dialog');
381
- if (this.open() && !dialog.open) {
382
- this.#cancelExit();
383
- this.#drag?.reset();
384
- dialog.showModal();
385
- }
386
- else if (!this.open() && dialog.open) {
387
- this.close('programmatic');
388
- }
389
- });
390
- }
391
- #pressedOnBackdrop = false;
392
- #drag = null;
393
- #reason = null;
394
- #cancelExit = () => undefined;
395
- close(reason) {
396
- if (this.#dialog.open) {
397
- this.#reason = reason;
398
- this.#dialog.close();
399
- }
400
- }
401
- onCancel(event) {
402
- if (event.target !== event.currentTarget) {
403
- return;
404
- }
405
- event.preventDefault();
406
- if (!this.busy()) {
407
- this.close('escape');
408
- }
409
- }
410
- onKeydown(event) {
411
- if (event.key === 'Escape' && this.busy()) {
412
- event.preventDefault();
413
- }
414
- }
415
- onPointerDown(event) {
416
- this.#pressedOnBackdrop = event.target === this.#dialog && this.#outside(event);
417
- }
418
- onClick(event) {
419
- if (this.#pressedOnBackdrop && !this.busy() && event.target === this.#dialog && this.#outside(event)) {
420
- this.close('backdrop');
421
- }
422
- this.#pressedOnBackdrop = false;
423
- }
424
- get #dialog() {
425
- return this.#host.nativeElement.querySelector('dialog');
426
- }
427
- #outside(event) {
428
- const rect = this.#dialog.getBoundingClientRect();
429
- return (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom);
430
- }
431
- onNativeClose() {
432
- const asked = this.#reason;
433
- this.#reason = null;
434
- if (this.#dialog.open) {
435
- return;
436
- }
437
- if (asked === null && this.busy()) {
438
- this.#dialog.showModal();
439
- return;
440
- }
441
- const reason = asked ?? 'escape';
442
- if (reason !== 'programmatic') {
443
- this.dismissed.emit();
444
- }
445
- this.#awaitExit(reason);
446
- }
447
- #awaitExit(reason) {
448
- this.#cancelExit();
449
- this.#cancelExit = afterExit(this.#dialog, () => {
450
- this.#cancelExit = () => undefined;
451
- this.#drag?.reset();
452
- this.closed.emit(reason);
453
- });
454
- }
455
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
456
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: UiDialog, isStandalone: true, selector: "ui-dialog", inputs: { heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, truncateDescription: { classPropertyName: "truncateDescription", publicName: "truncateDescription", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed", closed: "closed" }, host: { listeners: { "pointerdown": "onPointerDown($event)", "click": "onClick($event)", "keydown": "onKeydown($event)" } }, ngImport: i0, template: `
244
+ var UiDialog = class UiDialog {
245
+ heading = input.required(...ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []);
246
+ description = input(...ngDevMode ? [void 0, { debugName: "description" }] : /* istanbul ignore next */ []);
247
+ closeLabel = input(...ngDevMode ? [void 0, { debugName: "closeLabel" }] : /* istanbul ignore next */ []);
248
+ variant = input("default", ...ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []);
249
+ sheet = input("fit", ...ngDevMode ? [{ debugName: "sheet" }] : /* istanbul ignore next */ []);
250
+ truncateDescription = input(false, {
251
+ ...ngDevMode ? { debugName: "truncateDescription" } : /* istanbul ignore next */ {},
252
+ transform: booleanAttribute
253
+ });
254
+ width = input(...ngDevMode ? [void 0, { debugName: "width" }] : /* istanbul ignore next */ []);
255
+ open = input(false, {
256
+ ...ngDevMode ? { debugName: "open" } : /* istanbul ignore next */ {},
257
+ transform: booleanAttribute
258
+ });
259
+ busy = input(false, {
260
+ ...ngDevMode ? { debugName: "busy" } : /* istanbul ignore next */ {},
261
+ transform: booleanAttribute
262
+ });
263
+ dismissed = output();
264
+ closed = output();
265
+ headingId = nextId();
266
+ descriptionId = `${this.headingId}-description`;
267
+ bodyId = `${this.headingId}-body`;
268
+ scrollable = signal(false, ...ngDevMode ? [{ debugName: "scrollable" }] : /* istanbul ignore next */ []);
269
+ stacked = signal(false, ...ngDevMode ? [{ debugName: "stacked" }] : /* istanbul ignore next */ []);
270
+ describedBy = computed(() => {
271
+ if (this.description()) return this.descriptionId;
272
+ return this.variant() === "confirm" ? this.bodyId : null;
273
+ }, ...ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []);
274
+ widthValue = computed(() => {
275
+ const width = this.width() ?? DEFAULT_WIDTHS[this.variant()];
276
+ return Object.hasOwn(WIDTH_VALUES, width) ? WIDTH_VALUES[width] : width;
277
+ }, ...ngDevMode ? [{ debugName: "widthValue" }] : /* istanbul ignore next */ []);
278
+ spec = computed(() => VARIANTS[this.variant()], ...ngDevMode ? [{ debugName: "spec" }] : /* istanbul ignore next */ []);
279
+ hairlines = computed(() => Boolean(this.closeLabel()) && this.variant() === "default", ...ngDevMode ? [{ debugName: "hairlines" }] : /* istanbul ignore next */ []);
280
+ headerClasses = computed(() => `flex items-start gap-2 pl-4 max-lg:touch-none lg:gap-3 ${this.spec().header} ${this.closeLabel() ? "pr-2 lg:pr-4" : "pr-4 lg:pr-6"} ${this.hairlines() ? "shadow-[inset_0_-1px_0_var(--hairline)]" : ""}`, ...ngDevMode ? [{ debugName: "headerClasses" }] : /* istanbul ignore next */ []);
281
+ crossClasses = "rounded-pill lg:rounded-control grid size-11 flex-none cursor-pointer place-items-center text-(--muted-foreground) transition-[scale,background-color,color] [transition-duration:var(--duration-press),var(--duration-fast),var(--duration-fast)] ease-out outline-none focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-(--ring) active:scale-(--press-scale) active:bg-(--soft) disabled:pointer-events-none disabled:opacity-40 lg:size-9 lg:hover:bg-(--glow) lg:hover:text-(--foreground)";
282
+ footerClasses = computed(() => `max-lg:[&>[ui-button]]:text-body flex justify-end gap-2 px-4 pb-[calc(8px+env(safe-area-inset-bottom))] max-lg:flex-col-reverse max-lg:[&>[ui-button]]:h-[50px] max-lg:[&>[ui-button]]:w-full lg:px-6 ${this.spec().footer} ${this.hairlines() ? "shadow-[inset_0_1px_0_var(--hairline)]" : ""}`, ...ngDevMode ? [{ debugName: "footerClasses" }] : /* istanbul ignore next */ []);
283
+ classes = computed(() => `open:flex w-full flex-col overflow-hidden m-auto mt-auto max-lg:max-h-[calc(100dvh-2rem)] lg:max-h-[calc(100dvh-96px)] max-lg:mb-0 max-lg:max-w-none max-lg:rounded-b-none lg:max-w-(--dialog-width) rounded-container bg-(--card) text-(--foreground) outline-none shadow-[0_0_0_1px_var(--border),0_24px_64px_rgb(0_0_0/0.24)] max-lg:shadow-[0_-1px_0_var(--border),0_-12px_32px_rgb(0_0_0/0.16)] ${this.stacked() ? "backdrop:bg-black/[0.24]" : "backdrop:bg-black/[0.36]"} ${this.sheet() === "full" ? "max-lg:h-[calc(100dvh-58px)]" : ""}`, ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
284
+ #host = inject(ElementRef);
285
+ #drag = null;
286
+ modal;
287
+ constructor() {
288
+ const destroyRef = inject(DestroyRef);
289
+ afterNextRender(() => {
290
+ const host = this.#host.nativeElement;
291
+ const dialog = host.querySelector("dialog");
292
+ const grips = ["[data-dialog-handle]", "[data-dialog-header]"].map((grip) => host.querySelector(grip));
293
+ this.#drag = new SheetDrag(dialog, grips, () => this.modal.close("drag"), () => !this.busy());
294
+ destroyRef.onDestroy(() => this.#drag?.destroy());
295
+ if (typeof ResizeObserver === "undefined") return;
296
+ const body = host.querySelector("[data-dialog-body]");
297
+ const observer = new ResizeObserver(() => this.scrollable.set(body.scrollHeight > body.clientHeight));
298
+ observer.observe(body);
299
+ observer.observe(body.firstElementChild);
300
+ destroyRef.onDestroy(() => observer.disconnect());
301
+ });
302
+ this.modal = new ModalClose({
303
+ open: this.open,
304
+ busy: this.busy,
305
+ dismissed: this.dismissed,
306
+ closed: this.closed,
307
+ reset: () => this.#drag?.reset(),
308
+ opening: () => this.stacked.set(this.#overAnotherModal())
309
+ });
310
+ }
311
+ #overAnotherModal() {
312
+ const open = this.#host.nativeElement.ownerDocument.querySelectorAll("dialog[open]");
313
+ return Array.from(open).some((dialog) => dialog.matches(":modal"));
314
+ }
315
+ static ɵfac = i0.ɵɵngDeclareFactory({
316
+ minVersion: "12.0.0",
317
+ version: "22.2.0",
318
+ ngImport: i0,
319
+ type: UiDialog,
320
+ deps: [],
321
+ target: i0.ɵɵFactoryTarget.Component
322
+ });
323
+ static ɵcmp = i0.ɵɵngDeclareComponent({
324
+ minVersion: "17.0.0",
325
+ version: "22.2.0",
326
+ type: UiDialog,
327
+ isStandalone: true,
328
+ selector: "ui-dialog",
329
+ inputs: {
330
+ heading: {
331
+ classPropertyName: "heading",
332
+ publicName: "heading",
333
+ isSignal: true,
334
+ isRequired: true,
335
+ transformFunction: null
336
+ },
337
+ description: {
338
+ classPropertyName: "description",
339
+ publicName: "description",
340
+ isSignal: true,
341
+ isRequired: false,
342
+ transformFunction: null
343
+ },
344
+ closeLabel: {
345
+ classPropertyName: "closeLabel",
346
+ publicName: "closeLabel",
347
+ isSignal: true,
348
+ isRequired: false,
349
+ transformFunction: null
350
+ },
351
+ variant: {
352
+ classPropertyName: "variant",
353
+ publicName: "variant",
354
+ isSignal: true,
355
+ isRequired: false,
356
+ transformFunction: null
357
+ },
358
+ sheet: {
359
+ classPropertyName: "sheet",
360
+ publicName: "sheet",
361
+ isSignal: true,
362
+ isRequired: false,
363
+ transformFunction: null
364
+ },
365
+ truncateDescription: {
366
+ classPropertyName: "truncateDescription",
367
+ publicName: "truncateDescription",
368
+ isSignal: true,
369
+ isRequired: false,
370
+ transformFunction: null
371
+ },
372
+ width: {
373
+ classPropertyName: "width",
374
+ publicName: "width",
375
+ isSignal: true,
376
+ isRequired: false,
377
+ transformFunction: null
378
+ },
379
+ open: {
380
+ classPropertyName: "open",
381
+ publicName: "open",
382
+ isSignal: true,
383
+ isRequired: false,
384
+ transformFunction: null
385
+ },
386
+ busy: {
387
+ classPropertyName: "busy",
388
+ publicName: "busy",
389
+ isSignal: true,
390
+ isRequired: false,
391
+ transformFunction: null
392
+ }
393
+ },
394
+ outputs: {
395
+ dismissed: "dismissed",
396
+ closed: "closed"
397
+ },
398
+ host: { listeners: {
399
+ "pointerdown": "modal.onPointerDown($event)",
400
+ "click": "modal.onClick($event)",
401
+ "keydown": "modal.onKeydown($event)"
402
+ } },
403
+ ngImport: i0,
404
+ template: `
457
405
  <dialog
458
406
  #dlg
459
407
  [attr.aria-busy]="busy() || null"
460
408
  [attr.aria-describedby]="describedBy()"
461
409
  [attr.aria-labelledby]="headingId"
462
- [attr.role]="layout() === 'confirm' ? 'alertdialog' : 'dialog'"
410
+ [attr.role]="variant() === 'confirm' ? 'alertdialog' : 'dialog'"
463
411
  [class]="classes()"
464
412
  [style.--dialog-width]="widthValue()"
465
- (cancel)="onCancel($event)"
466
- (close)="onNativeClose()"
413
+ (cancel)="modal.onCancel($event)"
414
+ (close)="modal.onNativeClose()"
467
415
  >
468
416
  <div
469
417
  aria-hidden="true"
@@ -475,7 +423,7 @@ class UiDialog {
475
423
  </div>
476
424
 
477
425
  <div data-dialog-header [class]="headerClasses()">
478
- <div class="flex min-w-0 flex-1 flex-col" [class]="titleClasses()">
426
+ <div class="flex min-w-0 flex-1 flex-col" [class.max-lg:pt-1]="description()">
479
427
  <h2 class="text-title font-semibold" [id]="headingId">{{ heading() }}</h2>
480
428
 
481
429
  @if (description()) {
@@ -493,9 +441,9 @@ class UiDialog {
493
441
  <button
494
442
  type="button"
495
443
  [attr.aria-label]="closeLabel()"
496
- [class]="crossClasses()"
444
+ [class]="crossClasses"
497
445
  [disabled]="busy()"
498
- (click)="close('cross')"
446
+ (click)="modal.close('cross')"
499
447
  >
500
448
  <svg
501
449
  aria-hidden="true"
@@ -503,7 +451,6 @@ class UiDialog {
503
451
  stroke-linecap="round"
504
452
  stroke-linejoin="round"
505
453
  viewBox="0 0 24 24"
506
- [class]="iconClasses()"
507
454
  >
508
455
  <path d="M18 6 6 18" />
509
456
  <path d="m6 6 12 12" />
@@ -520,7 +467,6 @@ class UiDialog {
520
467
  [attr.tabindex]="scrollable() ? 0 : null"
521
468
  [id]="bodyId"
522
469
  >
523
- <!-- empty:hidden keeps a body-less dialog from carrying the body's vertical padding. -->
524
470
  <div class="flex flex-col gap-4 empty:hidden" [class]="spec().body">
525
471
  <ng-content />
526
472
  </div>
@@ -530,25 +476,36 @@ class UiDialog {
530
476
  <ng-content select="[dialogActions]" />
531
477
  </div>
532
478
  </dialog>
533
- `, isInline: true, styles: ["dialog{--dialog-ease: var(--ease-sheet);transition:transform var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;transform:translateY(var(--drag-y, 0px))}dialog:not([open]){transform:translateY(100%);transition-duration:var(--duration-exit)}@starting-style{dialog[open]{transform:translateY(100%)}}dialog[data-dragging]{transition:none}@media(prefers-reduced-motion:reduce){dialog{transition:opacity var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;opacity:1}dialog:not([open]){opacity:0;transform:translateY(var(--drag-y, 0px))}@starting-style{dialog[open]{opacity:0;transform:translateY(0)}}}@media(min-width:64rem){dialog{--dialog-ease: var(--ease-out);transition:opacity var(--duration-base) var(--dialog-ease),transform var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;opacity:1;transform:scale(1)}dialog:not([open]){opacity:0;transform:scale(var(--enter-scale))}@starting-style{dialog[open]{opacity:0;transform:scale(var(--enter-scale))}}}dialog::backdrop{transition:opacity var(--duration-base) var(--ease-out);opacity:1}dialog:not([open])::backdrop{opacity:0;transition-duration:var(--duration-exit)}@starting-style{dialog[open]::backdrop{opacity:0}}\n"] });
534
- }
535
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiDialog, decorators: [{
536
- type: Component,
537
- args: [{ selector: 'ui-dialog', host: {
538
- '(pointerdown)': 'onPointerDown($event)',
539
- '(click)': 'onClick($event)',
540
- '(keydown)': 'onKeydown($event)',
541
- }, template: `
479
+ `,
480
+ isInline: true,
481
+ styles: ["dialog{--dialog-ease: var(--ease-sheet);transition:transform var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;transform:translateY(var(--drag-y, 0px))}dialog:not([open]){transform:translateY(100%);transition-duration:var(--duration-exit)}@starting-style{dialog[open]{transform:translateY(100%)}}dialog[data-dragging]{transition:none}@media(prefers-reduced-motion:reduce){dialog{transition:opacity var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;opacity:1}dialog:not([open]){opacity:0;transform:translateY(var(--drag-y, 0px))}@starting-style{dialog[open]{opacity:0;transform:translateY(0)}}}@media(min-width:64rem){dialog{--dialog-ease: var(--ease-out);transition:opacity var(--duration-base) var(--dialog-ease),transform var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;opacity:1;transform:scale(1)}dialog:not([open]){opacity:0;transform:scale(var(--enter-scale))}@starting-style{dialog[open]{opacity:0;transform:scale(var(--enter-scale))}}}dialog::backdrop{transition:opacity var(--duration-base) var(--ease-out);opacity:1}dialog:not([open])::backdrop{opacity:0;transition-duration:var(--duration-exit)}@starting-style{dialog[open]::backdrop{opacity:0}}\n"]
482
+ });
483
+ };
484
+ i0.ɵɵngDeclareClassMetadata({
485
+ minVersion: "12.0.0",
486
+ version: "22.2.0",
487
+ ngImport: i0,
488
+ type: UiDialog,
489
+ decorators: [{
490
+ type: Component,
491
+ args: [{
492
+ selector: "ui-dialog",
493
+ host: {
494
+ "(pointerdown)": "modal.onPointerDown($event)",
495
+ "(click)": "modal.onClick($event)",
496
+ "(keydown)": "modal.onKeydown($event)"
497
+ },
498
+ template: `
542
499
  <dialog
543
500
  #dlg
544
501
  [attr.aria-busy]="busy() || null"
545
502
  [attr.aria-describedby]="describedBy()"
546
503
  [attr.aria-labelledby]="headingId"
547
- [attr.role]="layout() === 'confirm' ? 'alertdialog' : 'dialog'"
504
+ [attr.role]="variant() === 'confirm' ? 'alertdialog' : 'dialog'"
548
505
  [class]="classes()"
549
506
  [style.--dialog-width]="widthValue()"
550
- (cancel)="onCancel($event)"
551
- (close)="onNativeClose()"
507
+ (cancel)="modal.onCancel($event)"
508
+ (close)="modal.onNativeClose()"
552
509
  >
553
510
  <div
554
511
  aria-hidden="true"
@@ -560,7 +517,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
560
517
  </div>
561
518
 
562
519
  <div data-dialog-header [class]="headerClasses()">
563
- <div class="flex min-w-0 flex-1 flex-col" [class]="titleClasses()">
520
+ <div class="flex min-w-0 flex-1 flex-col" [class.max-lg:pt-1]="description()">
564
521
  <h2 class="text-title font-semibold" [id]="headingId">{{ heading() }}</h2>
565
522
 
566
523
  @if (description()) {
@@ -578,9 +535,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
578
535
  <button
579
536
  type="button"
580
537
  [attr.aria-label]="closeLabel()"
581
- [class]="crossClasses()"
538
+ [class]="crossClasses"
582
539
  [disabled]="busy()"
583
- (click)="close('cross')"
540
+ (click)="modal.close('cross')"
584
541
  >
585
542
  <svg
586
543
  aria-hidden="true"
@@ -588,7 +545,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
588
545
  stroke-linecap="round"
589
546
  stroke-linejoin="round"
590
547
  viewBox="0 0 24 24"
591
- [class]="iconClasses()"
592
548
  >
593
549
  <path d="M18 6 6 18" />
594
550
  <path d="m6 6 12 12" />
@@ -605,7 +561,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
605
561
  [attr.tabindex]="scrollable() ? 0 : null"
606
562
  [id]="bodyId"
607
563
  >
608
- <!-- empty:hidden keeps a body-less dialog from carrying the body's vertical padding. -->
609
564
  <div class="flex flex-col gap-4 empty:hidden" [class]="spec().body">
610
565
  <ng-content />
611
566
  </div>
@@ -615,12 +570,94 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
615
570
  <ng-content select="[dialogActions]" />
616
571
  </div>
617
572
  </dialog>
618
- `, styles: ["dialog{--dialog-ease: var(--ease-sheet);transition:transform var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;transform:translateY(var(--drag-y, 0px))}dialog:not([open]){transform:translateY(100%);transition-duration:var(--duration-exit)}@starting-style{dialog[open]{transform:translateY(100%)}}dialog[data-dragging]{transition:none}@media(prefers-reduced-motion:reduce){dialog{transition:opacity var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;opacity:1}dialog:not([open]){opacity:0;transform:translateY(var(--drag-y, 0px))}@starting-style{dialog[open]{opacity:0;transform:translateY(0)}}}@media(min-width:64rem){dialog{--dialog-ease: var(--ease-out);transition:opacity var(--duration-base) var(--dialog-ease),transform var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;opacity:1;transform:scale(1)}dialog:not([open]){opacity:0;transform:scale(var(--enter-scale))}@starting-style{dialog[open]{opacity:0;transform:scale(var(--enter-scale))}}}dialog::backdrop{transition:opacity var(--duration-base) var(--ease-out);opacity:1}dialog:not([open])::backdrop{opacity:0;transition-duration:var(--duration-exit)}@starting-style{dialog[open]::backdrop{opacity:0}}\n"] }]
619
- }], ctorParameters: () => [], propDecorators: { heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], truncateDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "truncateDescription", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], busy: [{ type: i0.Input, args: [{ isSignal: true, alias: "busy", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
620
-
621
- /**
622
- * Generated bundle index. Do not edit.
623
- */
573
+ `,
574
+ styles: ["dialog{--dialog-ease: var(--ease-sheet);transition:transform var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;transform:translateY(var(--drag-y, 0px))}dialog:not([open]){transform:translateY(100%);transition-duration:var(--duration-exit)}@starting-style{dialog[open]{transform:translateY(100%)}}dialog[data-dragging]{transition:none}@media(prefers-reduced-motion:reduce){dialog{transition:opacity var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;opacity:1}dialog:not([open]){opacity:0;transform:translateY(var(--drag-y, 0px))}@starting-style{dialog[open]{opacity:0;transform:translateY(0)}}}@media(min-width:64rem){dialog{--dialog-ease: var(--ease-out);transition:opacity var(--duration-base) var(--dialog-ease),transform var(--duration-base) var(--dialog-ease),overlay var(--duration-base) allow-discrete,display var(--duration-base) allow-discrete;opacity:1;transform:scale(1)}dialog:not([open]){opacity:0;transform:scale(var(--enter-scale))}@starting-style{dialog[open]{opacity:0;transform:scale(var(--enter-scale))}}}dialog::backdrop{transition:opacity var(--duration-base) var(--ease-out);opacity:1}dialog:not([open])::backdrop{opacity:0;transition-duration:var(--duration-exit)}@starting-style{dialog[open]::backdrop{opacity:0}}\n"]
575
+ }]
576
+ }],
577
+ ctorParameters: () => [],
578
+ propDecorators: {
579
+ heading: [{
580
+ type: i0.Input,
581
+ args: [{
582
+ isSignal: true,
583
+ alias: "heading",
584
+ required: true
585
+ }]
586
+ }],
587
+ description: [{
588
+ type: i0.Input,
589
+ args: [{
590
+ isSignal: true,
591
+ alias: "description",
592
+ required: false
593
+ }]
594
+ }],
595
+ closeLabel: [{
596
+ type: i0.Input,
597
+ args: [{
598
+ isSignal: true,
599
+ alias: "closeLabel",
600
+ required: false
601
+ }]
602
+ }],
603
+ variant: [{
604
+ type: i0.Input,
605
+ args: [{
606
+ isSignal: true,
607
+ alias: "variant",
608
+ required: false
609
+ }]
610
+ }],
611
+ sheet: [{
612
+ type: i0.Input,
613
+ args: [{
614
+ isSignal: true,
615
+ alias: "sheet",
616
+ required: false
617
+ }]
618
+ }],
619
+ truncateDescription: [{
620
+ type: i0.Input,
621
+ args: [{
622
+ isSignal: true,
623
+ alias: "truncateDescription",
624
+ required: false
625
+ }]
626
+ }],
627
+ width: [{
628
+ type: i0.Input,
629
+ args: [{
630
+ isSignal: true,
631
+ alias: "width",
632
+ required: false
633
+ }]
634
+ }],
635
+ open: [{
636
+ type: i0.Input,
637
+ args: [{
638
+ isSignal: true,
639
+ alias: "open",
640
+ required: false
641
+ }]
642
+ }],
643
+ busy: [{
644
+ type: i0.Input,
645
+ args: [{
646
+ isSignal: true,
647
+ alias: "busy",
648
+ required: false
649
+ }]
650
+ }],
651
+ dismissed: [{
652
+ type: i0.Output,
653
+ args: ["dismissed"]
654
+ }],
655
+ closed: [{
656
+ type: i0.Output,
657
+ args: ["closed"]
658
+ }]
659
+ }
660
+ });
661
+ export { DIALOG_CLOSE_REASONS, DIALOG_SHEETS, DIALOG_VARIANTS, DIALOG_WIDTHS, ModalClose, UiDialog };
624
662
 
625
- export { DIALOG_CLOSE_REASONS, DIALOG_LAYOUTS, DIALOG_WIDTHS, UiDialog };
626
- //# sourceMappingURL=joanroucoux-cairn-ui-dialog.mjs.map
663
+ //# sourceMappingURL=joanroucoux-cairn-ui-dialog.mjs.map