@krollins/blueprint 0.1.12 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/accordion.js +393 -0
- package/dist/components/accordion.js.map +1 -0
- package/dist/components/alert.js +213 -0
- package/dist/components/alert.js.map +1 -0
- package/dist/components/avatar.js +237 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.js +144 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/breadcrumb.js +481 -0
- package/dist/components/breadcrumb.js.map +1 -0
- package/dist/components/button.js +192 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/card.js +223 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/checkbox.js +337 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/color-picker.js +1660 -0
- package/dist/components/color-picker.js.map +1 -0
- package/dist/components/combobox.js +595 -0
- package/dist/components/combobox.js.map +1 -0
- package/dist/components/date-picker.js +726 -0
- package/dist/components/date-picker.js.map +1 -0
- package/dist/components/divider.js +214 -0
- package/dist/components/divider.js.map +1 -0
- package/dist/components/drawer.js +568 -0
- package/dist/components/drawer.js.map +1 -0
- package/dist/components/dropdown.js +377 -0
- package/dist/components/dropdown.js.map +1 -0
- package/dist/components/file-upload.js +669 -0
- package/dist/components/file-upload.js.map +1 -0
- package/dist/components/heading.js +161 -0
- package/dist/components/heading.js.map +1 -0
- package/dist/components/icon.js +599 -0
- package/dist/components/icon.js.map +1 -0
- package/dist/components/input.js +363 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/link.js +178 -0
- package/dist/components/link.js.map +1 -0
- package/dist/components/menu.js +331 -0
- package/dist/components/menu.js.map +1 -0
- package/dist/components/modal.js +317 -0
- package/dist/components/modal.js.map +1 -0
- package/dist/components/multi-select.js +642 -0
- package/dist/components/multi-select.js.map +1 -0
- package/dist/components/notification.js +429 -0
- package/dist/components/notification.js.map +1 -0
- package/dist/components/number-input.js +556 -0
- package/dist/components/number-input.js.map +1 -0
- package/dist/components/pagination.js +320 -0
- package/dist/components/pagination.js.map +1 -0
- package/dist/components/popover.js +597 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/progress.js +219 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/radio.js +321 -0
- package/dist/components/radio.js.map +1 -0
- package/dist/components/select.js +498 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/skeleton.js +240 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/slider.js +9 -0
- package/dist/components/slider.js.map +1 -0
- package/dist/components/spinner.js +133 -0
- package/dist/components/spinner.js.map +1 -0
- package/dist/components/stepper.js +812 -0
- package/dist/components/stepper.js.map +1 -0
- package/dist/components/switch.js +380 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/table.js +642 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/tabs.js +547 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/tag.js +291 -0
- package/dist/components/tag.js.map +1 -0
- package/dist/components/text.js +278 -0
- package/dist/components/text.js.map +1 -0
- package/dist/components/textarea.js +380 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/time-picker.js +457 -0
- package/dist/components/time-picker.js.map +1 -0
- package/dist/components/tooltip.js +239 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/tree.js +582 -0
- package/dist/components/tree.js.map +1 -0
- package/dist/index.js +93 -17799
- package/dist/index.js.map +1 -1
- package/dist/shared/boolean-converter-XDGfS9LC.js +12 -0
- package/dist/shared/boolean-converter-XDGfS9LC.js.map +1 -0
- package/dist/shared/debounce-BckY30Sf.js +23 -0
- package/dist/shared/debounce-BckY30Sf.js.map +1 -0
- package/dist/shared/memoize-DlOFy-92.js +16 -0
- package/dist/shared/memoize-DlOFy-92.js.map +1 -0
- package/dist/shared/slider-BNt5TITl.js +484 -0
- package/dist/shared/slider-BNt5TITl.js.map +1 -0
- package/package.json +44 -2
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { css as v, LitElement as m, html as a, nothing as f } from "lit";
|
|
2
|
+
import { property as o, state as g, customElement as b } from "lit/decorators.js";
|
|
3
|
+
const h = v`
|
|
4
|
+
/* Base styles - Menu Container */
|
|
5
|
+
:host {
|
|
6
|
+
display: block;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.menu {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
min-width: 200px;
|
|
13
|
+
padding: var(--bp-spacing-xs) 0;
|
|
14
|
+
margin: 0;
|
|
15
|
+
background-color: var(--bp-color-surface-elevated);
|
|
16
|
+
border: var(--bp-border-width) solid var(--bp-color-border);
|
|
17
|
+
border-radius: var(--bp-border-radius-md);
|
|
18
|
+
box-shadow: var(--bp-shadow-lg);
|
|
19
|
+
font-family: var(--bp-font-sans);
|
|
20
|
+
list-style: none;
|
|
21
|
+
outline: none;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Menu Sizes */
|
|
25
|
+
.menu--sm {
|
|
26
|
+
min-width: 160px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.menu--lg {
|
|
30
|
+
min-width: 280px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Menu Item Base */
|
|
34
|
+
.menu-item {
|
|
35
|
+
position: relative;
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
gap: var(--bp-spacing-sm);
|
|
39
|
+
padding: var(--bp-spacing-sm) var(--bp-spacing-md);
|
|
40
|
+
margin: 0 var(--bp-spacing-xs);
|
|
41
|
+
min-height: 40px;
|
|
42
|
+
border-radius: var(--bp-border-radius-sm);
|
|
43
|
+
background-color: transparent;
|
|
44
|
+
color: var(--bp-color-text);
|
|
45
|
+
font-family: var(--bp-font-sans);
|
|
46
|
+
font-size: var(--bp-font-size-base);
|
|
47
|
+
font-weight: var(--bp-font-weight-normal);
|
|
48
|
+
line-height: var(--bp-line-height-normal);
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
cursor: pointer;
|
|
51
|
+
transition:
|
|
52
|
+
background-color var(--bp-transition-fast),
|
|
53
|
+
transform var(--bp-transition-fast);
|
|
54
|
+
user-select: none;
|
|
55
|
+
outline: none;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* Menu Item Sizes */
|
|
59
|
+
.menu-item--sm {
|
|
60
|
+
padding: var(--bp-spacing-sm) var(--bp-spacing-sm);
|
|
61
|
+
min-height: 36px;
|
|
62
|
+
font-size: var(--bp-font-size-sm);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.menu-item--lg {
|
|
66
|
+
padding: var(--bp-spacing-md) var(--bp-spacing-lg);
|
|
67
|
+
min-height: 48px;
|
|
68
|
+
font-size: var(--bp-font-size-lg);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Menu Item States */
|
|
72
|
+
.menu-item:hover:not(.menu-item--disabled) {
|
|
73
|
+
background-color: var(--bp-color-surface);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.menu-item:focus-visible:not(.menu-item--disabled) {
|
|
77
|
+
background-color: var(--bp-color-surface);
|
|
78
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-primary);
|
|
79
|
+
outline-offset: var(--bp-focus-offset);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.menu-item:active:not(.menu-item--disabled) {
|
|
83
|
+
background-color: var(--bp-color-surface);
|
|
84
|
+
transform: scale(0.98);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.menu-item--selected {
|
|
88
|
+
background-color: var(--bp-color-surface);
|
|
89
|
+
font-weight: var(--bp-font-weight-medium);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.menu-item--selected::before {
|
|
93
|
+
content: '';
|
|
94
|
+
position: absolute;
|
|
95
|
+
left: 0;
|
|
96
|
+
top: 0;
|
|
97
|
+
bottom: 0;
|
|
98
|
+
width: 3px;
|
|
99
|
+
background-color: var(--bp-color-primary);
|
|
100
|
+
border-radius: 0 var(--bp-border-radius-sm) var(--bp-border-radius-sm) 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.menu-item--disabled {
|
|
104
|
+
color: var(--bp-color-text-muted);
|
|
105
|
+
cursor: not-allowed;
|
|
106
|
+
opacity: 0.5;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Menu Item Parts */
|
|
110
|
+
.menu-item__prefix {
|
|
111
|
+
display: inline-flex;
|
|
112
|
+
align-items: center;
|
|
113
|
+
flex-shrink: 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.menu-item__prefix:empty {
|
|
117
|
+
display: none;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.menu-item__label {
|
|
121
|
+
flex: 1;
|
|
122
|
+
overflow: hidden;
|
|
123
|
+
text-overflow: ellipsis;
|
|
124
|
+
white-space: nowrap;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.menu-item__suffix {
|
|
128
|
+
display: inline-flex;
|
|
129
|
+
align-items: center;
|
|
130
|
+
gap: var(--bp-spacing-sm);
|
|
131
|
+
flex-shrink: 0;
|
|
132
|
+
margin-left: auto;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.menu-item__suffix:empty {
|
|
136
|
+
display: none;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.menu-item__shortcut {
|
|
140
|
+
color: var(--bp-color-text-muted);
|
|
141
|
+
font-size: var(--bp-font-size-sm);
|
|
142
|
+
font-family: var(--bp-font-mono);
|
|
143
|
+
padding: 2px var(--bp-spacing-xs);
|
|
144
|
+
background-color: var(--bp-color-surface);
|
|
145
|
+
border-radius: var(--bp-border-radius-sm);
|
|
146
|
+
border: var(--bp-border-width) solid var(--bp-color-border);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.menu-item__arrow {
|
|
150
|
+
color: var(--bp-color-text-muted);
|
|
151
|
+
font-size: var(--bp-font-size-lg);
|
|
152
|
+
line-height: 1;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* Menu Divider */
|
|
156
|
+
.menu-divider {
|
|
157
|
+
height: var(--bp-border-width);
|
|
158
|
+
margin: var(--bp-spacing-sm) var(--bp-spacing-sm);
|
|
159
|
+
background-color: var(--bp-color-border);
|
|
160
|
+
}
|
|
161
|
+
`;
|
|
162
|
+
var x = Object.defineProperty, y = Object.getOwnPropertyDescriptor, s = (e, t, n, d) => {
|
|
163
|
+
for (var i = d > 1 ? void 0 : d ? y(t, n) : t, p = e.length - 1, u; p >= 0; p--)
|
|
164
|
+
(u = e[p]) && (i = (d ? u(t, n, i) : u(i)) || i);
|
|
165
|
+
return d && i && x(t, n, i), i;
|
|
166
|
+
};
|
|
167
|
+
let l = class extends m {
|
|
168
|
+
constructor() {
|
|
169
|
+
super(), this.focusedIndex = -1, this.handleFocusIn = (e) => {
|
|
170
|
+
const t = e.target, n = this.menuItems;
|
|
171
|
+
this.focusedIndex = n.indexOf(t);
|
|
172
|
+
}, this.size = "md";
|
|
173
|
+
}
|
|
174
|
+
connectedCallback() {
|
|
175
|
+
super.connectedCallback(), this.addEventListener("focusin", this.handleFocusIn);
|
|
176
|
+
}
|
|
177
|
+
disconnectedCallback() {
|
|
178
|
+
super.disconnectedCallback(), this.removeEventListener("focusin", this.handleFocusIn);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Gets all non-divider menu items from the default slot.
|
|
182
|
+
* @returns Array of bp-menu-item elements
|
|
183
|
+
*/
|
|
184
|
+
get menuItems() {
|
|
185
|
+
const e = this.shadowRoot?.querySelector("slot");
|
|
186
|
+
return e ? e.assignedElements().filter((t) => t.tagName === "BP-MENU-ITEM") : [];
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Handles keyboard navigation within the menu.
|
|
190
|
+
* Supports ArrowDown, ArrowUp, Home, and End keys.
|
|
191
|
+
*/
|
|
192
|
+
handleKeyDown(e) {
|
|
193
|
+
const t = this.menuItems.filter((n) => !n.disabled);
|
|
194
|
+
if (t.length !== 0)
|
|
195
|
+
switch (e.key) {
|
|
196
|
+
case "ArrowDown":
|
|
197
|
+
e.preventDefault(), this.focusedIndex = Math.min(this.focusedIndex + 1, t.length - 1), t[this.focusedIndex]?.focus();
|
|
198
|
+
break;
|
|
199
|
+
case "ArrowUp":
|
|
200
|
+
e.preventDefault(), this.focusedIndex = Math.max(this.focusedIndex - 1, 0), t[this.focusedIndex]?.focus();
|
|
201
|
+
break;
|
|
202
|
+
case "Home":
|
|
203
|
+
e.preventDefault(), this.focusedIndex = 0, t[0]?.focus();
|
|
204
|
+
break;
|
|
205
|
+
case "End":
|
|
206
|
+
e.preventDefault(), this.focusedIndex = t.length - 1, t[t.length - 1]?.focus();
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
handleSlotChange() {
|
|
211
|
+
this.menuItems.forEach((e) => {
|
|
212
|
+
e.size = this.size;
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
render() {
|
|
216
|
+
return a`
|
|
217
|
+
<div
|
|
218
|
+
class="menu menu--${this.size}"
|
|
219
|
+
part="container"
|
|
220
|
+
role="menu"
|
|
221
|
+
@keydown=${this.handleKeyDown}
|
|
222
|
+
>
|
|
223
|
+
<slot @slotchange=${this.handleSlotChange}></slot>
|
|
224
|
+
</div>
|
|
225
|
+
`;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
l.styles = [h];
|
|
229
|
+
s([
|
|
230
|
+
o({ type: String })
|
|
231
|
+
], l.prototype, "size", 2);
|
|
232
|
+
s([
|
|
233
|
+
g()
|
|
234
|
+
], l.prototype, "focusedIndex", 2);
|
|
235
|
+
l = s([
|
|
236
|
+
b("bp-menu")
|
|
237
|
+
], l);
|
|
238
|
+
let r = class extends m {
|
|
239
|
+
constructor() {
|
|
240
|
+
super(), this.value = "", this.disabled = !1, this.selected = !1, this.hasSubmenu = !1, this.size = "md", this.shortcut = "";
|
|
241
|
+
}
|
|
242
|
+
focus() {
|
|
243
|
+
this.shadowRoot?.querySelector(".menu-item")?.focus();
|
|
244
|
+
}
|
|
245
|
+
handleActivate() {
|
|
246
|
+
this.disabled || this.dispatchEvent(
|
|
247
|
+
new CustomEvent("bp-menu-select", {
|
|
248
|
+
detail: { value: this.value },
|
|
249
|
+
bubbles: !0,
|
|
250
|
+
composed: !0
|
|
251
|
+
})
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
handleClick(e) {
|
|
255
|
+
if (this.disabled) {
|
|
256
|
+
e.preventDefault(), e.stopPropagation();
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
this.handleActivate();
|
|
260
|
+
}
|
|
261
|
+
handleKeyDown(e) {
|
|
262
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), this.handleActivate());
|
|
263
|
+
}
|
|
264
|
+
render() {
|
|
265
|
+
return a`
|
|
266
|
+
<div
|
|
267
|
+
class="menu-item menu-item--${this.size} ${this.disabled ? "menu-item--disabled" : ""} ${this.selected ? "menu-item--selected" : ""}"
|
|
268
|
+
part="base"
|
|
269
|
+
role="menuitem"
|
|
270
|
+
tabindex=${this.disabled ? -1 : 0}
|
|
271
|
+
aria-disabled=${this.disabled}
|
|
272
|
+
aria-current=${this.selected ? "page" : "false"}
|
|
273
|
+
@click=${this.handleClick}
|
|
274
|
+
@keydown=${this.handleKeyDown}
|
|
275
|
+
>
|
|
276
|
+
<span class="menu-item__prefix" part="prefix">
|
|
277
|
+
<slot name="prefix"></slot>
|
|
278
|
+
</span>
|
|
279
|
+
<span class="menu-item__label" part="label">
|
|
280
|
+
<slot></slot>
|
|
281
|
+
</span>
|
|
282
|
+
<span class="menu-item__suffix" part="suffix">
|
|
283
|
+
${this.shortcut ? a`<span class="menu-item__shortcut">${this.shortcut}</span>` : f}
|
|
284
|
+
<slot name="suffix"></slot>
|
|
285
|
+
${this.hasSubmenu ? a`<span class="menu-item__arrow">›</span>` : f}
|
|
286
|
+
</span>
|
|
287
|
+
</div>
|
|
288
|
+
`;
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
r.styles = [h];
|
|
292
|
+
s([
|
|
293
|
+
o({ type: String })
|
|
294
|
+
], r.prototype, "value", 2);
|
|
295
|
+
s([
|
|
296
|
+
o({ type: Boolean })
|
|
297
|
+
], r.prototype, "disabled", 2);
|
|
298
|
+
s([
|
|
299
|
+
o({ type: Boolean })
|
|
300
|
+
], r.prototype, "selected", 2);
|
|
301
|
+
s([
|
|
302
|
+
o({ type: Boolean, attribute: "has-submenu" })
|
|
303
|
+
], r.prototype, "hasSubmenu", 2);
|
|
304
|
+
s([
|
|
305
|
+
o({ type: String })
|
|
306
|
+
], r.prototype, "size", 2);
|
|
307
|
+
s([
|
|
308
|
+
o({ type: String })
|
|
309
|
+
], r.prototype, "shortcut", 2);
|
|
310
|
+
r = s([
|
|
311
|
+
b("bp-menu-item")
|
|
312
|
+
], r);
|
|
313
|
+
let c = class extends m {
|
|
314
|
+
render() {
|
|
315
|
+
return a`<div
|
|
316
|
+
class="menu-divider"
|
|
317
|
+
part="divider"
|
|
318
|
+
role="separator"
|
|
319
|
+
></div>`;
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
c.styles = [h];
|
|
323
|
+
c = s([
|
|
324
|
+
b("bp-menu-divider")
|
|
325
|
+
], c);
|
|
326
|
+
export {
|
|
327
|
+
l as BpMenu,
|
|
328
|
+
c as BpMenuDivider,
|
|
329
|
+
r as BpMenuItem
|
|
330
|
+
};
|
|
331
|
+
//# sourceMappingURL=menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu.js","sources":["../../source/components/menu/menu.style.ts","../../source/components/menu/menu.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const menuStyles = css`\n /* Base styles - Menu Container */\n :host {\n display: block;\n }\n\n .menu {\n display: flex;\n flex-direction: column;\n min-width: 200px;\n padding: var(--bp-spacing-xs) 0;\n margin: 0;\n background-color: var(--bp-color-surface-elevated);\n border: var(--bp-border-width) solid var(--bp-color-border);\n border-radius: var(--bp-border-radius-md);\n box-shadow: var(--bp-shadow-lg);\n font-family: var(--bp-font-sans);\n list-style: none;\n outline: none;\n }\n\n /* Menu Sizes */\n .menu--sm {\n min-width: 160px;\n }\n\n .menu--lg {\n min-width: 280px;\n }\n\n /* Menu Item Base */\n .menu-item {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--bp-spacing-sm);\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\n margin: 0 var(--bp-spacing-xs);\n min-height: 40px;\n border-radius: var(--bp-border-radius-sm);\n background-color: transparent;\n color: var(--bp-color-text);\n font-family: var(--bp-font-sans);\n font-size: var(--bp-font-size-base);\n font-weight: var(--bp-font-weight-normal);\n line-height: var(--bp-line-height-normal);\n text-decoration: none;\n cursor: pointer;\n transition:\n background-color var(--bp-transition-fast),\n transform var(--bp-transition-fast);\n user-select: none;\n outline: none;\n }\n\n /* Menu Item Sizes */\n .menu-item--sm {\n padding: var(--bp-spacing-sm) var(--bp-spacing-sm);\n min-height: 36px;\n font-size: var(--bp-font-size-sm);\n }\n\n .menu-item--lg {\n padding: var(--bp-spacing-md) var(--bp-spacing-lg);\n min-height: 48px;\n font-size: var(--bp-font-size-lg);\n }\n\n /* Menu Item States */\n .menu-item:hover:not(.menu-item--disabled) {\n background-color: var(--bp-color-surface);\n }\n\n .menu-item:focus-visible:not(.menu-item--disabled) {\n background-color: var(--bp-color-surface);\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-primary);\n outline-offset: var(--bp-focus-offset);\n }\n\n .menu-item:active:not(.menu-item--disabled) {\n background-color: var(--bp-color-surface);\n transform: scale(0.98);\n }\n\n .menu-item--selected {\n background-color: var(--bp-color-surface);\n font-weight: var(--bp-font-weight-medium);\n }\n\n .menu-item--selected::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background-color: var(--bp-color-primary);\n border-radius: 0 var(--bp-border-radius-sm) var(--bp-border-radius-sm) 0;\n }\n\n .menu-item--disabled {\n color: var(--bp-color-text-muted);\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n /* Menu Item Parts */\n .menu-item__prefix {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .menu-item__prefix:empty {\n display: none;\n }\n\n .menu-item__label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .menu-item__suffix {\n display: inline-flex;\n align-items: center;\n gap: var(--bp-spacing-sm);\n flex-shrink: 0;\n margin-left: auto;\n }\n\n .menu-item__suffix:empty {\n display: none;\n }\n\n .menu-item__shortcut {\n color: var(--bp-color-text-muted);\n font-size: var(--bp-font-size-sm);\n font-family: var(--bp-font-mono);\n padding: 2px var(--bp-spacing-xs);\n background-color: var(--bp-color-surface);\n border-radius: var(--bp-border-radius-sm);\n border: var(--bp-border-width) solid var(--bp-color-border);\n }\n\n .menu-item__arrow {\n color: var(--bp-color-text-muted);\n font-size: var(--bp-font-size-lg);\n line-height: 1;\n }\n\n /* Menu Divider */\n .menu-divider {\n height: var(--bp-border-width);\n margin: var(--bp-spacing-sm) var(--bp-spacing-sm);\n background-color: var(--bp-color-border);\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\nimport { menuStyles } from './menu.style.js';\r\n\r\nexport type MenuSize = 'sm' | 'md' | 'lg';\r\n\r\n/**\r\n * A menu container component for displaying a list of actions or options.\r\n *\r\n * @fires bp-menu-select - Dispatched when a menu item is selected\r\n *\r\n * @slot - Menu items (bp-menu-item, bp-menu-divider)\r\n *\r\n * @csspart container - The menu container element\r\n */\r\n@customElement('bp-menu')\r\nexport class BpMenu extends LitElement {\r\n /** Size variant for all menu items */\r\n @property({ type: String }) declare size: MenuSize;\r\n\r\n /** Current focused item index for keyboard navigation */\r\n @state() private focusedIndex = -1;\r\n\r\n static styles = [menuStyles];\r\n\r\n constructor() {\r\n super();\r\n this.size = 'md';\r\n }\r\n\r\n private handleFocusIn = (event: FocusEvent) => {\r\n const target = event.target as BpMenuItem;\r\n const items = this.menuItems;\r\n this.focusedIndex = items.indexOf(target);\r\n };\r\n\r\n connectedCallback() {\r\n super.connectedCallback();\r\n this.addEventListener('focusin', this.handleFocusIn);\r\n }\r\n\r\n disconnectedCallback() {\r\n super.disconnectedCallback();\r\n this.removeEventListener('focusin', this.handleFocusIn);\r\n }\r\n\r\n /**\r\n * Gets all non-divider menu items from the default slot.\r\n * @returns Array of bp-menu-item elements\r\n */\r\n private get menuItems(): BpMenuItem[] {\r\n const slot = this.shadowRoot?.querySelector('slot');\r\n if (!slot) return [];\r\n return slot\r\n .assignedElements()\r\n .filter((el): el is BpMenuItem => el.tagName === 'BP-MENU-ITEM');\r\n }\r\n\r\n /**\r\n * Handles keyboard navigation within the menu.\r\n * Supports ArrowDown, ArrowUp, Home, and End keys.\r\n */\r\n private handleKeyDown(event: KeyboardEvent) {\r\n const items = this.menuItems.filter((item) => !item.disabled);\r\n if (items.length === 0) return;\r\n\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n this.focusedIndex = Math.min(this.focusedIndex + 1, items.length - 1);\r\n items[this.focusedIndex]?.focus();\r\n break;\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n this.focusedIndex = Math.max(this.focusedIndex - 1, 0);\r\n items[this.focusedIndex]?.focus();\r\n break;\r\n case 'Home':\r\n event.preventDefault();\r\n this.focusedIndex = 0;\r\n items[0]?.focus();\r\n break;\r\n case 'End':\r\n event.preventDefault();\r\n this.focusedIndex = items.length - 1;\r\n items[items.length - 1]?.focus();\r\n break;\r\n }\r\n }\r\n\r\n private handleSlotChange() {\r\n // Update size on all menu items\r\n this.menuItems.forEach((item) => {\r\n item.size = this.size;\r\n });\r\n }\r\n\r\n render() {\r\n return html`\r\n <div\r\n class=\"menu menu--${this.size}\"\r\n part=\"container\"\r\n role=\"menu\"\r\n @keydown=${this.handleKeyDown}\r\n >\r\n <slot @slotchange=${this.handleSlotChange}></slot>\r\n </div>\r\n `;\r\n }\r\n}\r\n\r\n/**\r\n * A menu item component for use within bp-menu.\r\n *\r\n * @fires bp-select - Dispatched when the item is selected\r\n *\r\n * @slot - Item label content\r\n * @slot prefix - Content before the label (typically an icon)\r\n * @slot suffix - Content after the label (typically a shortcut or arrow)\r\n *\r\n * @csspart base - The menu item container\r\n * @csspart prefix - The prefix slot container\r\n * @csspart label - The label container\r\n * @csspart suffix - The suffix slot container\r\n */\r\n@customElement('bp-menu-item')\r\nexport class BpMenuItem extends LitElement {\r\n /** The value associated with this menu item */\r\n @property({ type: String }) declare value: string;\r\n\r\n /** Whether the item is disabled */\r\n @property({ type: Boolean }) declare disabled: boolean;\r\n\r\n /** Whether the item is selected/active */\r\n @property({ type: Boolean }) declare selected: boolean;\r\n\r\n /** Whether the item has a submenu */\r\n @property({ type: Boolean, attribute: 'has-submenu' })\r\n declare hasSubmenu: boolean;\r\n\r\n /** Size variant (inherited from parent menu) */\r\n @property({ type: String }) declare size: MenuSize;\r\n\r\n /** Keyboard shortcut hint to display */\r\n @property({ type: String }) declare shortcut: string;\r\n\r\n static styles = [menuStyles];\r\n\r\n constructor() {\r\n super();\r\n this.value = '';\r\n this.disabled = false;\r\n this.selected = false;\r\n this.hasSubmenu = false;\r\n this.size = 'md';\r\n this.shortcut = '';\r\n }\r\n\r\n focus() {\r\n const button = this.shadowRoot?.querySelector('.menu-item') as HTMLElement;\r\n button?.focus();\r\n }\r\n\r\n private handleActivate() {\r\n if (this.disabled) return;\r\n\r\n this.dispatchEvent(\r\n new CustomEvent('bp-menu-select', {\r\n detail: { value: this.value },\r\n bubbles: true,\r\n composed: true,\r\n })\r\n );\r\n }\r\n\r\n private handleClick(event: MouseEvent) {\r\n if (this.disabled) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n return;\r\n }\r\n\r\n this.handleActivate();\r\n }\r\n\r\n private handleKeyDown(event: KeyboardEvent) {\r\n if (event.key === 'Enter' || event.key === ' ') {\r\n event.preventDefault();\r\n this.handleActivate();\r\n }\r\n }\r\n\r\n render() {\r\n return html`\r\n <div\r\n class=\"menu-item menu-item--${this.size} ${this.disabled\r\n ? 'menu-item--disabled'\r\n : ''} ${this.selected ? 'menu-item--selected' : ''}\"\r\n part=\"base\"\r\n role=\"menuitem\"\r\n tabindex=${this.disabled ? -1 : 0}\r\n aria-disabled=${this.disabled}\r\n aria-current=${this.selected ? 'page' : 'false'}\r\n @click=${this.handleClick}\r\n @keydown=${this.handleKeyDown}\r\n >\r\n <span class=\"menu-item__prefix\" part=\"prefix\">\r\n <slot name=\"prefix\"></slot>\r\n </span>\r\n <span class=\"menu-item__label\" part=\"label\">\r\n <slot></slot>\r\n </span>\r\n <span class=\"menu-item__suffix\" part=\"suffix\">\r\n ${this.shortcut\r\n ? html`<span class=\"menu-item__shortcut\">${this.shortcut}</span>`\r\n : nothing}\r\n <slot name=\"suffix\"></slot>\r\n ${this.hasSubmenu\r\n ? html`<span class=\"menu-item__arrow\">›</span>`\r\n : nothing}\r\n </span>\r\n </div>\r\n `;\r\n }\r\n}\r\n\r\n/**\r\n * A divider for visually separating menu items.\r\n *\r\n * @csspart divider - The divider element\r\n */\r\n@customElement('bp-menu-divider')\r\nexport class BpMenuDivider extends LitElement {\r\n static styles = [menuStyles];\r\n\r\n render() {\r\n return html`<div\r\n class=\"menu-divider\"\r\n part=\"divider\"\r\n role=\"separator\"\r\n ></div>`;\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'bp-menu': BpMenu;\r\n 'bp-menu-item': BpMenuItem;\r\n 'bp-menu-divider': BpMenuDivider;\r\n }\r\n}\r\n"],"names":["menuStyles","css","BpMenu","LitElement","event","target","items","slot","el","item","html","__decorateClass","property","state","customElement","BpMenuItem","nothing","BpMenuDivider"],"mappings":"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"}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { css as b, LitElement as h, html as c } from "lit";
|
|
2
|
+
import { property as d, query as u, state as p, customElement as m } from "lit/decorators.js";
|
|
3
|
+
import { classMap as f } from "lit/directives/class-map.js";
|
|
4
|
+
const v = b`
|
|
5
|
+
/* Base styles */
|
|
6
|
+
:host {
|
|
7
|
+
display: block;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
:host([open]) {
|
|
11
|
+
display: block;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
:host(:not([open])) {
|
|
15
|
+
display: none;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* Backdrop */
|
|
19
|
+
.modal-backdrop {
|
|
20
|
+
position: fixed;
|
|
21
|
+
top: 0;
|
|
22
|
+
left: 0;
|
|
23
|
+
right: 0;
|
|
24
|
+
bottom: 0;
|
|
25
|
+
z-index: var(--bp-z-modal);
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
background-color: var(--bp-color-backdrop);
|
|
30
|
+
animation: fadeIn var(--bp-duration-fast) var(--bp-ease-out);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@keyframes fadeIn {
|
|
34
|
+
from {
|
|
35
|
+
opacity: 0;
|
|
36
|
+
}
|
|
37
|
+
to {
|
|
38
|
+
opacity: 1;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@keyframes slideUp {
|
|
43
|
+
from {
|
|
44
|
+
transform: translateY(var(--bp-spacing-8));
|
|
45
|
+
opacity: 0;
|
|
46
|
+
}
|
|
47
|
+
to {
|
|
48
|
+
transform: translateY(0);
|
|
49
|
+
opacity: 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Dialog */
|
|
54
|
+
.modal-dialog {
|
|
55
|
+
position: relative;
|
|
56
|
+
background-color: var(--bp-color-surface-elevated);
|
|
57
|
+
border-radius: var(--bp-border-radius-lg);
|
|
58
|
+
box-shadow: var(--bp-shadow-xl);
|
|
59
|
+
max-height: 90vh;
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-direction: column;
|
|
62
|
+
overflow: hidden;
|
|
63
|
+
animation: slideUp var(--bp-duration-normal) var(--bp-ease-out);
|
|
64
|
+
outline: none;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Header */
|
|
68
|
+
.modal-header {
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
justify-content: space-between;
|
|
72
|
+
gap: var(--bp-spacing-md);
|
|
73
|
+
padding: var(--bp-spacing-6);
|
|
74
|
+
border-bottom: var(--bp-border-width) solid var(--bp-color-border);
|
|
75
|
+
font-family: var(--bp-font-family);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
::slotted([slot='header']) {
|
|
79
|
+
flex: 1;
|
|
80
|
+
font-size: var(--bp-font-size-xl);
|
|
81
|
+
font-weight: var(--bp-font-weight-semibold);
|
|
82
|
+
color: var(--bp-color-text-strong);
|
|
83
|
+
line-height: var(--bp-line-height-tight);
|
|
84
|
+
margin: 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Close button */
|
|
88
|
+
.modal-close {
|
|
89
|
+
appearance: none;
|
|
90
|
+
background: transparent;
|
|
91
|
+
border: none;
|
|
92
|
+
padding: var(--bp-spacing-2);
|
|
93
|
+
cursor: pointer;
|
|
94
|
+
color: var(--bp-color-text-muted);
|
|
95
|
+
border-radius: var(--bp-border-radius-md);
|
|
96
|
+
display: flex;
|
|
97
|
+
align-items: center;
|
|
98
|
+
justify-content: center;
|
|
99
|
+
transition: all var(--bp-transition-fast);
|
|
100
|
+
flex-shrink: 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.modal-close:hover {
|
|
104
|
+
background-color: var(--bp-color-surface);
|
|
105
|
+
color: var(--bp-color-text);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.modal-close:focus-visible {
|
|
109
|
+
outline: var(--bp-focus-ring);
|
|
110
|
+
outline-offset: var(--bp-focus-offset);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.modal-close svg {
|
|
114
|
+
display: block;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* Body */
|
|
118
|
+
.modal-body {
|
|
119
|
+
flex: 1;
|
|
120
|
+
padding: var(--bp-spacing-6);
|
|
121
|
+
overflow-y: auto;
|
|
122
|
+
font-family: var(--bp-font-family);
|
|
123
|
+
font-size: var(--bp-font-size-base);
|
|
124
|
+
line-height: var(--bp-line-height-relaxed);
|
|
125
|
+
color: var(--bp-color-text);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Footer */
|
|
129
|
+
.modal-footer {
|
|
130
|
+
padding: var(--bp-spacing-6);
|
|
131
|
+
border-top: var(--bp-border-width) solid var(--bp-color-border);
|
|
132
|
+
display: flex;
|
|
133
|
+
gap: var(--bp-spacing-3);
|
|
134
|
+
justify-content: flex-end;
|
|
135
|
+
align-items: center;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.modal-footer:empty {
|
|
139
|
+
display: none;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* Sizes */
|
|
143
|
+
.modal-dialog--sm {
|
|
144
|
+
width: 90%;
|
|
145
|
+
max-width: calc(var(--bp-spacing-24) * 4 + var(--bp-spacing-16));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.modal-dialog--md {
|
|
149
|
+
width: 90%;
|
|
150
|
+
max-width: var(--bp-breakpoint-sm);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.modal-dialog--lg {
|
|
154
|
+
width: 90%;
|
|
155
|
+
max-width: var(--bp-breakpoint-md);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* States */
|
|
159
|
+
.modal-dialog:focus {
|
|
160
|
+
outline: none;
|
|
161
|
+
}
|
|
162
|
+
`;
|
|
163
|
+
var y = Object.defineProperty, g = Object.getOwnPropertyDescriptor, r = (e, o, s, l) => {
|
|
164
|
+
for (var a = l > 1 ? void 0 : l ? g(o, s) : o, i = e.length - 1, n; i >= 0; i--)
|
|
165
|
+
(n = e[i]) && (a = (l ? n(o, s, a) : n(a)) || a);
|
|
166
|
+
return l && a && y(o, s, a), a;
|
|
167
|
+
};
|
|
168
|
+
let t = class extends h {
|
|
169
|
+
constructor() {
|
|
170
|
+
super(), this.previouslyFocusedElement = null, this.bodyScrollPrevented = !1, this.handleKeyDown = (e) => {
|
|
171
|
+
e.key === "Escape" && this.open && (e.preventDefault(), this.close()), e.key === "Tab" && this.open && this.trapFocus(e);
|
|
172
|
+
}, this.handleBackdropClick = (e) => {
|
|
173
|
+
e.target === e.currentTarget && this.close();
|
|
174
|
+
}, this.handleCloseButtonClick = () => {
|
|
175
|
+
this.close();
|
|
176
|
+
}, this.open = !1, this.size = "md", this.ariaLabelledby = "";
|
|
177
|
+
}
|
|
178
|
+
connectedCallback() {
|
|
179
|
+
super.connectedCallback(), this.addEventListener("keydown", this.handleKeyDown);
|
|
180
|
+
}
|
|
181
|
+
disconnectedCallback() {
|
|
182
|
+
super.disconnectedCallback(), this.removeEventListener("keydown", this.handleKeyDown), this.restoreFocus(), this.restoreBodyScroll();
|
|
183
|
+
}
|
|
184
|
+
updated(e) {
|
|
185
|
+
e.has("open") && (this.open ? this.handleOpen() : this.handleClose());
|
|
186
|
+
}
|
|
187
|
+
handleOpen() {
|
|
188
|
+
this.previouslyFocusedElement = document.activeElement, this.preventBodyScroll(), this.updateComplete.then(() => {
|
|
189
|
+
this.setFocusToDialog();
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
handleClose() {
|
|
193
|
+
this.restoreFocus(), this.restoreBodyScroll();
|
|
194
|
+
}
|
|
195
|
+
preventBodyScroll() {
|
|
196
|
+
this.bodyScrollPrevented || (document.body.style.overflow = "hidden", this.bodyScrollPrevented = !0);
|
|
197
|
+
}
|
|
198
|
+
restoreBodyScroll() {
|
|
199
|
+
this.bodyScrollPrevented && (document.body.style.overflow = "", this.bodyScrollPrevented = !1);
|
|
200
|
+
}
|
|
201
|
+
setFocusToDialog() {
|
|
202
|
+
this.dialogElement && this.dialogElement.focus();
|
|
203
|
+
}
|
|
204
|
+
restoreFocus() {
|
|
205
|
+
this.previouslyFocusedElement && (this.previouslyFocusedElement.focus(), this.previouslyFocusedElement = null);
|
|
206
|
+
}
|
|
207
|
+
trapFocus(e) {
|
|
208
|
+
const o = this.getFocusableElements();
|
|
209
|
+
if (o.length === 0) return;
|
|
210
|
+
const s = o[0], l = o[o.length - 1];
|
|
211
|
+
e.shiftKey ? document.activeElement === s && (e.preventDefault(), l.focus()) : document.activeElement === l && (e.preventDefault(), s.focus());
|
|
212
|
+
}
|
|
213
|
+
getFocusableElements() {
|
|
214
|
+
if (!this.shadowRoot) return [];
|
|
215
|
+
const e = [
|
|
216
|
+
"button:not([disabled])",
|
|
217
|
+
"a[href]",
|
|
218
|
+
"input:not([disabled])",
|
|
219
|
+
"select:not([disabled])",
|
|
220
|
+
"textarea:not([disabled])",
|
|
221
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
222
|
+
], o = this.shadowRoot.querySelectorAll(
|
|
223
|
+
e.join(",")
|
|
224
|
+
);
|
|
225
|
+
return Array.from(o);
|
|
226
|
+
}
|
|
227
|
+
close() {
|
|
228
|
+
this.open = !1, this.dispatchEvent(
|
|
229
|
+
new CustomEvent("bp-close", {
|
|
230
|
+
bubbles: !0,
|
|
231
|
+
composed: !0
|
|
232
|
+
})
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
render() {
|
|
236
|
+
if (!this.open)
|
|
237
|
+
return c``;
|
|
238
|
+
const e = {
|
|
239
|
+
"modal-dialog": !0,
|
|
240
|
+
[`modal-dialog--${this.size}`]: !0
|
|
241
|
+
};
|
|
242
|
+
return c`
|
|
243
|
+
<div
|
|
244
|
+
class="modal-backdrop"
|
|
245
|
+
part="backdrop"
|
|
246
|
+
@click=${this.handleBackdropClick}
|
|
247
|
+
>
|
|
248
|
+
<div
|
|
249
|
+
class=${f(e)}
|
|
250
|
+
part="dialog"
|
|
251
|
+
role="dialog"
|
|
252
|
+
aria-modal="true"
|
|
253
|
+
aria-labelledby=${this.ariaLabelledby || "modal-header"}
|
|
254
|
+
tabindex="-1"
|
|
255
|
+
>
|
|
256
|
+
<div class="modal-header" part="header">
|
|
257
|
+
<slot name="header"></slot>
|
|
258
|
+
<button
|
|
259
|
+
class="modal-close"
|
|
260
|
+
part="close-button"
|
|
261
|
+
type="button"
|
|
262
|
+
aria-label="Close"
|
|
263
|
+
@click=${this.handleCloseButtonClick}
|
|
264
|
+
>
|
|
265
|
+
<svg
|
|
266
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
267
|
+
width="20"
|
|
268
|
+
height="20"
|
|
269
|
+
viewBox="0 0 24 24"
|
|
270
|
+
fill="none"
|
|
271
|
+
stroke="currentColor"
|
|
272
|
+
stroke-width="2"
|
|
273
|
+
stroke-linecap="round"
|
|
274
|
+
stroke-linejoin="round"
|
|
275
|
+
>
|
|
276
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
277
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
278
|
+
</svg>
|
|
279
|
+
</button>
|
|
280
|
+
</div>
|
|
281
|
+
<div class="modal-body" part="body">
|
|
282
|
+
<slot></slot>
|
|
283
|
+
</div>
|
|
284
|
+
<div class="modal-footer" part="footer">
|
|
285
|
+
<slot name="footer"></slot>
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
289
|
+
`;
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
t.styles = [v];
|
|
293
|
+
r([
|
|
294
|
+
d({ type: Boolean, reflect: !0 })
|
|
295
|
+
], t.prototype, "open", 2);
|
|
296
|
+
r([
|
|
297
|
+
d({ type: String, reflect: !0 })
|
|
298
|
+
], t.prototype, "size", 2);
|
|
299
|
+
r([
|
|
300
|
+
d({ type: String, attribute: "aria-labelledby" })
|
|
301
|
+
], t.prototype, "ariaLabelledby", 2);
|
|
302
|
+
r([
|
|
303
|
+
u(".modal-dialog")
|
|
304
|
+
], t.prototype, "dialogElement", 2);
|
|
305
|
+
r([
|
|
306
|
+
p()
|
|
307
|
+
], t.prototype, "previouslyFocusedElement", 2);
|
|
308
|
+
r([
|
|
309
|
+
p()
|
|
310
|
+
], t.prototype, "bodyScrollPrevented", 2);
|
|
311
|
+
t = r([
|
|
312
|
+
m("bp-modal")
|
|
313
|
+
], t);
|
|
314
|
+
export {
|
|
315
|
+
t as BpModal
|
|
316
|
+
};
|
|
317
|
+
//# sourceMappingURL=modal.js.map
|