@brandsync/wc 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +139 -11
- package/dist/brandsync-wc/brandsync-wc.esm.js +1 -1
- package/dist/brandsync-wc/p-0eed6813.entry.js +1 -0
- package/dist/brandsync-wc/{p-ee7da23d.entry.js → p-107b1c5d.entry.js} +1 -1
- package/dist/brandsync-wc/p-2181378f.entry.js +1 -0
- package/dist/brandsync-wc/p-27bbed83.entry.js +1 -0
- package/dist/brandsync-wc/p-36bf37d9.entry.js +1 -0
- package/dist/brandsync-wc/p-3b64e3cd.entry.js +1 -0
- package/dist/brandsync-wc/p-6fd7dd6a.entry.js +1 -0
- package/dist/brandsync-wc/p-9f6fe37d.entry.js +1 -0
- package/dist/brandsync-wc/{p-03b08508.entry.js → p-c3f72584.entry.js} +1 -1
- package/dist/brandsync-wc/p-fc240aa0.entry.js +1 -0
- package/dist/cjs/brandsync-wc.cjs.js +1 -1
- package/dist/cjs/bs-breadcrumb-overflow.cjs.entry.js +13 -1
- package/dist/cjs/bs-breadcrumb.cjs.entry.js +15 -1
- package/dist/cjs/bs-data-table.cjs.entry.js +18 -4
- package/dist/cjs/bs-icon-button.cjs.entry.js +2 -2
- package/dist/cjs/bs-inline-tab.cjs.entry.js +5 -1
- package/dist/cjs/bs-navigation-drawer-item.cjs.entry.js +1 -1
- package/dist/cjs/bs-navigation-drawer.cjs.entry.js +118 -5
- package/dist/cjs/bs-navigation-header.cjs.entry.js +1 -1
- package/dist/cjs/bs-tab.cjs.entry.js +5 -1
- package/dist/cjs/bs-tabs.cjs.entry.js +47 -2
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.cmp.test.js +63 -0
- package/dist/collection/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.js +32 -1
- package/dist/collection/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.cmp.test.js +45 -0
- package/dist/collection/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.js +30 -1
- package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.cmp.test.js +20 -0
- package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.css +21 -4
- package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.js +3 -2
- package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.stories.js +10 -0
- package/dist/collection/components/bs-data-table/bs-data-table.cmp.test.js +19 -0
- package/dist/collection/components/bs-data-table/bs-data-table.js +19 -5
- package/dist/collection/components/bs-data-table/bs-data-table.stories.js +8 -1
- package/dist/collection/components/bs-logo/bs-logo.cmp.test.js +52 -3
- package/dist/collection/components/bs-menu/bs-menu.stories.js +54 -0
- package/dist/collection/components/bs-tab/bs-inline-tab/bs-inline-tab.js +24 -1
- package/dist/collection/components/bs-tab/bs-tab/bs-tab.js +24 -1
- package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.cmp.test.js +88 -0
- package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.js +83 -2
- package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.stories.js +24 -0
- package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.cmp.test.js +173 -5
- package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.css +106 -34
- package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.js +181 -5
- package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.stories.js +48 -0
- package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer-item/bs-navigation-drawer-item.js +1 -1
- package/dist/collection/components/ui-shell/bs-navigation-header/bs-navigation-header/bs-navigation-header.cmp.test.js +68 -0
- package/dist/collection/components/ui-shell/bs-navigation-header/bs-navigation-header/bs-navigation-header.css +31 -17
- package/dist/components/bs-attachment.js +1 -1
- package/dist/components/bs-breadcrumb-overflow.js +1 -1
- package/dist/components/bs-breadcrumb.js +1 -1
- package/dist/components/bs-carousel.js +1 -1
- package/dist/components/bs-data-table.js +1 -1
- package/dist/components/bs-dialog.js +1 -1
- package/dist/components/bs-file-upload-item.js +1 -1
- package/dist/components/bs-icon-button.js +1 -1
- package/dist/components/bs-inline-tab.js +1 -1
- package/dist/components/bs-navigation-drawer-item.js +1 -1
- package/dist/components/bs-navigation-drawer.js +1 -1
- package/dist/components/bs-navigation-header.js +1 -1
- package/dist/components/bs-snackbar.js +1 -1
- package/dist/components/bs-tab.js +1 -1
- package/dist/components/bs-tabs.js +1 -1
- package/dist/components/p-BoeorHNv.js +1 -0
- package/dist/esm/brandsync-wc.js +1 -1
- package/dist/esm/bs-breadcrumb-overflow.entry.js +14 -2
- package/dist/esm/bs-breadcrumb.entry.js +16 -2
- package/dist/esm/bs-data-table.entry.js +18 -4
- package/dist/esm/bs-icon-button.entry.js +2 -2
- package/dist/esm/bs-inline-tab.entry.js +5 -1
- package/dist/esm/bs-navigation-drawer-item.entry.js +1 -1
- package/dist/esm/bs-navigation-drawer.entry.js +119 -6
- package/dist/esm/bs-navigation-header.entry.js +1 -1
- package/dist/esm/bs-tab.entry.js +5 -1
- package/dist/esm/bs-tabs.entry.js +48 -3
- package/dist/esm/loader.js +1 -1
- package/dist/types/components/bs-breadcrumb/bs-breadcrumb/bs-breadcrumb.d.ts +10 -0
- package/dist/types/components/bs-breadcrumb/bs-breadcrumb-overflow/bs-breadcrumb-overflow.d.ts +8 -0
- package/dist/types/components/bs-button/bs-icon-button/bs-icon-button.d.ts +2 -1
- package/dist/types/components/bs-button/bs-icon-button/bs-icon-button.stories.d.ts +1 -0
- package/dist/types/components/bs-data-table/bs-data-table.d.ts +16 -2
- package/dist/types/components/bs-menu/bs-menu.stories.d.ts +1 -0
- package/dist/types/components/bs-tab/bs-inline-tab/bs-inline-tab.d.ts +4 -0
- package/dist/types/components/bs-tab/bs-tab/bs-tab.d.ts +4 -0
- package/dist/types/components/bs-tab/bs-tabs/bs-tabs.d.ts +17 -0
- package/dist/types/components/bs-tab/bs-tabs/bs-tabs.stories.d.ts +1 -0
- package/dist/types/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.d.ts +50 -1
- package/dist/types/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.stories.d.ts +2 -0
- package/dist/types/components.d.ts +130 -2
- package/package.json +1 -1
- package/dist/brandsync-wc/p-002d258d.entry.js +0 -1
- package/dist/brandsync-wc/p-153da845.entry.js +0 -1
- package/dist/brandsync-wc/p-2e7a1082.entry.js +0 -1
- package/dist/brandsync-wc/p-612cf79c.entry.js +0 -1
- package/dist/brandsync-wc/p-652d4068.entry.js +0 -1
- package/dist/brandsync-wc/p-bc69a96c.entry.js +0 -1
- package/dist/brandsync-wc/p-bf53ad52.entry.js +0 -1
- package/dist/brandsync-wc/p-c7f4c114.entry.js +0 -1
- package/dist/components/p-BkHYJIyj.js +0 -1
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import { render, h, describe, it, expect } from "@stencil/vitest";
|
|
2
|
+
import { afterEach, beforeEach } from "vitest";
|
|
2
3
|
import { page } from "vitest/browser";
|
|
4
|
+
import { runAxeCheck } from "../../../../test/helpers/conventions";
|
|
5
|
+
// The test browser (and its viewport) is shared across test files, so every test here starts from a
|
|
6
|
+
// known viewport and restores whatever it found. The default 414px viewport is inside the drawer's
|
|
7
|
+
// small-screen (<= 768px) overlay mode, so the original tests -- written for the desktop drawer --
|
|
8
|
+
// run at 1024px; the overlay has its own describe at 390px below.
|
|
9
|
+
const previousViewport = { w: 0, h: 0 };
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
previousViewport.w = window.innerWidth;
|
|
12
|
+
previousViewport.h = window.innerHeight;
|
|
13
|
+
await page.viewport(1024, 768);
|
|
14
|
+
});
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
await page.viewport(previousViewport.w, previousViewport.h);
|
|
17
|
+
document.body.style.overflow = '';
|
|
18
|
+
});
|
|
3
19
|
describe('bs-navigation-drawer', () => {
|
|
4
20
|
it('renders a <nav> landmark with the logo', async () => {
|
|
5
21
|
const { root } = await render(h("bs-navigation-drawer", null));
|
|
@@ -110,11 +126,8 @@ describe('bs-navigation-drawer', () => {
|
|
|
110
126
|
expect(searchClickSpy).toHaveReceivedEventTimes(1);
|
|
111
127
|
});
|
|
112
128
|
it('hides the search-trigger button when not collapsed', async () => {
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
// `collapsed` regardless of the prop -- widen the viewport here so this test is isolated to
|
|
116
|
-
// the `collapsed` *prop*'s own behavior, not the viewport-driven treatment.
|
|
117
|
-
await page.viewport(1024, 768);
|
|
129
|
+
// Desktop viewport (set for the whole file above), so this is isolated to the `collapsed`
|
|
130
|
+
// *prop*'s own behavior, not the small-screen overlay.
|
|
118
131
|
const { root } = await render(h("bs-navigation-drawer", null));
|
|
119
132
|
const trigger = root.shadowRoot.querySelector('[part="search-trigger"]');
|
|
120
133
|
expect(getComputedStyle(trigger).display).toBe('none');
|
|
@@ -147,3 +160,158 @@ describe('bs-navigation-drawer', () => {
|
|
|
147
160
|
});
|
|
148
161
|
});
|
|
149
162
|
});
|
|
163
|
+
describe('bs-navigation-drawer: small-screen overlay (<= 768px)', () => {
|
|
164
|
+
const frame = () => new Promise(r => requestAnimationFrame(() => requestAnimationFrame(() => r())));
|
|
165
|
+
const nav = (root) => root.shadowRoot.querySelector('nav');
|
|
166
|
+
const backdrop = (root) => root.shadowRoot.querySelector('[part="backdrop"]');
|
|
167
|
+
const css = (el) => getComputedStyle(el);
|
|
168
|
+
const renderDrawer = async (props = {}) => {
|
|
169
|
+
await page.viewport(390, 800);
|
|
170
|
+
const result = await render(h("bs-navigation-drawer", { ...props }, h("bs-navigation-drawer-item", null, "Home"), h("bs-navigation-drawer-item", { expandable: true, expanded: true }, "Reports", h("bs-navigation-drawer-item", { slot: "children", nested: true }, "Sales"))));
|
|
171
|
+
await result.waitForChanges();
|
|
172
|
+
return result;
|
|
173
|
+
};
|
|
174
|
+
it('is closed by default: off-canvas, hidden from the tab order and the accessibility tree', async () => {
|
|
175
|
+
const { root } = await renderDrawer();
|
|
176
|
+
expect(css(nav(root)).visibility).toBe('hidden');
|
|
177
|
+
expect(nav(root)).not.toHaveClass('bs-navigation-drawer--open');
|
|
178
|
+
expect(nav(root).getAttribute('role')).toBeNull();
|
|
179
|
+
expect(css(backdrop(root)).visibility).toBe('hidden');
|
|
180
|
+
});
|
|
181
|
+
it('takes no space in the page flow (position: fixed)', async () => {
|
|
182
|
+
const { root } = await renderDrawer();
|
|
183
|
+
expect(css(nav(root)).position).toBe('fixed');
|
|
184
|
+
});
|
|
185
|
+
it('open shows the drawer fully expanded over a backdrop', async () => {
|
|
186
|
+
const { root, waitForChanges } = await renderDrawer();
|
|
187
|
+
root.open = true;
|
|
188
|
+
await waitForChanges();
|
|
189
|
+
await new Promise(r => setTimeout(r, 350)); // let the slide-in finish
|
|
190
|
+
expect(css(nav(root)).visibility).toBe('visible');
|
|
191
|
+
expect(Math.round(nav(root).getBoundingClientRect().left)).toBe(0);
|
|
192
|
+
expect(Math.round(nav(root).getBoundingClientRect().width)).toBe(280);
|
|
193
|
+
// still the plain nav landmark: ARIA does not allow role="dialog" on <nav>
|
|
194
|
+
expect(nav(root).getAttribute('role')).toBeNull();
|
|
195
|
+
expect(css(backdrop(root)).visibility).toBe('visible');
|
|
196
|
+
// full wordmark + title, not the rail's mark; no collapse toggle or compact search trigger
|
|
197
|
+
expect(css(root.shadowRoot.querySelector('.bs-navigation-drawer__logo--full')).display).not.toBe('none');
|
|
198
|
+
expect(css(root.shadowRoot.querySelector('.bs-navigation-drawer__logo--mark')).display).toBe('none');
|
|
199
|
+
expect(css(root.shadowRoot.querySelector('[part="title"]')).display).not.toBe('none');
|
|
200
|
+
expect(css(root.shadowRoot.querySelector('[part="collapse"]')).display).toBe('none');
|
|
201
|
+
expect(css(root.shadowRoot.querySelector('[part="search-trigger"]')).display).toBe('none');
|
|
202
|
+
});
|
|
203
|
+
it('forces the items to their expanded layout, even when the drawer has collapsed set', async () => {
|
|
204
|
+
const { root, waitForChanges } = await renderDrawer({ collapsed: true });
|
|
205
|
+
root.open = true;
|
|
206
|
+
await waitForChanges();
|
|
207
|
+
const topLevel = Array.from(root.querySelectorAll(':scope > bs-navigation-drawer-item'));
|
|
208
|
+
expect(topLevel.map(i => i.collapsed)).toEqual([false, false]);
|
|
209
|
+
// the expandable item's children are reachable (its children wrapper is shown)
|
|
210
|
+
const children = topLevel[1].shadowRoot.querySelector('[part="children"]');
|
|
211
|
+
expect(children).not.toBeNull();
|
|
212
|
+
expect(css(children).display).not.toBe('none');
|
|
213
|
+
});
|
|
214
|
+
it('Escape closes the overlay, sets open back to false and emits bsClose once', async () => {
|
|
215
|
+
const { root, waitForChanges, spyOnEvent } = await renderDrawer();
|
|
216
|
+
const spy = spyOnEvent('bsClose');
|
|
217
|
+
root.open = true;
|
|
218
|
+
await waitForChanges();
|
|
219
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
220
|
+
await waitForChanges();
|
|
221
|
+
expect(root.open).toBe(false);
|
|
222
|
+
expect(root.hasAttribute('open')).toBe(false);
|
|
223
|
+
expect(spy).toHaveReceivedEventTimes(1);
|
|
224
|
+
});
|
|
225
|
+
it('clicking the backdrop closes the overlay and emits bsClose', async () => {
|
|
226
|
+
const { root, waitForChanges, spyOnEvent } = await renderDrawer();
|
|
227
|
+
const spy = spyOnEvent('bsClose');
|
|
228
|
+
root.open = true;
|
|
229
|
+
await waitForChanges();
|
|
230
|
+
backdrop(root).click();
|
|
231
|
+
await waitForChanges();
|
|
232
|
+
expect(root.open).toBe(false);
|
|
233
|
+
expect(spy).toHaveReceivedEventTimes(1);
|
|
234
|
+
});
|
|
235
|
+
it('setting open = false from code does not emit bsClose', async () => {
|
|
236
|
+
const { root, waitForChanges, spyOnEvent } = await renderDrawer({ open: true });
|
|
237
|
+
const spy = spyOnEvent('bsClose');
|
|
238
|
+
root.open = false;
|
|
239
|
+
await waitForChanges();
|
|
240
|
+
expect(spy).not.toHaveReceivedEvent();
|
|
241
|
+
});
|
|
242
|
+
it('Escape does nothing while the overlay is closed', async () => {
|
|
243
|
+
const { waitForChanges, spyOnEvent } = await renderDrawer();
|
|
244
|
+
const spy = spyOnEvent('bsClose');
|
|
245
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
246
|
+
await waitForChanges();
|
|
247
|
+
expect(spy).not.toHaveReceivedEvent();
|
|
248
|
+
});
|
|
249
|
+
it('moves focus into the overlay on open and returns it to the trigger on close', async () => {
|
|
250
|
+
await page.viewport(390, 800);
|
|
251
|
+
const { root, waitForChanges } = await render(h("div", null, h("button", { id: "hamburger" }, "Menu"), h("bs-navigation-drawer", null, h("bs-navigation-drawer-item", null, "Home"))));
|
|
252
|
+
const trigger = root.querySelector('#hamburger');
|
|
253
|
+
const drawer = root.querySelector('bs-navigation-drawer');
|
|
254
|
+
trigger.focus();
|
|
255
|
+
drawer.open = true;
|
|
256
|
+
await waitForChanges();
|
|
257
|
+
await frame();
|
|
258
|
+
expect(drawer.shadowRoot.activeElement).toBe(nav(drawer));
|
|
259
|
+
drawer.open = false;
|
|
260
|
+
await waitForChanges();
|
|
261
|
+
expect(document.activeElement).toBe(trigger);
|
|
262
|
+
});
|
|
263
|
+
it('keeps focus inside the open overlay: focus that lands outside is pulled back in', async () => {
|
|
264
|
+
await page.viewport(390, 800);
|
|
265
|
+
const { root, waitForChanges } = await render(h("div", null, h("button", { id: "outside" }, "Outside"), h("bs-navigation-drawer", { open: true }, h("bs-navigation-drawer-item", null, "Home"))));
|
|
266
|
+
await waitForChanges();
|
|
267
|
+
await frame();
|
|
268
|
+
const drawer = root.querySelector('bs-navigation-drawer');
|
|
269
|
+
root.querySelector('#outside').focus();
|
|
270
|
+
await frame();
|
|
271
|
+
expect(drawer.shadowRoot.activeElement).toBe(nav(drawer));
|
|
272
|
+
});
|
|
273
|
+
it('locks page scroll while open and restores it on close', async () => {
|
|
274
|
+
const { root, waitForChanges } = await renderDrawer();
|
|
275
|
+
expect(document.body.style.overflow).toBe('');
|
|
276
|
+
root.open = true;
|
|
277
|
+
await waitForChanges();
|
|
278
|
+
expect(document.body.style.overflow).toBe('hidden');
|
|
279
|
+
root.open = false;
|
|
280
|
+
await waitForChanges();
|
|
281
|
+
expect(document.body.style.overflow).toBe('');
|
|
282
|
+
});
|
|
283
|
+
it('on wider screens open is ignored: in the page flow, no backdrop, no scroll lock', async () => {
|
|
284
|
+
await page.viewport(1024, 768);
|
|
285
|
+
const { root, waitForChanges } = await render(h("bs-navigation-drawer", { open: true }));
|
|
286
|
+
await waitForChanges();
|
|
287
|
+
expect(css(nav(root)).position).not.toBe('fixed');
|
|
288
|
+
expect(css(nav(root)).visibility).toBe('visible');
|
|
289
|
+
expect(backdrop(root)).toBeNull();
|
|
290
|
+
expect(document.body.style.overflow).toBe('');
|
|
291
|
+
expect(nav(root).getAttribute('role')).toBeNull();
|
|
292
|
+
});
|
|
293
|
+
it('widening the viewport while the overlay is open returns to the normal drawer and releases scroll', async () => {
|
|
294
|
+
const { root, waitForChanges } = await renderDrawer({ open: true });
|
|
295
|
+
expect(document.body.style.overflow).toBe('hidden');
|
|
296
|
+
await page.viewport(1024, 768);
|
|
297
|
+
await new Promise(r => setTimeout(r, 150));
|
|
298
|
+
await waitForChanges();
|
|
299
|
+
expect(css(nav(root)).position).not.toBe('fixed');
|
|
300
|
+
expect(document.body.style.overflow).toBe('');
|
|
301
|
+
expect(backdrop(root)).toBeNull();
|
|
302
|
+
});
|
|
303
|
+
it('is off-canvas on the inline-end side in RTL', async () => {
|
|
304
|
+
await page.viewport(390, 800);
|
|
305
|
+
const { root, waitForChanges } = await render(h("div", { dir: "rtl" }, h("bs-navigation-drawer", null)));
|
|
306
|
+
await waitForChanges();
|
|
307
|
+
const drawer = root.querySelector('bs-navigation-drawer');
|
|
308
|
+
// closed: translated by +100% of its width (to the right, off-screen) rather than -100%
|
|
309
|
+
expect(new DOMMatrix(css(nav(drawer)).transform).m41).toBeGreaterThan(0);
|
|
310
|
+
});
|
|
311
|
+
it('has no axe-core violations while open', async () => {
|
|
312
|
+
const { root, waitForChanges } = await renderDrawer({ open: true });
|
|
313
|
+
await waitForChanges();
|
|
314
|
+
await new Promise(r => setTimeout(r, 350));
|
|
315
|
+
await runAxeCheck(root);
|
|
316
|
+
});
|
|
317
|
+
});
|
|
@@ -12,10 +12,9 @@
|
|
|
12
12
|
* rhythm) -- bumped up from the originally Figma-measured --bs-spacing-150 (12px) at the user's
|
|
13
13
|
* request after seeing it rendered (felt cramped in practice), not a Figma re-measurement.
|
|
14
14
|
* @prop --bs-navigation-drawer-width: Default width of the drawer. 280px, matching Figma's own
|
|
15
|
-
* frame -- overridable by a consumer that needs a different fixed width.
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* below), so the drawer stops reserving a permanent 280px of layout width on small screens.
|
|
15
|
+
* frame -- overridable by a consumer that needs a different fixed width. At 768px and below the
|
|
16
|
+
* drawer is an off-canvas overlay (see `open`) of this same width (capped at the viewport
|
|
17
|
+
* width), so it stops reserving a permanent 280px of layout width on small screens.
|
|
19
18
|
* @prop --bs-navigation-drawer-title-font-family: Title text font family. Aliased to
|
|
20
19
|
* --bs-typography-font-family-heading.
|
|
21
20
|
* @prop --bs-navigation-drawer-title-font-weight: Title text font weight. Aliased to
|
|
@@ -50,6 +49,14 @@
|
|
|
50
49
|
* --bs-border-neutral-container (same border color as the drawer's own right edge).
|
|
51
50
|
* @prop --bs-navigation-drawer-search-trigger-icon: Search-trigger icon color. Aliased to
|
|
52
51
|
* --bs-icon-default.
|
|
52
|
+
* @prop --bs-navigation-drawer-backdrop: Scrim behind the small-screen overlay. Aliased to
|
|
53
|
+
* --bs-surface-overlay-level-2.
|
|
54
|
+
* @prop --bs-navigation-drawer-overlay-shadow: Shadow of the small-screen overlay panel. Aliased
|
|
55
|
+
* to --bs-shadow-lg.
|
|
56
|
+
* @prop --bs-navigation-drawer-overlay-z-index: Stacking order of the small-screen overlay (the
|
|
57
|
+
* panel sits one above its backdrop). Aliased to --bs-z-index-modal.
|
|
58
|
+
* @prop --bs-navigation-drawer-overlay-duration: Slide/fade duration of the small-screen overlay.
|
|
59
|
+
* Aliased to --bs-duration-default.
|
|
53
60
|
*/
|
|
54
61
|
:host {
|
|
55
62
|
display: block;
|
|
@@ -82,6 +89,11 @@
|
|
|
82
89
|
--bs-navigation-drawer-search-trigger-bg: var(--bs-color-neutral-container);
|
|
83
90
|
--bs-navigation-drawer-search-trigger-border: var(--bs-border-neutral-container);
|
|
84
91
|
--bs-navigation-drawer-search-trigger-icon: var(--bs-icon-default);
|
|
92
|
+
|
|
93
|
+
--bs-navigation-drawer-backdrop: var(--bs-surface-overlay-level-2);
|
|
94
|
+
--bs-navigation-drawer-overlay-shadow: var(--bs-shadow-lg);
|
|
95
|
+
--bs-navigation-drawer-overlay-z-index: var(--bs-z-index-modal);
|
|
96
|
+
--bs-navigation-drawer-overlay-duration: var(--bs-duration-default);
|
|
85
97
|
}
|
|
86
98
|
|
|
87
99
|
.bs-navigation-drawer {
|
|
@@ -259,41 +271,101 @@
|
|
|
259
271
|
display: none;
|
|
260
272
|
}
|
|
261
273
|
|
|
262
|
-
/*
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
@media (max-width: 768px) {
|
|
273
|
-
.bs-navigation-drawer {
|
|
274
|
-
width: var(--bs-navigation-drawer-collapsed-width);
|
|
275
|
-
padding-left: 0;
|
|
276
|
-
padding-right: 0;
|
|
277
|
-
align-items: center;
|
|
278
|
-
}
|
|
274
|
+
/* Small screens (768px and below, tracked in bs-navigation-drawer.tsx with matchMedia, which sets
|
|
275
|
+
the `data-overlay` attribute on the host): instead of a permanent rail the drawer becomes an
|
|
276
|
+
off-canvas overlay -- hidden until `open`, then sliding in over the page with a backdrop. A rail
|
|
277
|
+
clipped item labels inside 96px and offered no way to reach nested items, so the overlay shows the
|
|
278
|
+
drawer fully expanded (the items are switched to their expanded layout in the component). The
|
|
279
|
+
overrides below intentionally come after, and match the specificity of, the `:host([collapsed])`
|
|
280
|
+
rules above, so a `collapsed` set for desktop never leaks into the overlay. */
|
|
281
|
+
.bs-navigation-drawer:focus {
|
|
282
|
+
outline: none; /* programmatic focus target only (tabindex="-1"), see the component */
|
|
283
|
+
}
|
|
279
284
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
285
|
+
:host([data-overlay]) .bs-navigation-drawer {
|
|
286
|
+
position: fixed;
|
|
287
|
+
inset-block: 0;
|
|
288
|
+
inset-inline-start: 0;
|
|
289
|
+
z-index: calc(var(--bs-navigation-drawer-overlay-z-index) + 1);
|
|
290
|
+
width: var(--bs-navigation-drawer-width);
|
|
291
|
+
max-width: 100vw;
|
|
292
|
+
padding: var(--bs-navigation-drawer-padding-y) var(--bs-navigation-drawer-padding-right) var(--bs-navigation-drawer-padding-y)
|
|
293
|
+
var(--bs-navigation-drawer-padding-left);
|
|
294
|
+
align-items: stretch;
|
|
295
|
+
box-shadow: var(--bs-navigation-drawer-overlay-shadow);
|
|
296
|
+
/* Closed: off-canvas and hidden from the tab order / accessibility tree. `visibility` flips after
|
|
297
|
+
the slide-out finishes (delayed transition) so the exit is still seen. */
|
|
298
|
+
transform: translateX(-100%);
|
|
299
|
+
visibility: hidden;
|
|
300
|
+
transition:
|
|
301
|
+
transform var(--bs-navigation-drawer-overlay-duration) var(--bs-easing-standard),
|
|
302
|
+
visibility 0s linear var(--bs-navigation-drawer-overlay-duration);
|
|
303
|
+
}
|
|
283
304
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
305
|
+
:host([data-overlay]:dir(rtl)) .bs-navigation-drawer {
|
|
306
|
+
transform: translateX(100%);
|
|
307
|
+
}
|
|
287
308
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
309
|
+
:host([data-overlay]) .bs-navigation-drawer.bs-navigation-drawer--open {
|
|
310
|
+
transform: none;
|
|
311
|
+
visibility: visible;
|
|
312
|
+
transition:
|
|
313
|
+
transform var(--bs-navigation-drawer-overlay-duration) var(--bs-easing-standard),
|
|
314
|
+
visibility 0s;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/* Fully expanded inside the overlay, whatever `collapsed` says. Nothing sits behind the collapse
|
|
318
|
+
toggle or the compact search trigger here, so neither is shown. */
|
|
319
|
+
:host([data-overlay]) .bs-navigation-drawer__logo--full {
|
|
320
|
+
display: flex;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
:host([data-overlay]) .bs-navigation-drawer__logo--mark {
|
|
324
|
+
display: none;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
:host([data-overlay]) .bs-navigation-drawer__title {
|
|
328
|
+
display: block;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
:host([data-overlay]) .bs-navigation-drawer__search {
|
|
332
|
+
display: block;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
:host([data-overlay]) .bs-navigation-drawer__search-trigger,
|
|
336
|
+
:host([data-overlay]) .bs-navigation-drawer__collapse {
|
|
337
|
+
display: none;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.bs-navigation-drawer__backdrop {
|
|
341
|
+
position: fixed;
|
|
342
|
+
inset: 0;
|
|
343
|
+
z-index: var(--bs-navigation-drawer-overlay-z-index);
|
|
344
|
+
background: var(--bs-navigation-drawer-backdrop);
|
|
345
|
+
opacity: 0;
|
|
346
|
+
visibility: hidden;
|
|
347
|
+
transition:
|
|
348
|
+
opacity var(--bs-navigation-drawer-overlay-duration) var(--bs-easing-standard),
|
|
349
|
+
visibility 0s linear var(--bs-navigation-drawer-overlay-duration);
|
|
350
|
+
}
|
|
291
351
|
|
|
292
|
-
|
|
293
|
-
|
|
352
|
+
:host([open]) .bs-navigation-drawer__backdrop {
|
|
353
|
+
opacity: 1;
|
|
354
|
+
visibility: visible;
|
|
355
|
+
transition:
|
|
356
|
+
opacity var(--bs-navigation-drawer-overlay-duration) var(--bs-easing-standard),
|
|
357
|
+
visibility 0s;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
@media (prefers-reduced-motion: reduce) {
|
|
361
|
+
:host([data-overlay]) .bs-navigation-drawer,
|
|
362
|
+
.bs-navigation-drawer__backdrop {
|
|
363
|
+
transition: none;
|
|
294
364
|
}
|
|
365
|
+
}
|
|
295
366
|
|
|
296
|
-
|
|
297
|
-
|
|
367
|
+
@media (forced-colors: active) {
|
|
368
|
+
:host([data-overlay]) .bs-navigation-drawer {
|
|
369
|
+
border: 1px solid CanvasText;
|
|
298
370
|
}
|
|
299
371
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { h } from "@stencil/core";
|
|
1
|
+
import { Host, h } from "@stencil/core";
|
|
2
2
|
/**
|
|
3
3
|
* A left-side persistent navigation sidebar: the BrandSync logo, a "Main Menu" title with a
|
|
4
4
|
* collapse toggle, a reserved slot for a search field, and a scrollable list of nav items.
|
|
@@ -37,6 +37,14 @@ import { h } from "@stencil/core";
|
|
|
37
37
|
* that state, so this deliberately does not add the same "flip on toggle" idiom the drawer item's
|
|
38
38
|
* own disclosure chevron does (that one really is an unconfirmed addition; this one was checked).
|
|
39
39
|
*
|
|
40
|
+
* **Small screens (768px and below)** switch to an off-canvas overlay instead of a permanent rail:
|
|
41
|
+
* the drawer is hidden until `open` is set, then slides in over the page with a backdrop, fully
|
|
42
|
+
* expanded (labels visible, nested items reachable). Escape or a click on the backdrop closes it and
|
|
43
|
+
* emits `bsClose`; focus moves into it on open and back to whatever opened it on close. The
|
|
44
|
+
* collapse toggle and the compact search trigger are not shown in this mode (nothing sits behind
|
|
45
|
+
* them). The drawer has no trigger of its own -- put a button in your header and set `open` from it.
|
|
46
|
+
* On wider screens `open` is ignored and nothing changes.
|
|
47
|
+
*
|
|
40
48
|
* @slot search - Reserved for a search field, e.g. a `bs-input type="search"`. This component
|
|
41
49
|
* does not build one itself. Hidden while `collapsed` (see above).
|
|
42
50
|
* @slot - Default slot: the scrollable list of nav items, typically one or more
|
|
@@ -52,6 +60,7 @@ import { h } from "@stencil/core";
|
|
|
52
60
|
* @part search - The wrapper around the `search` slot.
|
|
53
61
|
* @part search-trigger - The compact search button shown instead of the `search` slot while `collapsed`.
|
|
54
62
|
* @part items - The wrapper around the default (items) slot.
|
|
63
|
+
* @part backdrop - The scrim behind the overlay (small screens only; clicking it closes the overlay).
|
|
55
64
|
*/
|
|
56
65
|
// Note: this component's CSS Custom Properties are documented via @prop comments in
|
|
57
66
|
// bs-navigation-drawer.css, not here -- see bs-navigation-header.css's identical note.
|
|
@@ -92,11 +101,112 @@ export class BsNavigationDrawer {
|
|
|
92
101
|
* pairing works too: a header that keeps its own logo (`alignment="default"`) paired with this
|
|
93
102
|
* drawer set to `showLogo={false}`, so the brand mark only ever appears once. */
|
|
94
103
|
showLogo = true;
|
|
95
|
-
|
|
96
|
-
|
|
104
|
+
/** Small screens only (768px and below): whether the off-canvas overlay is shown. Mutable and
|
|
105
|
+
* reflected -- the drawer sets it back to `false` itself when the user dismisses it (Escape or
|
|
106
|
+
* the backdrop), and emits `bsClose`. Ignored on wider screens, where the drawer is always in
|
|
107
|
+
* the page flow. There is no built-in trigger: set this from your own button. */
|
|
108
|
+
open = false;
|
|
109
|
+
/** Fires when the user dismisses the overlay (Escape, or a click on the backdrop), after `open`
|
|
110
|
+
* has been set back to `false`. Does not fire when you set `open = false` yourself. */
|
|
111
|
+
bsClose;
|
|
112
|
+
/** Whether the viewport is in the small-screen range (<= 768px), tracked with `matchMedia`. */
|
|
113
|
+
mobile = false;
|
|
114
|
+
mediaQuery;
|
|
115
|
+
focusPending = false;
|
|
116
|
+
navRef;
|
|
117
|
+
previouslyFocused;
|
|
118
|
+
bodyOverflowBefore;
|
|
119
|
+
get overlayOpen() {
|
|
120
|
+
return this.mobile && this.open;
|
|
121
|
+
}
|
|
122
|
+
connectedCallback() {
|
|
123
|
+
this.mediaQuery = window.matchMedia?.('(max-width: 768px)');
|
|
124
|
+
if (this.mediaQuery) {
|
|
125
|
+
this.mobile = this.mediaQuery.matches;
|
|
126
|
+
this.mediaQuery.addEventListener('change', this.onMediaChange);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
disconnectedCallback() {
|
|
130
|
+
this.mediaQuery?.removeEventListener('change', this.onMediaChange);
|
|
131
|
+
this.unlockScroll();
|
|
132
|
+
}
|
|
133
|
+
onMediaChange = (ev) => {
|
|
134
|
+
this.mobile = ev.matches;
|
|
135
|
+
};
|
|
136
|
+
onCollapsedChange() {
|
|
137
|
+
this.syncItems();
|
|
138
|
+
}
|
|
139
|
+
onMobileChange() {
|
|
140
|
+
this.syncItems();
|
|
141
|
+
this.applyOverlayState();
|
|
142
|
+
}
|
|
143
|
+
onOpenChange() {
|
|
144
|
+
this.applyOverlayState();
|
|
97
145
|
}
|
|
98
146
|
componentDidLoad() {
|
|
99
|
-
this.
|
|
147
|
+
this.syncItems();
|
|
148
|
+
this.applyOverlayState();
|
|
149
|
+
this.flushFocus();
|
|
150
|
+
}
|
|
151
|
+
componentDidRender() {
|
|
152
|
+
this.flushFocus();
|
|
153
|
+
}
|
|
154
|
+
/** Focus is moved only after the render that makes the panel visible -- focusing earlier races the
|
|
155
|
+
* re-render (the panel is still `visibility: hidden`), and a hidden element can't take focus. */
|
|
156
|
+
flushFocus() {
|
|
157
|
+
if (this.focusPending && this.overlayOpen) {
|
|
158
|
+
this.focusPending = false;
|
|
159
|
+
requestAnimationFrame(() => this.navRef?.focus());
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/** In the small-screen overlay the items always use their expanded layout -- the collapsed
|
|
163
|
+
* (icon-above-caption) layout is for the desktop rail, and would clip labels in a full-width
|
|
164
|
+
* panel and hide nested items. */
|
|
165
|
+
syncItems() {
|
|
166
|
+
this.syncItemsCollapsed(this.mobile ? false : this.collapsed);
|
|
167
|
+
}
|
|
168
|
+
/** Scroll lock, focus entry and focus return for the overlay, mirroring `bs-dialog`: the focus
|
|
169
|
+
* move is deferred a frame because focusing right after the panel becomes visible does not
|
|
170
|
+
* reliably land. */
|
|
171
|
+
applyOverlayState() {
|
|
172
|
+
if (this.overlayOpen) {
|
|
173
|
+
if (this.bodyOverflowBefore === undefined) {
|
|
174
|
+
this.bodyOverflowBefore = document.body.style.overflow;
|
|
175
|
+
document.body.style.overflow = 'hidden';
|
|
176
|
+
}
|
|
177
|
+
if (!this.previouslyFocused) {
|
|
178
|
+
this.previouslyFocused = document.activeElement;
|
|
179
|
+
}
|
|
180
|
+
this.focusPending = true;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
this.focusPending = false;
|
|
184
|
+
this.unlockScroll();
|
|
185
|
+
if (this.previouslyFocused?.isConnected)
|
|
186
|
+
this.previouslyFocused.focus();
|
|
187
|
+
this.previouslyFocused = undefined;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
unlockScroll() {
|
|
191
|
+
if (this.bodyOverflowBefore !== undefined) {
|
|
192
|
+
document.body.style.overflow = this.bodyOverflowBefore;
|
|
193
|
+
this.bodyOverflowBefore = undefined;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
requestClose = () => {
|
|
197
|
+
this.open = false;
|
|
198
|
+
this.bsClose.emit();
|
|
199
|
+
};
|
|
200
|
+
onDocumentKeydown(ev) {
|
|
201
|
+
if (this.overlayOpen && ev.key === 'Escape')
|
|
202
|
+
this.requestClose();
|
|
203
|
+
}
|
|
204
|
+
/** Keeps focus inside the open overlay: focus that lands anywhere outside this component is
|
|
205
|
+
* pulled back in. `composedPath()` is used so this works across shadow-DOM boundaries (same
|
|
206
|
+
* approach as `bs-dialog`). */
|
|
207
|
+
onDocumentFocusIn(ev) {
|
|
208
|
+
if (this.overlayOpen && !ev.composedPath().includes(this.el))
|
|
209
|
+
this.navRef?.focus();
|
|
100
210
|
}
|
|
101
211
|
/** Keeps every direct-child `bs-navigation-drawer-item`'s `collapsed` prop in sync with this
|
|
102
212
|
* component's own -- same direct-children-prop-sync approach `bs-tabs` uses for `selected`
|
|
@@ -117,7 +227,12 @@ export class BsNavigationDrawer {
|
|
|
117
227
|
this.bsSearchClick.emit();
|
|
118
228
|
};
|
|
119
229
|
render() {
|
|
120
|
-
|
|
230
|
+
const classes = ['bs-navigation-drawer', this.mobile ? 'bs-navigation-drawer--overlay' : '', this.overlayOpen ? 'bs-navigation-drawer--open' : ''].filter(Boolean).join(' ');
|
|
231
|
+
return (h(Host, { key: '94c3fbfb2d9826979f2f90ec0c9571aadc484450', "data-overlay": this.mobile ? '' : undefined }, this.mobile && h("div", { key: 'cc8b62b02a561dfbb0a15918e4bbbf241919ea7d', part: "backdrop", class: "bs-navigation-drawer__backdrop", onClick: this.requestClose }), h("nav", { key: 'ad3e970438fca27636992cc434584bfae7888895', ref: el => (this.navRef = el), class: classes, "aria-label": this.heading,
|
|
232
|
+
// Stays a plain <nav> landmark in every state: ARIA does not allow role="dialog" on <nav>
|
|
233
|
+
// (axe: aria-allowed-role). Modality is behavioral -- focus is held inside, the page behind is
|
|
234
|
+
// scrimmed, Escape closes -- rather than announced through aria-modal.
|
|
235
|
+
tabIndex: this.mobile ? -1 : undefined }, this.showLogo && (h("div", { key: '41552cc9bc1fd33081119b6b6a475e9a81281e97', part: "logo", class: "bs-navigation-drawer__logo bs-navigation-drawer__logo--full" }, h("bs-logo", { key: '96503cee7e467c535747171f46ab8b36f2d9262a', variant: "full", background: this.logoBackground }))), this.showLogo && (h("div", { key: '6b4e91b0296772ea492a2e12c1f81933be1af02b', part: "logo", class: "bs-navigation-drawer__logo bs-navigation-drawer__logo--mark" }, h("bs-logo", { key: '72c4cae8f25aebef923d2b346ee3a3224a1a4550', variant: "mark", background: this.logoBackground }))), h("div", { key: '2fde5f92e629d34321e0e0e6eaf776027614836a', class: "bs-navigation-drawer__title-row" }, h("span", { key: 'fde5717eeec30bbade48f574e44f9eec841bab36', part: "title", class: "bs-navigation-drawer__title" }, this.heading), this.collapsible && (h("button", { key: '59d514aec296c5b4eb459de259aa29d77a435ecf', type: "button", part: "collapse", class: "bs-navigation-drawer__collapse", "aria-label": this.collapsed ? 'Expand' : 'Collapse', "aria-pressed": this.collapsed ? 'true' : 'false', onClick: this.onCollapseClick }, h(CaretLeftIcon, { key: 'a992c1fcaa3e143ee9f1469958eeab12e03bce03' })))), h("div", { key: '1a74885abe2e50b3a6eccd7d4cacca4582dc5fa9', part: "search", class: "bs-navigation-drawer__search" }, h("slot", { key: 'ac98f9ca62a289e21fcbf0f005c6c0f7e02d9967', name: "search" })), h("button", { key: 'c7c50e5cf2c81ec8445a557505faf2ea40add094', type: "button", part: "search-trigger", class: "bs-navigation-drawer__search-trigger", "aria-label": "Search", onClick: this.onSearchTriggerClick }, h(SearchIcon, { key: '538bcfc474036d2c79fe821011490bf7cbd4d018' })), h("div", { key: '1a7aa824a99823b2d06309c5192a200afe378a7b', part: "items", class: "bs-navigation-drawer__items" }, h("slot", { key: '1a79d4f0e809b16a9d19efb06d36052c0539bba2' })))));
|
|
121
236
|
}
|
|
122
237
|
static get is() { return "bs-navigation-drawer"; }
|
|
123
238
|
static get encapsulation() { return "shadow"; }
|
|
@@ -232,9 +347,34 @@ export class BsNavigationDrawer {
|
|
|
232
347
|
"reflect": false,
|
|
233
348
|
"attribute": "show-logo",
|
|
234
349
|
"defaultValue": "true"
|
|
350
|
+
},
|
|
351
|
+
"open": {
|
|
352
|
+
"type": "boolean",
|
|
353
|
+
"mutable": true,
|
|
354
|
+
"complexType": {
|
|
355
|
+
"original": "boolean",
|
|
356
|
+
"resolved": "boolean",
|
|
357
|
+
"references": {}
|
|
358
|
+
},
|
|
359
|
+
"required": false,
|
|
360
|
+
"optional": false,
|
|
361
|
+
"docs": {
|
|
362
|
+
"tags": [],
|
|
363
|
+
"text": "Small screens only (768px and below): whether the off-canvas overlay is shown. Mutable and\nreflected -- the drawer sets it back to `false` itself when the user dismisses it (Escape or\nthe backdrop), and emits `bsClose`. Ignored on wider screens, where the drawer is always in\nthe page flow. There is no built-in trigger: set this from your own button."
|
|
364
|
+
},
|
|
365
|
+
"getter": false,
|
|
366
|
+
"setter": false,
|
|
367
|
+
"reflect": true,
|
|
368
|
+
"attribute": "open",
|
|
369
|
+
"defaultValue": "false"
|
|
235
370
|
}
|
|
236
371
|
};
|
|
237
372
|
}
|
|
373
|
+
static get states() {
|
|
374
|
+
return {
|
|
375
|
+
"mobile": {}
|
|
376
|
+
};
|
|
377
|
+
}
|
|
238
378
|
static get events() {
|
|
239
379
|
return [{
|
|
240
380
|
"method": "bsCollapse",
|
|
@@ -266,6 +406,21 @@ export class BsNavigationDrawer {
|
|
|
266
406
|
"resolved": "void",
|
|
267
407
|
"references": {}
|
|
268
408
|
}
|
|
409
|
+
}, {
|
|
410
|
+
"method": "bsClose",
|
|
411
|
+
"name": "bsClose",
|
|
412
|
+
"bubbles": true,
|
|
413
|
+
"cancelable": true,
|
|
414
|
+
"composed": true,
|
|
415
|
+
"docs": {
|
|
416
|
+
"tags": [],
|
|
417
|
+
"text": "Fires when the user dismisses the overlay (Escape, or a click on the backdrop), after `open`\nhas been set back to `false`. Does not fire when you set `open = false` yourself."
|
|
418
|
+
},
|
|
419
|
+
"complexType": {
|
|
420
|
+
"original": "void",
|
|
421
|
+
"resolved": "void",
|
|
422
|
+
"references": {}
|
|
423
|
+
}
|
|
269
424
|
}];
|
|
270
425
|
}
|
|
271
426
|
static get elementRef() { return "el"; }
|
|
@@ -273,6 +428,27 @@ export class BsNavigationDrawer {
|
|
|
273
428
|
return [{
|
|
274
429
|
"propName": "collapsed",
|
|
275
430
|
"methodName": "onCollapsedChange"
|
|
431
|
+
}, {
|
|
432
|
+
"propName": "mobile",
|
|
433
|
+
"methodName": "onMobileChange"
|
|
434
|
+
}, {
|
|
435
|
+
"propName": "open",
|
|
436
|
+
"methodName": "onOpenChange"
|
|
437
|
+
}];
|
|
438
|
+
}
|
|
439
|
+
static get listeners() {
|
|
440
|
+
return [{
|
|
441
|
+
"name": "keydown",
|
|
442
|
+
"method": "onDocumentKeydown",
|
|
443
|
+
"target": "document",
|
|
444
|
+
"capture": false,
|
|
445
|
+
"passive": false
|
|
446
|
+
}, {
|
|
447
|
+
"name": "focusin",
|
|
448
|
+
"method": "onDocumentFocusIn",
|
|
449
|
+
"target": "document",
|
|
450
|
+
"capture": false,
|
|
451
|
+
"passive": false
|
|
276
452
|
}];
|
|
277
453
|
}
|
|
278
454
|
}
|