mirror of
https://github.com/material-components/material-web.git
synced 2024-09-11 13:46:10 +03:00
refactor(menu,select)!: rename fixed
to positioning
This will enable forwards compatibility for `positioning="top-layer"` with popover. BREAKING CHANGE: refactor `fixed` property to `positioning="fixed"` in Menu and `menuFixed` to `menuPositioning="fixed"` PiperOrigin-RevId: 567723646
This commit is contained in:
parent
2a1d8776a7
commit
63b01425e7
@ -398,7 +398,7 @@ export function selectDropdown<T extends string>({
|
||||
<label>
|
||||
<md-filled-select
|
||||
@change="${valueChanged}"
|
||||
menu-fixed
|
||||
menu-positioning="fixed"
|
||||
style=${styleMap(sharedTextFieldStyles)}>
|
||||
${listItems}
|
||||
</md-filled-select>
|
||||
|
@ -195,7 +195,7 @@
|
||||
overflow: hidden;
|
||||
// needed to display scrollbars on Chrome linux. Also needs to be > 0 so
|
||||
// that content that is position: fixed in the content can render above the
|
||||
// actions bar. e.g. <md-select menu-fixed>
|
||||
// actions bar. e.g. <md-select positioning="menu-fixed">
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<div style="margin: 16px">
|
||||
<md-filled-button id="usage-fixed-anchor">Open fixed menu</md-filled-button>
|
||||
</div>
|
||||
<md-menu fixed id="usage-fixed" anchor="usage-fixed-anchor">
|
||||
<md-menu positioning="fixed" id="usage-fixed" anchor="usage-fixed-anchor">
|
||||
<md-menu-item headline="Apple"></md-menu-item>
|
||||
<md-menu-item headline="Banana"></md-menu-item>
|
||||
<md-menu-item headline="Cucumber"></md-menu-item>
|
||||
|
@ -194,8 +194,8 @@ Internally menu uses `position: absolute` by default. Though there are cases
|
||||
when the anchor and the node cannot share a common ancestor that is `position:
|
||||
relative`, or sometimes, menu will render below another item due to limitations
|
||||
with `position: absolute`. In most of these cases, you would want to use the
|
||||
`fixed` attribute to position the menu relative to the window instead of
|
||||
relative to the parent.
|
||||
`positioning="fixed"` attribute to position the menu relative to the window
|
||||
instead of relative to the parent.
|
||||
|
||||
> Note: Fixed menu positions are positioned relative to the window and not the
|
||||
> document. This means that the menu will not scroll with the anchor as the page
|
||||
@ -217,7 +217,7 @@ Cucumber."](images/menu/usage-fixed.webp)
|
||||
</div>
|
||||
|
||||
<!-- Fixed menus do not require a common ancestor with the anchor. -->
|
||||
<md-menu fixed id="usage-fixed" anchor="usage-fixed-anchor">
|
||||
<md-menu positioning="fixed" id="usage-fixed" anchor="usage-fixed-anchor">
|
||||
<md-menu-item headline="Apple"></md-menu-item>
|
||||
<md-menu-item headline="Banana"></md-menu-item>
|
||||
<md-menu-item headline="Cucumber"></md-menu-item>
|
||||
@ -353,7 +353,6 @@ a sharp 0px border radius.](images/menu/theming.webp)
|
||||
|
||||
## API
|
||||
|
||||
|
||||
### MdMenu <md-menu>
|
||||
|
||||
#### Properties
|
||||
|
@ -49,11 +49,16 @@ const collection =
|
||||
]
|
||||
}),
|
||||
}),
|
||||
new Knob('open', {
|
||||
defaultValue: false,
|
||||
ui: boolInput(),
|
||||
new Knob('positioning', {
|
||||
defaultValue: 'absolute' as const,
|
||||
ui: selectDropdown<'absolute'|'fixed'>({
|
||||
options: [
|
||||
{label: 'absolute', value: 'absolute'},
|
||||
{label: 'fixed', value: 'fixed'},
|
||||
]
|
||||
})
|
||||
}),
|
||||
new Knob('fixed', {
|
||||
new Knob('open', {
|
||||
defaultValue: false,
|
||||
ui: boolInput(),
|
||||
}),
|
||||
|
@ -23,8 +23,8 @@ export interface StoryKnobs {
|
||||
anchorCorner: Corner|undefined;
|
||||
menuCorner: Corner|undefined;
|
||||
defaultFocus: FocusState|undefined;
|
||||
positioning: 'absolute'|'fixed'|undefined;
|
||||
open: boolean;
|
||||
fixed: boolean;
|
||||
quick: boolean;
|
||||
hasOverflow: boolean;
|
||||
stayOpenOnOutsideClick: boolean;
|
||||
@ -120,7 +120,7 @@ const standard: MaterialStoryInit<StoryKnobs> = {
|
||||
.menuCorner="${knobs.menuCorner!}"
|
||||
.xOffset=${knobs.xOffset}
|
||||
.yOffset=${knobs.yOffset}
|
||||
.fixed=${knobs.fixed}
|
||||
.positioning=${knobs.positioning!}
|
||||
.defaultFocus=${knobs.defaultFocus!}
|
||||
.skipRestoreFocus=${knobs.skipRestoreFocus}
|
||||
.typeaheadDelay=${knobs.typeaheadDelay}
|
||||
@ -188,7 +188,7 @@ const linkable: MaterialStoryInit<StoryKnobs> = {
|
||||
.menuCorner="${knobs.menuCorner!}"
|
||||
.xOffset=${knobs.xOffset}
|
||||
.yOffset=${knobs.yOffset}
|
||||
.fixed=${knobs.fixed}
|
||||
.positioning=${knobs.positioning!}
|
||||
.defaultFocus=${knobs.defaultFocus!}
|
||||
.skipRestoreFocus=${knobs.skipRestoreFocus}
|
||||
.typeaheadDelay=${knobs.typeaheadDelay}
|
||||
@ -250,7 +250,7 @@ const submenu: MaterialStoryInit<StoryKnobs> = {
|
||||
.ariaLabel=${knobs.ariaLabel}
|
||||
.xOffset=${knobs.xOffset}
|
||||
.yOffset=${knobs.yOffset}
|
||||
.fixed=${knobs.fixed}
|
||||
.positioning=${knobs.positioning!}
|
||||
.defaultFocus=${knobs.defaultFocus!}
|
||||
.typeaheadDelay=${knobs.typeaheadDelay}>
|
||||
${layer2}
|
||||
@ -296,7 +296,7 @@ const submenu: MaterialStoryInit<StoryKnobs> = {
|
||||
.ariaLabel=${knobs.ariaLabel}
|
||||
.xOffset=${knobs.xOffset}
|
||||
.yOffset=${knobs.yOffset}
|
||||
.fixed=${knobs.fixed}
|
||||
.positioning=${knobs.positioning!}
|
||||
.defaultFocus=${knobs.defaultFocus!}
|
||||
.typeaheadDelay=${knobs.typeaheadDelay}>
|
||||
${layer1}
|
||||
@ -327,7 +327,7 @@ const submenu: MaterialStoryInit<StoryKnobs> = {
|
||||
.menuCorner="${knobs.menuCorner!}"
|
||||
.xOffset=${knobs.xOffset}
|
||||
.yOffset=${knobs.yOffset}
|
||||
.fixed=${knobs.fixed}
|
||||
.positioning=${knobs.positioning!}
|
||||
.defaultFocus=${knobs.defaultFocus!}
|
||||
.skipRestoreFocus=${knobs.skipRestoreFocus}
|
||||
.typeaheadDelay=${knobs.typeaheadDelay}
|
||||
@ -377,7 +377,7 @@ const menuWithoutButton: MaterialStoryInit<StoryKnobs> = {
|
||||
.menuCorner="${knobs.menuCorner!}"
|
||||
.xOffset=${knobs.xOffset}
|
||||
.yOffset=${knobs.yOffset}
|
||||
.fixed=${knobs.fixed}
|
||||
.positioning=${knobs.positioning!}
|
||||
.defaultFocus=${knobs.defaultFocus!}
|
||||
.skipRestoreFocus=${knobs.skipRestoreFocus}
|
||||
.typeaheadDelay=${knobs.typeaheadDelay}
|
||||
|
@ -17,7 +17,7 @@ import {createAnimationSignal, EASING} from '../../internal/motion/animation.js'
|
||||
|
||||
import {ListController, NavigableKeys} from './list-controller.js';
|
||||
import {getActiveItem, getFirstActivatableItem, getLastActivatableItem} from './list-navigation-helpers.js';
|
||||
import {ActivateTypeaheadEvent, DeactivateTypeaheadEvent, isClosableKey, isElementInSubtree, MenuItem} from './shared.js';
|
||||
import {ActivateTypeaheadEvent, DeactivateTypeaheadEvent, FocusState, isClosableKey, isElementInSubtree, MenuItem} from './shared.js';
|
||||
import {Corner, SurfacePositionController, SurfacePositionTarget} from './surfacePositionController.js';
|
||||
import {TypeaheadController} from './typeaheadController.js';
|
||||
|
||||
@ -41,22 +41,6 @@ const menuNavKeys = new Set<string>([
|
||||
...submenuNavKeys,
|
||||
]);
|
||||
|
||||
/**
|
||||
* Element to focus on when menu is first opened.
|
||||
*/
|
||||
// tslint:disable-next-line:enforce-name-casing We are mimicking enum style
|
||||
export const FocusState = {
|
||||
NONE: 'none',
|
||||
LIST_ROOT: 'list-root',
|
||||
FIRST_ITEM: 'first-item',
|
||||
LAST_ITEM: 'last-item'
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Element to focus on when menu is first opened.
|
||||
*/
|
||||
export type FocusState = typeof FocusState[keyof typeof FocusState];
|
||||
|
||||
/**
|
||||
* Gets the currently focused element on the page.
|
||||
*
|
||||
@ -101,15 +85,26 @@ export abstract class Menu extends LitElement {
|
||||
*/
|
||||
@property() anchor = '';
|
||||
/**
|
||||
* Makes the element use `position:fixed` instead of `position:absolute`. In
|
||||
* most cases, the menu should position itself above most other
|
||||
* `position:absolute` or `position:fixed` elements when placed inside of
|
||||
* them. e.g. using a menu inside of an `md-dialog`.
|
||||
* Whether the positioning algorithim should calculate relative to the parent
|
||||
* of the anchor element (absolute) or relative to the window (fixed).
|
||||
*
|
||||
* Examples for `position = 'fixed'`:
|
||||
*
|
||||
* - If there is no `position:relative` in the given parent tree and the
|
||||
* surface is `position:absolute`
|
||||
* - If the surface is `position:fixed`
|
||||
* - If the surface is in the "top layer"
|
||||
* - The anchor and the surface do not share a common `position:relative`
|
||||
* ancestor
|
||||
*
|
||||
* When using positioning = fixed, in most cases, the menu should position
|
||||
* itself above most other `position:absolute` or `position:fixed` elements
|
||||
* when placed inside of them. e.g. using a menu inside of an `md-dialog`.
|
||||
*
|
||||
* __NOTE__: Fixed menus will not scroll with the page and will be fixed to
|
||||
* the window instead.
|
||||
*/
|
||||
@property({type: Boolean}) fixed = false;
|
||||
@property() positioning: 'absolute'|'fixed' = 'absolute';
|
||||
/**
|
||||
* Skips the opening and closing animations.
|
||||
*/
|
||||
@ -325,7 +320,7 @@ export abstract class Menu extends LitElement {
|
||||
surfaceCorner: this.menuCorner,
|
||||
surfaceEl: this.surfaceEl,
|
||||
anchorEl: this.anchorElement,
|
||||
isTopLayer: this.fixed,
|
||||
positioning: this.positioning,
|
||||
isOpen: this.open,
|
||||
xOffset: this.xOffset,
|
||||
yOffset: this.yOffset,
|
||||
@ -403,7 +398,7 @@ export abstract class Menu extends LitElement {
|
||||
private getSurfaceClasses() {
|
||||
return {
|
||||
open: this.open,
|
||||
fixed: this.fixed,
|
||||
fixed: this.positioning === 'fixed',
|
||||
'has-overflow': this.hasOverflow,
|
||||
};
|
||||
}
|
||||
|
@ -227,3 +227,19 @@ export function isElementInSubtree(
|
||||
const isContained = composedPath.length > 0;
|
||||
return isContained;
|
||||
}
|
||||
|
||||
/**
|
||||
* Element to focus on when menu is first opened.
|
||||
*/
|
||||
// tslint:disable-next-line:enforce-name-casing We are mimicking enum style
|
||||
export const FocusState = {
|
||||
NONE: 'none',
|
||||
LIST_ROOT: 'list-root',
|
||||
FIRST_ITEM: 'first-item',
|
||||
LAST_ITEM: 'last-item'
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Element to focus on when menu is first opened.
|
||||
*/
|
||||
export type FocusState = typeof FocusState[keyof typeof FocusState];
|
@ -53,10 +53,10 @@ export interface SurfacePositionControllerProperties {
|
||||
*/
|
||||
anchorEl: SurfacePositionTarget|null;
|
||||
/**
|
||||
* Whether or not the calculation should be relative to the top layer rather
|
||||
* than relative to the parent of the anchor.
|
||||
* Whether the positioning algorithim should calculate relative to the parent
|
||||
* of the anchor element (absolute) or relative to the window (fixed).
|
||||
*
|
||||
* Examples for `isTopLayer:true`:
|
||||
* Examples for `position = 'fixed'`:
|
||||
*
|
||||
* - If there is no `position:relative` in the given parent tree and the
|
||||
* surface is `position:absolute`
|
||||
@ -65,7 +65,7 @@ export interface SurfacePositionControllerProperties {
|
||||
* - The anchor and the surface do not share a common `position:relative`
|
||||
* ancestor
|
||||
*/
|
||||
isTopLayer: boolean;
|
||||
positioning: 'absolute'|'fixed';
|
||||
/**
|
||||
* Whether or not the surface should be "open" and visible
|
||||
*/
|
||||
@ -153,7 +153,7 @@ export class SurfacePositionController implements ReactiveController {
|
||||
anchorEl,
|
||||
anchorCorner: anchorCornerRaw,
|
||||
surfaceCorner: surfaceCornerRaw,
|
||||
isTopLayer,
|
||||
positioning,
|
||||
xOffset,
|
||||
yOffset,
|
||||
repositionStrategy,
|
||||
@ -231,7 +231,7 @@ export class SurfacePositionController implements ReactiveController {
|
||||
anchorBlock,
|
||||
surfaceBlock,
|
||||
yOffset,
|
||||
isTopLayer
|
||||
positioning
|
||||
});
|
||||
|
||||
// If the surface should be out of bounds in the block direction, flip the
|
||||
@ -246,7 +246,7 @@ export class SurfacePositionController implements ReactiveController {
|
||||
anchorBlock: flippedAnchorBlock,
|
||||
surfaceBlock: flippedSurfaceBlock,
|
||||
yOffset,
|
||||
isTopLayer
|
||||
positioning
|
||||
});
|
||||
|
||||
// In the case that the flipped verion would require less out of bounds
|
||||
@ -267,7 +267,7 @@ export class SurfacePositionController implements ReactiveController {
|
||||
anchorInline,
|
||||
surfaceInline,
|
||||
xOffset,
|
||||
isTopLayer,
|
||||
positioning,
|
||||
isLTR,
|
||||
});
|
||||
|
||||
@ -283,7 +283,7 @@ export class SurfacePositionController implements ReactiveController {
|
||||
anchorInline: flippedAnchorInline,
|
||||
surfaceInline: flippedSurfaceInline,
|
||||
xOffset,
|
||||
isTopLayer,
|
||||
positioning,
|
||||
isLTR,
|
||||
});
|
||||
|
||||
@ -340,7 +340,7 @@ export class SurfacePositionController implements ReactiveController {
|
||||
anchorBlock: 'start'|'end',
|
||||
surfaceBlock: 'start'|'end',
|
||||
yOffset: number,
|
||||
isTopLayer: boolean,
|
||||
positioning: 'absolute'|'fixed',
|
||||
}) {
|
||||
const {
|
||||
surfaceRect,
|
||||
@ -348,11 +348,11 @@ export class SurfacePositionController implements ReactiveController {
|
||||
anchorBlock,
|
||||
surfaceBlock,
|
||||
yOffset,
|
||||
isTopLayer: isTopLayerBool,
|
||||
positioning,
|
||||
} = config;
|
||||
// We use number booleans to multiply values rather than `if` / ternary
|
||||
// statements because it _heavily_ cuts down on nesting and readability
|
||||
const isTopLayer = isTopLayerBool ? 1 : 0;
|
||||
const relativeToWindow = positioning === 'fixed' ? 1 : 0;
|
||||
const isSurfaceBlockStart = surfaceBlock === 'start' ? 1 : 0;
|
||||
const isSurfaceBlockEnd = surfaceBlock === 'end' ? 1 : 0;
|
||||
const isOneBlockEnd = anchorBlock !== surfaceBlock ? 1 : 0;
|
||||
@ -371,7 +371,8 @@ export class SurfacePositionController implements ReactiveController {
|
||||
|
||||
|
||||
// The block logical value of the surface
|
||||
const blockInset = isTopLayer * blockTopLayerOffset + blockAnchorOffset;
|
||||
const blockInset =
|
||||
relativeToWindow * blockTopLayerOffset + blockAnchorOffset;
|
||||
|
||||
const surfaceBlockProperty =
|
||||
surfaceBlock === 'start' ? 'inset-block-start' : 'inset-block-end';
|
||||
@ -390,7 +391,7 @@ export class SurfacePositionController implements ReactiveController {
|
||||
anchorRect: DOMRect,
|
||||
surfaceRect: DOMRect,
|
||||
xOffset: number,
|
||||
isTopLayer: boolean,
|
||||
positioning: 'absolute'|'fixed',
|
||||
}) {
|
||||
const {
|
||||
isLTR: isLTRBool,
|
||||
@ -399,11 +400,11 @@ export class SurfacePositionController implements ReactiveController {
|
||||
anchorRect,
|
||||
surfaceRect,
|
||||
xOffset,
|
||||
isTopLayer: isTopLayerBool,
|
||||
positioning,
|
||||
} = config;
|
||||
// We use number booleans to multiply values rather than `if` / ternary
|
||||
// statements because it _heavily_ cuts down on nesting and readability
|
||||
const isTopLayer = isTopLayerBool ? 1 : 0;
|
||||
const relativeToWindow = positioning === 'fixed' ? 1 : 0;
|
||||
const isLTR = isLTRBool ? 1 : 0;
|
||||
const isRTL = isLTRBool ? 0 : 1;
|
||||
const isSurfaceInlineStart = surfaceInline === 'start' ? 1 : 0;
|
||||
@ -432,7 +433,8 @@ export class SurfacePositionController implements ReactiveController {
|
||||
|
||||
|
||||
// The inline logical value of the surface
|
||||
const inlineInset = isTopLayer * inlineTopLayerOffset + inlineAnchorOffset;
|
||||
const inlineInset =
|
||||
relativeToWindow * inlineTopLayerOffset + inlineAnchorOffset;
|
||||
|
||||
const surfaceInlineProperty =
|
||||
surfaceInline === 'start' ? 'inset-inline-start' : 'inset-inline-end';
|
||||
|
@ -11,8 +11,8 @@ import {Menu} from './internal/menu.js';
|
||||
import {styles} from './internal/menu-styles.css.js';
|
||||
|
||||
export {ListItem} from '../list/internal/listitem/list-item.js';
|
||||
export {Corner, FocusState} from './internal/menu.js';
|
||||
export {CloseMenuEvent, MenuItem} from './internal/shared.js';
|
||||
export {Corner} from './internal/menu.js';
|
||||
export {CloseMenuEvent, FocusState, MenuItem} from './internal/shared.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
@ -28,8 +28,9 @@ declare global {
|
||||
* `deselect-items` events.
|
||||
*
|
||||
* This menu item will open a sub-menu that is slotted in the `submenu` slot.
|
||||
* Additionally, the containing menu must either have `has-overflow` or `fixed`
|
||||
* set to `true` in order to display the containing menu properly.
|
||||
* Additionally, the containing menu must either have `has-overflow` or
|
||||
* `positioning=fixed` set to `true` in order to display the containing menu
|
||||
* properly.
|
||||
*
|
||||
* @example
|
||||
* ```html
|
||||
|
@ -8,7 +8,7 @@ import './index.js';
|
||||
import './material-collection.js';
|
||||
|
||||
import {KnobTypesToKnobs, MaterialCollection, materialInitsToStoryInits, setUpDemo, title} from './material-collection.js';
|
||||
import {boolInput, Knob, numberInput, textInput} from './index.js';
|
||||
import {boolInput, Knob, numberInput, selectDropdown, textInput} from './index.js';
|
||||
|
||||
import {stories, StoryKnobs} from './stories.js';
|
||||
|
||||
@ -22,8 +22,16 @@ const collection =
|
||||
new Knob('disabled', {ui: boolInput(), defaultValue: false}),
|
||||
new Knob('errorText', {ui: textInput(), defaultValue: ''}),
|
||||
new Knob('supportingText', {ui: textInput(), defaultValue: ''}),
|
||||
new Knob('menuPositioning', {
|
||||
defaultValue: 'absolute' as const,
|
||||
ui: selectDropdown<'absolute'|'fixed'>({
|
||||
options: [
|
||||
{label: 'absolute', value: 'absolute'},
|
||||
{label: 'fixed', value: 'fixed'},
|
||||
]
|
||||
})
|
||||
}),
|
||||
new Knob('error', {ui: boolInput(), defaultValue: false}),
|
||||
new Knob('menuFixed', {ui: boolInput(), defaultValue: false}),
|
||||
|
||||
new Knob('md-select Slots', {ui: title()}),
|
||||
new Knob('slot=leading-icon', {ui: textInput(), defaultValue: ''}),
|
||||
|
@ -23,7 +23,7 @@ export interface StoryKnobs {
|
||||
errorText: string;
|
||||
supportingText: string;
|
||||
error: boolean;
|
||||
menuFixed: boolean;
|
||||
menuPositioning: 'absolute'|'fixed'|undefined;
|
||||
|
||||
'md-select Slots': void;
|
||||
'slot=leading-icon': string;
|
||||
@ -41,7 +41,7 @@ const outlined: MaterialStoryInit<StoryKnobs> = {
|
||||
.disabled=${knobs.disabled}
|
||||
.errorText=${knobs.errorText}
|
||||
.supportingText=${knobs.supportingText}
|
||||
.menuFixed=${knobs.menuFixed}
|
||||
.menuPositioning=${knobs.menuPositioning!}
|
||||
.typeaheadDelay=${knobs.typeaheadDelay}
|
||||
.error=${knobs.error}>
|
||||
${renderIcon(knobs['slot=leading-icon'], 'leading-icon')}
|
||||
@ -63,7 +63,7 @@ const filled: MaterialStoryInit<StoryKnobs> = {
|
||||
.disabled=${knobs.disabled}
|
||||
.errorText=${knobs.errorText}
|
||||
.supportingText=${knobs.supportingText}
|
||||
.menuFixed=${knobs.menuFixed}
|
||||
.menuPositioning=${knobs.menuPositioning!}
|
||||
.typeaheadDelay=${knobs.typeaheadDelay}
|
||||
.error=${knobs.error}>
|
||||
${renderIcon(knobs['slot=leading-icon'], 'leading-icon')}
|
||||
|
@ -77,9 +77,13 @@ export abstract class Select extends LitElement {
|
||||
@property({type: Boolean, reflect: true}) error = false;
|
||||
/**
|
||||
* Whether or not the underlying md-menu should be position: fixed to display
|
||||
* in a top-level manner.
|
||||
* in a top-level manner, or position: absolute.
|
||||
*
|
||||
* position:fixed is useful for cases where select is inside of another
|
||||
* element with stacking context and hidden overflows such as `md-dialog`.
|
||||
*/
|
||||
@property({type: Boolean, attribute: 'menu-fixed'}) menuFixed = false;
|
||||
@property({attribute: 'menu-positioning'})
|
||||
menuPositioning: 'absolute'|'fixed' = 'absolute';
|
||||
/**
|
||||
* The max time between the keystrokes of the typeahead select / menu behavior
|
||||
* before it clears the typeahead buffer.
|
||||
@ -478,7 +482,7 @@ export abstract class Select extends LitElement {
|
||||
anchor="field"
|
||||
.open=${this.open}
|
||||
.quick=${this.quick}
|
||||
.fixed=${this.menuFixed}
|
||||
.positioning=${this.menuPositioning}
|
||||
.typeaheadDelay=${this.typeaheadDelay}
|
||||
@opening=${this.handleOpening}
|
||||
@opened=${this.redispatchEvent}
|
||||
|
Loading…
Reference in New Issue
Block a user