@api-client/ui 0.5.53 → 0.5.54
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/build/src/md/menu/internal/Menu.d.ts.map +1 -1
- package/build/src/md/menu/internal/Menu.js +16 -5
- package/build/src/md/menu/internal/Menu.js.map +1 -1
- package/build/src/md/menu/internal/Menu.styles.d.ts.map +1 -1
- package/build/src/md/menu/internal/Menu.styles.js +5 -1
- package/build/src/md/menu/internal/Menu.styles.js.map +1 -1
- package/build/src/md/select/internals/Select.d.ts +21 -0
- package/build/src/md/select/internals/Select.d.ts.map +1 -1
- package/build/src/md/select/internals/Select.js +98 -0
- package/build/src/md/select/internals/Select.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/md/menu/internal/Menu.styles.ts +5 -1
- package/src/md/menu/internal/Menu.ts +17 -6
- package/src/md/select/internals/Select.ts +116 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAI1D,OAAO,MAAM,MAAM,8BAA8B,CAAA;AACjD,OAAO,UAAU,MAAM,eAAe,CAAA;AACtC,OAAO,SAAS,MAAM,cAAc,CAAA;AAEpC,OAAO,UAAU,MAAM,kCAAkC,CAAA;AAGzD;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,MAAM;IACtC;;;OAGG;IACyC,QAAQ,CAAC,IAAI,UAAQ;IAEjE;;;OAGG;IACyC,QAAQ,CAAC,QAAQ,UAAQ;IAErE;;;;;;;;OAQG;IAC0B,QAAQ,CAAC,gBAAgB,UAAQ;IAE9D;;OAEG;IACM,QAAQ,CAAC,aAAa,EAAE,SAAS,GAAG,IAAI,CAAO;;IAS/C,iBAAiB,IAAI,IAAI;cAYf,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI;IAQhE,aAAa,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO;
|
|
1
|
+
{"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAI1D,OAAO,MAAM,MAAM,8BAA8B,CAAA;AACjD,OAAO,UAAU,MAAM,eAAe,CAAA;AACtC,OAAO,SAAS,MAAM,cAAc,CAAA;AAEpC,OAAO,UAAU,MAAM,kCAAkC,CAAA;AAGzD;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,MAAM;IACtC;;;OAGG;IACyC,QAAQ,CAAC,IAAI,UAAQ;IAEjE;;;OAGG;IACyC,QAAQ,CAAC,QAAQ,UAAQ;IAErE;;;;;;;;OAQG;IAC0B,QAAQ,CAAC,gBAAgB,UAAQ;IAE9D;;OAEG;IACM,QAAQ,CAAC,aAAa,EAAE,SAAS,GAAG,IAAI,CAAO;;IAS/C,iBAAiB,IAAI,IAAI;cAYf,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI;IAQhE,aAAa,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO;IAchD,SAAS,CAAC,cAAc,IAAI,UAAU,EAAE;IAOxC,IAAI,IAAI,IAAI;IAIZ,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACM,WAAW,IAAI,IAAI;IAU5B;;OAEG;IACM,WAAW,IAAI,IAAI;IAS5B,YAAY,IAAI,IAAI;IAiEpB;;OAEG;IACH,SAAS,CAAC,kBAAkB,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;IAQ5C;;OAEG;IACM,aAAa,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI;IAuB9C,mBAAmB,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI;IAIzC;;OAEG;IACH,SAAS,CAAC,WAAW,IAAI,IAAI;IAO7B;;OAEG;IACH,YAAY,IAAI,IAAI;IAQpB;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI;IAKxC,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO;IAUzF;;OAEG;IACH,SAAS,CAAC,cAAc,IAAI,IAAI;IAOhC;;OAEG;IACH,IAAI,YAAY,IAAI,UAAU,GAAG,IAAI,CAGpC;IAED;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI;IAO9C;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI;IAKjD;;OAEG;IACH,SAAS,CAAC,gBAAgB,IAAI,IAAI;IAKzB,MAAM,IAAI,cAAc;CAWlC"}
|
|
@@ -113,12 +113,14 @@ let Menu = (() => {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
togglePopover(force) {
|
|
116
|
+
if (!this.open && !this.disabled) {
|
|
117
|
+
this.positionMenu();
|
|
118
|
+
}
|
|
116
119
|
this.open = !this.open;
|
|
117
120
|
this.ariaExpanded = String(this.open);
|
|
118
121
|
this.tabIndex = this.open ? 0 : -1;
|
|
119
122
|
const result = super.togglePopover(force);
|
|
120
123
|
if (this.open) {
|
|
121
|
-
this.positionMenu();
|
|
122
124
|
this.focus();
|
|
123
125
|
}
|
|
124
126
|
return result;
|
|
@@ -142,9 +144,9 @@ let Menu = (() => {
|
|
|
142
144
|
showPopover() {
|
|
143
145
|
this.tabIndex = 0; // Make menu focusable
|
|
144
146
|
this.ariaExpanded = 'true';
|
|
147
|
+
this.positionMenu();
|
|
145
148
|
super.showPopover();
|
|
146
149
|
this.open = true;
|
|
147
|
-
this.positionMenu();
|
|
148
150
|
this.focus();
|
|
149
151
|
this.dispatchEvent(new CustomEvent('open', { bubbles: false, composed: true }));
|
|
150
152
|
}
|
|
@@ -160,13 +162,17 @@ let Menu = (() => {
|
|
|
160
162
|
this.dispatchEvent(new CustomEvent('close', { bubbles: false, composed: true }));
|
|
161
163
|
}
|
|
162
164
|
positionMenu() {
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
|
|
165
|
+
// for the frame, make the element visible (without animations)
|
|
166
|
+
// to take measurements correctly.
|
|
167
|
+
this.classList.add('measurements');
|
|
166
168
|
// Reset any previous manual positioning to let CSS anchor positioning work
|
|
167
169
|
this.style.removeProperty('position-area');
|
|
168
170
|
this.style.removeProperty('max-height');
|
|
169
171
|
this.style.removeProperty('max-width');
|
|
172
|
+
// Let CSS anchor positioning handle the positioning automatically
|
|
173
|
+
// Only intervene if we need to set max-height for overflow cases
|
|
174
|
+
const box = this.getBoundingClientRect();
|
|
175
|
+
this.classList.remove('measurements');
|
|
170
176
|
// Check if the menu content is being clipped
|
|
171
177
|
const isVerticallyClipped = this.scrollHeight > this.clientHeight;
|
|
172
178
|
const isHorizontallyClipped = this.scrollWidth > this.clientWidth;
|
|
@@ -177,6 +183,11 @@ let Menu = (() => {
|
|
|
177
183
|
// by checking if the menu is in the upper or lower half of the viewport
|
|
178
184
|
const viewportMiddle = innerHeight / 2;
|
|
179
185
|
const isMenuInUpperHalf = box.top < viewportMiddle;
|
|
186
|
+
// console.log(`Menu positioned at: top=${box.top}, left=${box.left}, bottom=${menuBottom}, right=${menuRight}`)
|
|
187
|
+
// console.log(
|
|
188
|
+
// eslint-disable-next-line max-len
|
|
189
|
+
// `Menu is in upper half: ${isMenuInUpperHalf}, Vertically clipped: ${isVerticallyClipped}, Horizontally clipped: ${isHorizontallyClipped}`
|
|
190
|
+
// )
|
|
180
191
|
// Add CSS class to control animation direction
|
|
181
192
|
if (isMenuInUpperHalf) {
|
|
182
193
|
this.classList.add('menu-positioned-above');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.js","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, PropertyValues, TemplateResult } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { nanoid } from 'nanoid'\nimport UiList from '../../list/internals/List.js'\nimport UiMenuItem from './MenuItem.js'\nimport UiSubMenu from './SubMenu.js'\nimport { setDisabled } from '../../../lib/disabled.js'\nimport UiListItem from '../../list/internals/ListItem.js'\nimport { bound } from '../../../decorators/bound.js'\n\n/**\n * Material Design 3 Menu component with sub-menu support.\n * Uses Popover API and Anchor Positioning API for modern positioning.\n *\n * @fires select - Dispatched when a menu item is selected\n * @fires close - Dispatched when the menu is closed\n * @fires open - Dispatched when the menu is opened\n */\nexport default class Menu extends UiList {\n /**\n * Whether the menu is currently open\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor open = false\n\n /**\n * Whether the menu is disabled\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor disabled = false\n\n /**\n * Whether to select menu items when they are activated.\n * When true, clicking or pressing Enter/Space on a menu item will mark it as selected.\n * When false (default), menu items will not be marked as selected when activated.\n *\n * Note, this is different than `selectActive` as this property controls the class names\n * set on the menu item.\n * @attribute\n */\n @property({ type: Boolean }) accessor selectOnActivate = false\n\n /**\n * Currently active sub-menu\n */\n @state() accessor activeSubMenu: UiSubMenu | null = null\n\n constructor() {\n super()\n this.selector = 'ui-menu-item'\n this.ariaExpanded = 'false'\n this.addEventListener('beforetoggle', this.handleBeforeToggle.bind(this))\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.setAttribute('role', 'menu')\n this.setAttribute('tabindex', '-1')\n if (!this.hasAttribute('popover')) {\n this.setAttribute('popover', 'auto')\n }\n if (!this.id) {\n this.id = nanoid()\n }\n }\n\n protected override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties)\n\n if (changedProperties.has('disabled')) {\n setDisabled(this, this.disabled)\n }\n }\n\n override togglePopover(force?: boolean): boolean {\n this.open = !this.open\n this.ariaExpanded = String(this.open)\n this.tabIndex = this.open ? 0 : -1\n const result = super.togglePopover(force)\n if (this.open) {\n this.positionMenu()\n this.focus()\n }\n return result\n }\n\n protected queryMenuItems(): UiMenuItem[] {\n const slot = this.shadowRoot?.querySelector('slot')\n if (!slot) return []\n const { selector } = this\n return Array.from(slot.assignedElements({ flatten: true })).filter((el) => el.matches(selector)) as UiMenuItem[]\n }\n\n show(): void {\n this.showPopover()\n }\n\n hide(): void {\n this.hidePopover()\n }\n\n /**\n * Shows the menu\n */\n override showPopover(): void {\n this.tabIndex = 0 // Make menu focusable\n this.ariaExpanded = 'true'\n super.showPopover()\n this.open = true\n this.positionMenu()\n this.focus()\n this.dispatchEvent(new CustomEvent('open', { bubbles: false, composed: true }))\n }\n\n /**\n * Hides the menu\n */\n override hidePopover(): void {\n this.tabIndex = -1\n this.ariaExpanded = 'false'\n super.hidePopover()\n this.open = false\n this.closeSubMenu()\n this.dispatchEvent(new CustomEvent('close', { bubbles: false, composed: true }))\n }\n\n positionMenu(): void {\n // Let CSS anchor positioning handle the positioning automatically\n // Only intervene if we need to set max-height for overflow cases\n const box = this.getBoundingClientRect()\n\n // Reset any previous manual positioning to let CSS anchor positioning work\n this.style.removeProperty('position-area')\n this.style.removeProperty('max-height')\n this.style.removeProperty('max-width')\n\n // Check if the menu content is being clipped\n const isVerticallyClipped = this.scrollHeight > this.clientHeight\n const isHorizontallyClipped = this.scrollWidth > this.clientWidth\n\n // Get the actual bottom and right edges of the menu\n const menuBottom = box.top + box.height\n const menuRight = box.left + box.width\n\n // Detect if menu is positioned above or below the anchor\n // by checking if the menu is in the upper or lower half of the viewport\n const viewportMiddle = innerHeight / 2\n const isMenuInUpperHalf = box.top < viewportMiddle\n\n // Add CSS class to control animation direction\n if (isMenuInUpperHalf) {\n this.classList.add('menu-positioned-above')\n this.classList.remove('menu-positioned-below')\n } else {\n this.classList.add('menu-positioned-below')\n this.classList.remove('menu-positioned-above')\n }\n\n // Only set max-height if the menu would overflow the viewport OR is already clipped\n if (menuBottom > innerHeight || isVerticallyClipped) {\n let availableHeight: number\n\n if (isMenuInUpperHalf) {\n // Menu is positioned below the anchor - available space is from top to bottom of viewport\n availableHeight = innerHeight - box.top\n } else {\n // Menu is positioned above the anchor - available space is from top of viewport to bottom of menu\n availableHeight = box.top + box.height\n }\n\n this.style.maxHeight = `${Math.max(200, availableHeight - 20)}px`\n }\n\n // Only set max-width if the menu would overflow the viewport OR is already clipped\n if (menuRight > innerWidth || isHorizontallyClipped) {\n const availableWidth = innerWidth - box.left\n if (availableWidth < 200) {\n this.style.maxWidth = `${Math.max(180, availableWidth - 20)}px`\n }\n }\n }\n\n /**\n * Handles beforetoggle event from popover\n */\n protected handleBeforeToggle(e: Event): void {\n const toggleEvent = e as ToggleEvent\n if (toggleEvent.newState === 'closed') {\n this.open = false\n this.closeSubMenu()\n }\n }\n\n /**\n * Handles keyboard navigation for the menu\n */\n override handleKeydown(e: KeyboardEvent): void {\n if (!this.open || e.defaultPrevented) return\n\n switch (e.key) {\n case 'Escape':\n e.preventDefault()\n this.hide()\n break\n case 'ArrowRight':\n e.preventDefault()\n this.openSubMenu()\n break\n case 'ArrowLeft':\n e.preventDefault()\n this.closeSubMenu()\n break\n default:\n // Let the parent UiList handle other keys\n super.handleKeydown(e)\n }\n }\n\n @bound\n handleSubMenuSelect(e: CustomEvent): void {\n super.notifySelect(e.detail.item, e.detail.index)\n }\n\n /**\n * Opens the sub-menu for the currently active item\n */\n protected openSubMenu(): void {\n const activeItem = this.activeListItem as UiMenuItem\n if (activeItem?.hasSubMenu) {\n activeItem.openSubMenu()\n }\n }\n\n /**\n * Closes the currently open sub-menu\n */\n closeSubMenu(): void {\n if (this.activeSubMenu) {\n this.activeSubMenu.removeEventListener('select', this.handleSubMenuSelect as EventListener)\n this.activeSubMenu.hide()\n this.activeSubMenu = null\n }\n }\n\n /**\n * Sets the active sub-menu\n */\n setActiveSubMenu(subMenu: UiSubMenu | null): void {\n this.activeSubMenu = subMenu\n subMenu?.addEventListener('select', this.handleSubMenuSelect as EventListener)\n }\n\n override notifySelect(item: UiListItem & { selected?: boolean }, index?: number): boolean {\n // Only handle selection if selectOnActivate is enabled\n if (this.selectOnActivate) {\n this.clearSelection()\n item.selected = true\n }\n this.hide()\n return super.notifySelect(item, index)\n }\n\n /**\n * Clears selection from all menu items\n */\n protected clearSelection(): void {\n const items = this.queryMenuItems()\n items.forEach((menuItem) => {\n menuItem.selected = false\n })\n }\n\n /**\n * Gets the currently selected menu item\n */\n get selectedItem(): UiMenuItem | null {\n const items = this.queryMenuItems()\n return items.find((item) => item.selected) || null\n }\n\n /**\n * Sets the selected menu item\n */\n setSelectedItem(item: UiMenuItem | null): void {\n this.clearSelection()\n if (item) {\n item.selected = true\n }\n }\n\n /**\n * Handles sub-menu opening\n */\n protected handleSubMenuOpen(e: CustomEvent): void {\n const subMenu = e.detail.subMenu\n this.setActiveSubMenu(subMenu)\n }\n\n /**\n * Handles slot changes to update menu items\n */\n protected handleSlotChange(): void {\n // Update the items list when slot content changes\n this.updateItems()\n }\n\n override render(): TemplateResult {\n const classes = classMap({\n 'menu-container': true,\n })\n\n return html`\n <div class=${classes}>\n <slot @slotchange=${this.handleSlotChange}></slot>\n </div>\n `\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Menu.js","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, PropertyValues, TemplateResult } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { nanoid } from 'nanoid'\nimport UiList from '../../list/internals/List.js'\nimport UiMenuItem from './MenuItem.js'\nimport UiSubMenu from './SubMenu.js'\nimport { setDisabled } from '../../../lib/disabled.js'\nimport UiListItem from '../../list/internals/ListItem.js'\nimport { bound } from '../../../decorators/bound.js'\n\n/**\n * Material Design 3 Menu component with sub-menu support.\n * Uses Popover API and Anchor Positioning API for modern positioning.\n *\n * @fires select - Dispatched when a menu item is selected\n * @fires close - Dispatched when the menu is closed\n * @fires open - Dispatched when the menu is opened\n */\nexport default class Menu extends UiList {\n /**\n * Whether the menu is currently open\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor open = false\n\n /**\n * Whether the menu is disabled\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor disabled = false\n\n /**\n * Whether to select menu items when they are activated.\n * When true, clicking or pressing Enter/Space on a menu item will mark it as selected.\n * When false (default), menu items will not be marked as selected when activated.\n *\n * Note, this is different than `selectActive` as this property controls the class names\n * set on the menu item.\n * @attribute\n */\n @property({ type: Boolean }) accessor selectOnActivate = false\n\n /**\n * Currently active sub-menu\n */\n @state() accessor activeSubMenu: UiSubMenu | null = null\n\n constructor() {\n super()\n this.selector = 'ui-menu-item'\n this.ariaExpanded = 'false'\n this.addEventListener('beforetoggle', this.handleBeforeToggle.bind(this))\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.setAttribute('role', 'menu')\n this.setAttribute('tabindex', '-1')\n if (!this.hasAttribute('popover')) {\n this.setAttribute('popover', 'auto')\n }\n if (!this.id) {\n this.id = nanoid()\n }\n }\n\n protected override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties)\n\n if (changedProperties.has('disabled')) {\n setDisabled(this, this.disabled)\n }\n }\n\n override togglePopover(force?: boolean): boolean {\n if (!this.open && !this.disabled) {\n this.positionMenu()\n }\n this.open = !this.open\n this.ariaExpanded = String(this.open)\n this.tabIndex = this.open ? 0 : -1\n const result = super.togglePopover(force)\n if (this.open) {\n this.focus()\n }\n return result\n }\n\n protected queryMenuItems(): UiMenuItem[] {\n const slot = this.shadowRoot?.querySelector('slot')\n if (!slot) return []\n const { selector } = this\n return Array.from(slot.assignedElements({ flatten: true })).filter((el) => el.matches(selector)) as UiMenuItem[]\n }\n\n show(): void {\n this.showPopover()\n }\n\n hide(): void {\n this.hidePopover()\n }\n\n /**\n * Shows the menu\n */\n override showPopover(): void {\n this.tabIndex = 0 // Make menu focusable\n this.ariaExpanded = 'true'\n this.positionMenu()\n super.showPopover()\n this.open = true\n this.focus()\n this.dispatchEvent(new CustomEvent('open', { bubbles: false, composed: true }))\n }\n\n /**\n * Hides the menu\n */\n override hidePopover(): void {\n this.tabIndex = -1\n this.ariaExpanded = 'false'\n super.hidePopover()\n this.open = false\n this.closeSubMenu()\n this.dispatchEvent(new CustomEvent('close', { bubbles: false, composed: true }))\n }\n\n positionMenu(): void {\n // for the frame, make the element visible (without animations)\n // to take measurements correctly.\n this.classList.add('measurements')\n\n // Reset any previous manual positioning to let CSS anchor positioning work\n this.style.removeProperty('position-area')\n this.style.removeProperty('max-height')\n this.style.removeProperty('max-width')\n\n // Let CSS anchor positioning handle the positioning automatically\n // Only intervene if we need to set max-height for overflow cases\n const box = this.getBoundingClientRect()\n this.classList.remove('measurements')\n\n // Check if the menu content is being clipped\n const isVerticallyClipped = this.scrollHeight > this.clientHeight\n const isHorizontallyClipped = this.scrollWidth > this.clientWidth\n\n // Get the actual bottom and right edges of the menu\n const menuBottom = box.top + box.height\n const menuRight = box.left + box.width\n\n // Detect if menu is positioned above or below the anchor\n // by checking if the menu is in the upper or lower half of the viewport\n const viewportMiddle = innerHeight / 2\n const isMenuInUpperHalf = box.top < viewportMiddle\n\n // console.log(`Menu positioned at: top=${box.top}, left=${box.left}, bottom=${menuBottom}, right=${menuRight}`)\n // console.log(\n // eslint-disable-next-line max-len\n // `Menu is in upper half: ${isMenuInUpperHalf}, Vertically clipped: ${isVerticallyClipped}, Horizontally clipped: ${isHorizontallyClipped}`\n // )\n // Add CSS class to control animation direction\n if (isMenuInUpperHalf) {\n this.classList.add('menu-positioned-above')\n this.classList.remove('menu-positioned-below')\n } else {\n this.classList.add('menu-positioned-below')\n this.classList.remove('menu-positioned-above')\n }\n // Only set max-height if the menu would overflow the viewport OR is already clipped\n if (menuBottom > innerHeight || isVerticallyClipped) {\n let availableHeight: number\n\n if (isMenuInUpperHalf) {\n // Menu is positioned below the anchor - available space is from top to bottom of viewport\n availableHeight = innerHeight - box.top\n } else {\n // Menu is positioned above the anchor - available space is from top of viewport to bottom of menu\n availableHeight = box.top + box.height\n }\n\n this.style.maxHeight = `${Math.max(200, availableHeight - 20)}px`\n }\n\n // Only set max-width if the menu would overflow the viewport OR is already clipped\n if (menuRight > innerWidth || isHorizontallyClipped) {\n const availableWidth = innerWidth - box.left\n if (availableWidth < 200) {\n this.style.maxWidth = `${Math.max(180, availableWidth - 20)}px`\n }\n }\n }\n\n /**\n * Handles beforetoggle event from popover\n */\n protected handleBeforeToggle(e: Event): void {\n const toggleEvent = e as ToggleEvent\n if (toggleEvent.newState === 'closed') {\n this.open = false\n this.closeSubMenu()\n }\n }\n\n /**\n * Handles keyboard navigation for the menu\n */\n override handleKeydown(e: KeyboardEvent): void {\n if (!this.open || e.defaultPrevented) return\n\n switch (e.key) {\n case 'Escape':\n e.preventDefault()\n this.hide()\n break\n case 'ArrowRight':\n e.preventDefault()\n this.openSubMenu()\n break\n case 'ArrowLeft':\n e.preventDefault()\n this.closeSubMenu()\n break\n default:\n // Let the parent UiList handle other keys\n super.handleKeydown(e)\n }\n }\n\n @bound\n handleSubMenuSelect(e: CustomEvent): void {\n super.notifySelect(e.detail.item, e.detail.index)\n }\n\n /**\n * Opens the sub-menu for the currently active item\n */\n protected openSubMenu(): void {\n const activeItem = this.activeListItem as UiMenuItem\n if (activeItem?.hasSubMenu) {\n activeItem.openSubMenu()\n }\n }\n\n /**\n * Closes the currently open sub-menu\n */\n closeSubMenu(): void {\n if (this.activeSubMenu) {\n this.activeSubMenu.removeEventListener('select', this.handleSubMenuSelect as EventListener)\n this.activeSubMenu.hide()\n this.activeSubMenu = null\n }\n }\n\n /**\n * Sets the active sub-menu\n */\n setActiveSubMenu(subMenu: UiSubMenu | null): void {\n this.activeSubMenu = subMenu\n subMenu?.addEventListener('select', this.handleSubMenuSelect as EventListener)\n }\n\n override notifySelect(item: UiListItem & { selected?: boolean }, index?: number): boolean {\n // Only handle selection if selectOnActivate is enabled\n if (this.selectOnActivate) {\n this.clearSelection()\n item.selected = true\n }\n this.hide()\n return super.notifySelect(item, index)\n }\n\n /**\n * Clears selection from all menu items\n */\n protected clearSelection(): void {\n const items = this.queryMenuItems()\n items.forEach((menuItem) => {\n menuItem.selected = false\n })\n }\n\n /**\n * Gets the currently selected menu item\n */\n get selectedItem(): UiMenuItem | null {\n const items = this.queryMenuItems()\n return items.find((item) => item.selected) || null\n }\n\n /**\n * Sets the selected menu item\n */\n setSelectedItem(item: UiMenuItem | null): void {\n this.clearSelection()\n if (item) {\n item.selected = true\n }\n }\n\n /**\n * Handles sub-menu opening\n */\n protected handleSubMenuOpen(e: CustomEvent): void {\n const subMenu = e.detail.subMenu\n this.setActiveSubMenu(subMenu)\n }\n\n /**\n * Handles slot changes to update menu items\n */\n protected handleSlotChange(): void {\n // Update the items list when slot content changes\n this.updateItems()\n }\n\n override render(): TemplateResult {\n const classes = classMap({\n 'menu-container': true,\n })\n\n return html`\n <div class=${classes}>\n <slot @slotchange=${this.handleSlotChange}></slot>\n </div>\n `\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.styles.d.ts","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.styles.ts"],"names":[],"mappings":";AAEA,
|
|
1
|
+
{"version":3,"file":"Menu.styles.d.ts","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.styles.ts"],"names":[],"mappings":";AAEA,wBA2QC"}
|
|
@@ -8,7 +8,6 @@ export default css `
|
|
|
8
8
|
margin: 0;
|
|
9
9
|
padding: 0;
|
|
10
10
|
border: none;
|
|
11
|
-
overflow: hidden;
|
|
12
11
|
/* in most cases the max-height won't matter as this assumes the whole screen to be available, which is rarely the truth. */
|
|
13
12
|
max-height: 90vh;
|
|
14
13
|
overflow: auto;
|
|
@@ -26,6 +25,11 @@ export default css `
|
|
|
26
25
|
position-area: top span-left;
|
|
27
26
|
}
|
|
28
27
|
|
|
28
|
+
/* Special class set on the element to render the menu to take measurements */
|
|
29
|
+
:host(.measurements) {
|
|
30
|
+
display: block;
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
:host(:popover-open) {
|
|
30
34
|
display: block;
|
|
31
35
|
background-color: var(--md-sys-color-surface-container);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.styles.js","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,eAAe,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"Menu.styles.js","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,eAAe,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2QjB,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport default css`\n :host {\n display: none;\n position-area: bottom span-right;\n position-try: --menu-fallback-bottom-left, --menu-fallback-top-right, --menu-fallback-top-left, flip-block;\n position: fixed;\n margin: 0;\n padding: 0;\n border: none;\n /* in most cases the max-height won't matter as this assumes the whole screen to be available, which is rarely the truth. */\n max-height: 90vh;\n overflow: auto;\n }\n\n @position-try --menu-fallback-bottom-left {\n position-area: bottom span-left;\n }\n\n @position-try --menu-fallback-top-right {\n position-area: top span-right;\n }\n\n @position-try --menu-fallback-top-left {\n position-area: top span-left;\n }\n\n /* Special class set on the element to render the menu to take measurements */\n :host(.measurements) {\n display: block;\n }\n\n :host(:popover-open) {\n display: block;\n background-color: var(--md-sys-color-surface-container);\n border-radius: var(--md-sys-shape-corner-extra-small);\n box-shadow: var(--md-sys-elevation-3);\n animation: menu-scale-in 0.15s cubic-bezier(0.4, 0, 0.2, 1) forwards;\n }\n\n /* Scale animation for menus positioned below the anchor */\n @keyframes menu-scale-in {\n 0% {\n transform: scaleY(0);\n transform-origin: top center;\n opacity: 0;\n }\n 100% {\n transform: scaleY(1);\n transform-origin: top center;\n opacity: 1;\n }\n }\n\n /* Scale animation for menus positioned above the anchor */\n @keyframes menu-scale-in-up {\n 0% {\n transform: scaleY(0);\n transform-origin: bottom center;\n opacity: 0;\n }\n 100% {\n transform: scaleY(1);\n transform-origin: bottom center;\n opacity: 1;\n }\n }\n\n /* Position-specific animations using JavaScript-detected classes */\n :host(.menu-positioned-above):popover-open {\n animation: menu-scale-in-up 0.15s var(--md-sys-motion-easing-standard-accelerate) forwards;\n }\n\n :host(.menu-positioned-below):popover-open {\n animation: menu-scale-in 0.15s var(--md-sys-motion-easing-standard-accelerate) forwards;\n }\n\n .menu-container {\n min-width: 200px;\n padding: 8px 0;\n outline: none;\n }\n\n .menu-divider {\n height: 1px;\n background-color: var(--md-sys-color-outline-variant);\n margin: 8px 0;\n }\n\n /* Menu Item Styles */\n .menu-item {\n position: relative;\n display: flex;\n align-items: center;\n min-height: 48px;\n padding: 0 16px;\n cursor: pointer;\n outline: none;\n transition: background-color 0.2s ease;\n }\n\n .menu-item:hover {\n background-color: var(--md-sys-color-surface-variant);\n }\n\n .menu-item:focus {\n background-color: var(--md-sys-color-surface-variant);\n }\n\n .menu-item[disabled] {\n opacity: 0.38;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .menu-item-content {\n display: flex;\n align-items: center;\n width: 100%;\n gap: 12px;\n }\n\n .menu-item-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n color: var(--md-sys-color-on-surface);\n font-size: 20px;\n }\n\n .menu-item-label {\n flex: 1;\n color: var(--md-sys-color-on-surface);\n font-family: var(--md-sys-typescale-label-large-font-family-name);\n font-size: var(--md-sys-typescale-label-large-font-size);\n font-weight: var(--md-sys-typescale-label-large-font-weight);\n line-height: var(--md-sys-typescale-label-large-line-height);\n letter-spacing: var(--md-sys-typescale-label-large-letter-spacing);\n }\n\n .menu-item-arrow {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n color: var(--md-sys-color-on-surface);\n font-size: 18px;\n font-weight: 500;\n }\n\n .menu-item-with-submenu {\n position: relative;\n }\n\n .menu-item-with-submenu:hover .menu-item-arrow {\n color: var(--md-sys-color-primary);\n }\n\n /* Sub-menu Styles */\n .submenu-container {\n min-width: 200px;\n max-width: 320px;\n background-color: var(--md-sys-color-surface);\n border-radius: var(--md-sys-shape-corner-extra-small);\n box-shadow: var(--md-sys-elevation-level3);\n padding: 8px 0;\n }\n\n /* Submenu positioning with Anchor API */\n ui-sub-menu {\n display: none;\n }\n\n ui-sub-menu:popover-open {\n display: block;\n background-color: var(--md-sys-color-surface);\n border-radius: var(--md-sys-shape-corner-extra-small);\n box-shadow: var(--md-sys-elevation-level3);\n min-width: 200px;\n max-width: 320px;\n padding: 8px 0;\n z-index: 1000;\n animation: submenu-scale-in 0.12s cubic-bezier(0.4, 0, 0.2, 1) forwards;\n }\n\n /* Submenu scale animation */\n @keyframes submenu-scale-in {\n 0% {\n transform: scaleY(0) scaleX(0.8);\n transform-origin: left top;\n opacity: 0;\n }\n 100% {\n transform: scaleY(1) scaleX(1);\n transform-origin: left top;\n opacity: 1;\n }\n }\n\n /* Fallback positioning for browsers without anchor positioning */\n @supports not (anchor-name: --test) {\n ui-sub-menu:popover-open {\n position: fixed;\n transform: translateX(200px);\n }\n }\n\n /* Focus Ring */\n md-focus-ring {\n --md-focus-ring-color: var(--md-sys-color-primary);\n --md-focus-ring-width: 2px;\n }\n\n /* Ripple Effect */\n ui-ripple {\n --md-ripple-color: var(--md-sys-color-primary);\n --md-ripple-opacity: 0.12;\n }\n\n /* Responsive Design */\n @media (max-width: 600px) {\n .menu-container {\n min-width: 180px;\n max-width: 280px;\n }\n\n .submenu-container {\n min-width: 180px;\n max-width: 280px;\n }\n }\n\n /* High Contrast Mode */\n @media (prefers-contrast: high) {\n .menu-container {\n border: 1px solid var(--md-sys-color-outline);\n }\n\n .submenu-container {\n border: 1px solid var(--md-sys-color-outline);\n }\n\n .menu-divider {\n background-color: var(--md-sys-color-outline);\n }\n }\n\n /* Reduced Motion */\n @media (prefers-reduced-motion: reduce) {\n .menu-item {\n transition: none;\n }\n\n :host(:popover-open) {\n animation: none;\n opacity: 1;\n transform: none;\n }\n\n ui-sub-menu:popover-open {\n animation: none;\n opacity: 1;\n transform: none;\n }\n }\n`\n"]}
|
|
@@ -21,6 +21,10 @@ export interface UiSelectChangeEvent {
|
|
|
21
21
|
export default class UiSelect extends UiElement {
|
|
22
22
|
#private;
|
|
23
23
|
static readonly formAssociated = true;
|
|
24
|
+
/**
|
|
25
|
+
* Timeout duration for type-ahead reset (in milliseconds)
|
|
26
|
+
*/
|
|
27
|
+
static readonly TYPE_AHEAD_TIMEOUT = 1000;
|
|
24
28
|
/**
|
|
25
29
|
* The currently selected value. Corresponds to the `value` attribute of the selected `ui-option`.
|
|
26
30
|
* When set programmatically, it will update the selected option if a matching option exists.
|
|
@@ -207,6 +211,7 @@ export default class UiSelect extends UiElement {
|
|
|
207
211
|
checkValidity(): boolean;
|
|
208
212
|
constructor();
|
|
209
213
|
connectedCallback(): void;
|
|
214
|
+
disconnectedCallback(): void;
|
|
210
215
|
/**
|
|
211
216
|
* Resets the select to its initial state. Called automatically when the parent
|
|
212
217
|
* form is reset. Part of the form-associated custom element API.
|
|
@@ -282,6 +287,22 @@ export default class UiSelect extends UiElement {
|
|
|
282
287
|
* Checks if an option is selectable (not disabled and not hidden)
|
|
283
288
|
*/
|
|
284
289
|
protected isOptionSelectable(option: UiOption): boolean;
|
|
290
|
+
/**
|
|
291
|
+
* Handles type-ahead functionality for keyboard navigation
|
|
292
|
+
*/
|
|
293
|
+
protected handleTypeAhead(char: string): void;
|
|
294
|
+
/**
|
|
295
|
+
* Finds an option that matches the type-ahead search string
|
|
296
|
+
*/
|
|
297
|
+
protected findOptionByTypeAhead(searchString: string): UiOption | null;
|
|
298
|
+
/**
|
|
299
|
+
* Gets the display text for an option (either textContent or renderValue)
|
|
300
|
+
*/
|
|
301
|
+
protected getOptionDisplayText(option: UiOption): string;
|
|
302
|
+
/**
|
|
303
|
+
* Selects an option and updates the component state
|
|
304
|
+
*/
|
|
305
|
+
protected selectOption(option: UiOption): void;
|
|
285
306
|
handleSelect(e: CustomEvent<{
|
|
286
307
|
item: UiOption;
|
|
287
308
|
}>): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../../../src/md/select/internals/Select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAK1D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAO,KAAK,QAAQ,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAG1D,OAAO,4CAA4C,CAAA;AACnD,OAAO,uBAAuB,CAAA;AAC9B,OAAO,wBAAwB,CAAA;AAC/B,OAAO,mCAAmC,CAAA;AAE1C,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,SAAS;;IAC7C,MAAM,CAAC,QAAQ,CAAC,cAAc,QAAO;
|
|
1
|
+
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../../../src/md/select/internals/Select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAK1D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAO,KAAK,QAAQ,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAG1D,OAAO,4CAA4C,CAAA;AACnD,OAAO,uBAAuB,CAAA;AAC9B,OAAO,wBAAwB,CAAA;AAC/B,OAAO,mCAAmC,CAAA;AAE1C,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,SAAS;;IAC7C,MAAM,CAAC,QAAQ,CAAC,cAAc,QAAO;IAmBrC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,QAAO;IAEzC;;;;;;;;;;;;OAYG;IACH,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAED,IACI,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAKrC;IAED;;;;;;;;;;;OAWG;IACyB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IAE7D;;;;;;;;;;;OAWG;IACyB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IAE9D;;;;;;;;;;;OAWG;IAC0B,QAAQ,CAAC,QAAQ,UAAQ;IAEtD;;;;;;;;;;;OAWG;IAC0B,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;IAElE;;;;;;;;;;;OAWG;IACyB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IAEpE;;OAEG;IACyB,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;IAEvE;;;;;;;;;;;;OAYG;IACyC,QAAQ,CAAC,QAAQ,UAAQ;IAErE;;;;;;;;;;;;;OAaG;IACyC,QAAQ,CAAC,IAAI,UAAQ;IAExD,QAAQ,CAAC,cAAc,EAAE,QAAQ,GAAG,IAAI,CAAO;IAExC,QAAQ,CAAC,IAAI,EAAG,aAAa,CAAA;IAE7C;;;;;;;;;;;;;OAaG;IACH,IAAI,YAAY,IAAI,QAAQ,GAAG,IAAI,CAElC;IAED;;;;;;;;;;OAUG;IACH,IAAI,WAAW,IAAI,MAAM,CAGxB;IAED;;;;;OAKG;IACH,IAAI,IAAI,IAAI,eAAe,GAAG,IAAI,CAEjC;IAED;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,aAAa,CAE5B;IAED;;;;;OAKG;IACH,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED;;;;;OAKG;IACH,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED;;;;;;;;;;;;OAYG;IACH,aAAa,IAAI,OAAO;;IAWf,iBAAiB,IAAI,IAAI;IAazB,oBAAoB,IAAI,IAAI;IASrC;;;;;;;;;OASG;IACH,iBAAiB,IAAI,IAAI;IAIzB;;;;;OAKG;IACH,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIpD;;;;;;;;;;;;OAYG;IACH,QAAQ,IAAI,IAAI;cAYG,UAAU,CAAC,iBAAiB,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI;cAsBzD,YAAY,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI;IAYzD,SAAS,CAAC,gBAAgB,IAAI,IAAI;IAelC,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI;IA2E/C,SAAS,CAAC,UAAU,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI;IAehC,WAAW,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;cAYpB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BjD;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAQzB;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAQ7B;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAO1B;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAOzB;;OAEG;IACH,wBAAwB,IAAI,QAAQ,GAAG,IAAI;IAU3C;;OAEG;IACH,uBAAuB,IAAI,QAAQ,GAAG,IAAI;IAU1C;;OAEG;IACH,SAAS,CAAC,uBAAuB,CAAC,aAAa,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI;IAoB3E;;OAEG;IACH,SAAS,CAAC,2BAA2B,CAAC,aAAa,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI;IAoB/E;;OAEG;IACH,SAAS,CAAC,kBAAkB,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO;IAavD;;OAEG;IACH,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA4B7C;;OAEG;IACH,SAAS,CAAC,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAmBtE;;OAEG;IACH,SAAS,CAAC,oBAAoB,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM;IAKxD;;OAEG;IACH,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAmB9C,YAAY,CAAC,CAAC,EAAE,WAAW,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,GAAG,IAAI;IAsBtD,eAAe,IAAI,IAAI;IAKvB,gBAAgB,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI;IAMtC,SAAS,CAAC,WAAW,IAAI,cAAc;IAyBvC,SAAS,CAAC,UAAU,IAAI,cAAc;cAmBtB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IASjD,SAAS,CAAC,eAAe,IAAI,cAAc;IAIlC,MAAM,IAAI,cAAc;CASlC"}
|
|
@@ -78,6 +78,18 @@ let UiSelect = (() => {
|
|
|
78
78
|
* the side effects.
|
|
79
79
|
*/
|
|
80
80
|
#value;
|
|
81
|
+
/**
|
|
82
|
+
* Type-ahead search string accumulated from user typing
|
|
83
|
+
*/
|
|
84
|
+
#typeAheadString = '';
|
|
85
|
+
/**
|
|
86
|
+
* Timer for resetting the type-ahead search string
|
|
87
|
+
*/
|
|
88
|
+
#typeAheadTimer = null;
|
|
89
|
+
/**
|
|
90
|
+
* Timeout duration for type-ahead reset (in milliseconds)
|
|
91
|
+
*/
|
|
92
|
+
static TYPE_AHEAD_TIMEOUT = 1000;
|
|
81
93
|
/**
|
|
82
94
|
* The currently selected value. Corresponds to the `value` attribute of the selected `ui-option`.
|
|
83
95
|
* When set programmatically, it will update the selected option if a matching option exists.
|
|
@@ -352,6 +364,14 @@ let UiSelect = (() => {
|
|
|
352
364
|
this.id = `select-${nanoid(6)}`;
|
|
353
365
|
}
|
|
354
366
|
}
|
|
367
|
+
disconnectedCallback() {
|
|
368
|
+
super.disconnectedCallback();
|
|
369
|
+
// Clean up the type-ahead timer
|
|
370
|
+
if (this.#typeAheadTimer) {
|
|
371
|
+
clearTimeout(this.#typeAheadTimer);
|
|
372
|
+
this.#typeAheadTimer = null;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
355
375
|
/**
|
|
356
376
|
* Resets the select to its initial state. Called automatically when the parent
|
|
357
377
|
* form is reset. Part of the form-associated custom element API.
|
|
@@ -451,6 +471,11 @@ let UiSelect = (() => {
|
|
|
451
471
|
handleKeydown(e) {
|
|
452
472
|
if (this.disabled || e.defaultPrevented)
|
|
453
473
|
return;
|
|
474
|
+
// Handle type-ahead for printable characters
|
|
475
|
+
if (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
|
476
|
+
this.handleTypeAhead(e.key.toLowerCase());
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
454
479
|
if (this.open) {
|
|
455
480
|
switch (e.key) {
|
|
456
481
|
case 'Tab': {
|
|
@@ -553,11 +578,13 @@ let UiSelect = (() => {
|
|
|
553
578
|
// Focus on the selected option or first selectable option when menu opens
|
|
554
579
|
if (this.selectedOption && this.isOptionSelectable(this.selectedOption)) {
|
|
555
580
|
this.selectedOption.focus();
|
|
581
|
+
this.selectedOption.scrollIntoView({ behavior: 'instant', block: 'nearest', inline: 'nearest' });
|
|
556
582
|
}
|
|
557
583
|
else {
|
|
558
584
|
const firstSelectableOption = this.getFirstSelectableOption();
|
|
559
585
|
if (firstSelectableOption) {
|
|
560
586
|
firstSelectableOption.focus();
|
|
587
|
+
firstSelectableOption.scrollIntoView({ behavior: 'instant', block: 'nearest', inline: 'nearest' });
|
|
561
588
|
}
|
|
562
589
|
}
|
|
563
590
|
this.dispatchEvent(new CustomEvent('open', { bubbles: false, composed: true }));
|
|
@@ -684,6 +711,77 @@ let UiSelect = (() => {
|
|
|
684
711
|
}
|
|
685
712
|
return true;
|
|
686
713
|
}
|
|
714
|
+
/**
|
|
715
|
+
* Handles type-ahead functionality for keyboard navigation
|
|
716
|
+
*/
|
|
717
|
+
handleTypeAhead(char) {
|
|
718
|
+
// Clear the existing timer
|
|
719
|
+
if (this.#typeAheadTimer) {
|
|
720
|
+
clearTimeout(this.#typeAheadTimer);
|
|
721
|
+
}
|
|
722
|
+
// Add the character to the search string
|
|
723
|
+
this.#typeAheadString += char;
|
|
724
|
+
// Find the matching option
|
|
725
|
+
const matchingOption = this.findOptionByTypeAhead(this.#typeAheadString);
|
|
726
|
+
if (matchingOption) {
|
|
727
|
+
if (this.open) {
|
|
728
|
+
// If menu is open, focus the matching option
|
|
729
|
+
matchingOption.focus();
|
|
730
|
+
}
|
|
731
|
+
else {
|
|
732
|
+
// If menu is closed, select the matching option
|
|
733
|
+
this.selectOption(matchingOption);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
// Set a timer to reset the search string
|
|
737
|
+
this.#typeAheadTimer = window.setTimeout(() => {
|
|
738
|
+
this.#typeAheadString = '';
|
|
739
|
+
this.#typeAheadTimer = null;
|
|
740
|
+
}, UiSelect.TYPE_AHEAD_TIMEOUT);
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Finds an option that matches the type-ahead search string
|
|
744
|
+
*/
|
|
745
|
+
findOptionByTypeAhead(searchString) {
|
|
746
|
+
const options = this.querySelectorAll('ui-option');
|
|
747
|
+
for (const option of options) {
|
|
748
|
+
if (!this.isOptionSelectable(option)) {
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
// Get the option's text content for comparison
|
|
752
|
+
const optionText = this.getOptionDisplayText(option).toLowerCase();
|
|
753
|
+
if (optionText.startsWith(searchString)) {
|
|
754
|
+
return option;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Gets the display text for an option (either textContent or renderValue)
|
|
761
|
+
*/
|
|
762
|
+
getOptionDisplayText(option) {
|
|
763
|
+
// Use renderValue if available, otherwise fall back to textContent
|
|
764
|
+
return option.renderValue || option.textContent?.trim() || '';
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Selects an option and updates the component state
|
|
768
|
+
*/
|
|
769
|
+
selectOption(option) {
|
|
770
|
+
if (this.selectedOption && this.selectedOption !== option) {
|
|
771
|
+
this.selectedOption.selected = false;
|
|
772
|
+
}
|
|
773
|
+
option.selected = true;
|
|
774
|
+
this.selectedOption = option;
|
|
775
|
+
this.#value = option.value;
|
|
776
|
+
this.#internals.setFormValue(this.value ?? null);
|
|
777
|
+
// Dispatch change event
|
|
778
|
+
const changeEvent = new CustomEvent('change', {
|
|
779
|
+
detail: { value: this.value, item: option },
|
|
780
|
+
bubbles: false,
|
|
781
|
+
composed: true,
|
|
782
|
+
});
|
|
783
|
+
this.dispatchEvent(changeEvent);
|
|
784
|
+
}
|
|
687
785
|
handleSelect(e) {
|
|
688
786
|
e.stopPropagation();
|
|
689
787
|
const item = e.detail.item;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.js","sourceRoot":"","sources":["../../../../../src/md/select/internals/Select.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, PropertyValues, TemplateResult } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { styleMap } from 'lit/directives/style-map.js'\nimport { setDisabled } from '../../../lib/disabled.js'\nimport { UiElement } from '../../UiElement.js'\nimport type UiOption from './Option.js'\nimport type { UiMenuElement } from '../../menu/ui-menu.js'\nimport { nanoid } from 'nanoid'\n\nimport '../../text-field/ui-outlined-text-field.js'\nimport '../../menu/ui-menu.js'\nimport '../../icons/ui-icon.js'\nimport '../../focus-ring/ui-focus-ring.js'\n\nexport interface UiSelectChangeEvent {\n value: string | undefined\n item: UiOption | null\n}\n\n/**\n * Material Design 3 Select component that behaves like an outlined text field with dropdown.\n *\n * @fires change - Dispatched when the selection changes. The event is non-bubbling and non-cancelable.\n * The `event.detail` object contains the `value` and `item` properties.\n * @fires open - Dispatched when the dropdown opens\n * @fires close - Dispatched when the dropdown closes\n */\nexport default class UiSelect extends UiElement {\n static readonly formAssociated = true\n #internals = this.attachInternals()\n\n /**\n * The value has a private member so that we can set the value without triggering\n * the side effects.\n */\n #value: string | undefined\n\n /**\n * The currently selected value. Corresponds to the `value` attribute of the selected `ui-option`.\n * When set programmatically, it will update the selected option if a matching option exists.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select value=\"apple\">\n * <ui-option value=\"apple\">Apple</ui-option>\n * <ui-option value=\"banana\">Banana</ui-option>\n * </ui-select>\n * ```\n */\n get value(): string | undefined {\n return this.#value\n }\n\n @property({ type: String })\n set value(newValue: string | undefined) {\n const oldValue = this.#value\n if (newValue === oldValue) return\n this.#value = newValue\n this.requestUpdate()\n }\n\n /**\n * The name attribute for form submission. This value will be used as the key\n * when the form is submitted.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select name=\"country\" value=\"us\">\n * <ui-option value=\"us\">United States</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: String }) accessor name: string | undefined\n\n /**\n * The label text displayed in the select field. Provides accessible labeling\n * and is shown as the floating label in the outlined text field.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select label=\"Select a country\">\n * <ui-option value=\"us\">United States</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: String }) accessor label: string | undefined\n\n /**\n * Whether the select is required for form validation. When true, the select\n * must have a value selected for the form to be valid.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select required label=\"Required field\">\n * <ui-option value=\"option1\">Option 1</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: Boolean }) accessor required = false\n\n /**\n * Whether the select is in an invalid state. This is typically set automatically\n * during validation, but can be set manually to indicate validation errors.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select invalid invalidText=\"Please select a valid option\">\n * <ui-option value=\"option1\">Option 1</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: Boolean }) accessor invalid: boolean | undefined\n\n /**\n * The error message to display when the select is invalid. This text is shown\n * below the select field when `invalid` is true.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select invalid invalidText=\"This field is required\">\n * <ui-option value=\"option1\">Option 1</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: String }) accessor invalidText: string | undefined\n\n /**\n * @attribute\n */\n @property({ type: String }) accessor supportingText: string | undefined\n\n /**\n * Whether the select is disabled. When disabled, the select cannot be interacted\n * with and will not receive focus or respond to user input.\n *\n * @default false\n * @attribute\n * @example\n * ```html\n * <ui-select disabled label=\"Disabled select\">\n * <ui-option value=\"option1\">Option 1</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: Boolean, reflect: true }) accessor disabled = false\n\n /**\n * Whether the dropdown menu is currently open. This property reflects the\n * current state of the dropdown and can be set programmatically to open/close it.\n *\n * @default false\n * @example\n * ```javascript\n * // Open the dropdown programmatically\n * selectElement.open = true;\n *\n * // Close the dropdown\n * selectElement.open = false;\n * ```\n */\n @property({ type: Boolean, reflect: true }) accessor open = false\n\n @state() accessor selectedOption: UiOption | null = null\n\n @query('.menu') accessor menu!: UiMenuElement\n\n /**\n * Returns the currently selected option element. This provides access to the\n * full `ui-option` element, not just its value.\n *\n * @readonly\n * @example\n * ```javascript\n * const select = document.querySelector('ui-select');\n * const selectedItem = select.selectedItem;\n * if (selectedItem) {\n * console.log('Selected option:', selectedItem.textContent);\n * }\n * ```\n */\n get selectedItem(): UiOption | null {\n return this.selectedOption\n }\n\n /**\n * Returns the text content that should be displayed in the select field.\n * This is the rendered value of the currently selected option.\n *\n * @readonly\n * @example\n * ```javascript\n * const select = document.querySelector('ui-select');\n * console.log('Display text:', select.renderValue);\n * ```\n */\n get renderValue(): string {\n const item = this.selectedOption\n return item ? item.renderValue : ''\n }\n\n /**\n * Returns the form element that contains this select, if any.\n * Part of the form-associated custom element API.\n *\n * @readonly\n */\n get form(): HTMLFormElement | null {\n return this.#internals.form\n }\n\n /**\n * Returns the validity state of the select element.\n * Part of the form-associated custom element API.\n *\n * @readonly\n */\n get validity(): ValidityState {\n return this.#internals.validity\n }\n\n /**\n * Returns the validation message for the select element.\n * Part of the form-associated custom element API.\n *\n * @readonly\n */\n get validationMessage(): string {\n return this.#internals.validationMessage\n }\n\n /**\n * Returns whether the select element will be validated when the form is submitted.\n * Part of the form-associated custom element API.\n *\n * @readonly\n */\n get willValidate(): boolean {\n return this.#internals.willValidate\n }\n\n /**\n * Checks the validity of the select element and returns true if valid.\n * Part of the form-associated custom element API.\n *\n * @returns {boolean} True if the element is valid, false otherwise\n * @example\n * ```javascript\n * const select = document.querySelector('ui-select');\n * if (!select.checkValidity()) {\n * console.log('Select is invalid:', select.validationMessage);\n * }\n * ```\n */\n checkValidity(): boolean {\n return this.#internals.checkValidity()\n }\n\n constructor() {\n super()\n this.addEventListener('click', this.handleClick.bind(this))\n this.addEventListener('blur', this.handleBlur.bind(this))\n this.addEventListener('keydown', this.handleKeydown.bind(this))\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.setAttribute('role', 'combobox')\n this.setAttribute('aria-haspopup', 'listbox')\n this.setAttribute('aria-controls', 'menu')\n if (!this.disabled) {\n this.setAttribute('tabindex', '0')\n }\n if (!this.id) {\n this.id = `select-${nanoid(6)}`\n }\n }\n\n /**\n * Resets the select to its initial state. Called automatically when the parent\n * form is reset. Part of the form-associated custom element API.\n *\n * @example\n * ```javascript\n * const select = document.querySelector('ui-select');\n * select.formResetCallback(); // Clears the selection\n * ```\n */\n formResetCallback(): void {\n this.value = undefined\n }\n\n /**\n * Restores the select's state from saved form data. Called automatically when\n * the browser restores form state. Part of the form-associated custom element API.\n *\n * @param {string | null} state - The saved state to restore\n */\n formStateRestoreCallback(state: string | null): void {\n this.value = state ?? undefined\n }\n\n /**\n * Validates the select element and updates its validity state. This is called\n * automatically during property changes, but can be called manually to trigger validation.\n *\n * @example\n * ```javascript\n * const select = document.querySelector('ui-select');\n * select.validate();\n * if (select.invalid) {\n * console.log('Validation failed:', select.invalidText);\n * }\n * ```\n */\n validate(): void {\n let message = ''\n if (this.required && !this.value) {\n message = 'Please select an item.'\n this.#internals.setValidity({ valueMissing: true }, message)\n } else {\n this.#internals.setValidity({})\n }\n this.invalid = !this.#internals.validity.valid\n this.invalidText = message\n }\n\n protected override willUpdate(changedProperties: PropertyValues<this>): void {\n super.willUpdate(changedProperties)\n if (changedProperties.has('disabled')) {\n setDisabled(this, this.disabled)\n }\n if (changedProperties.has('open')) {\n this.handleOpenChange()\n }\n if (changedProperties.has('value')) {\n this.setCurrentOption()\n this.#internals.setFormValue(this.value ?? null)\n this.validate()\n }\n if (changedProperties.has('label')) {\n if (this.label) {\n this.setAttribute('aria-label', this.label)\n } else {\n this.removeAttribute('aria-label')\n }\n }\n }\n\n protected override firstUpdated(cp: PropertyValues): void {\n super.firstUpdated(cp)\n this.updateComplete.then(() => {\n this.setCurrentOption()\n this.#internals.setFormValue(this.value ?? null)\n // We need to update here as event with `value` and `selectedOption`\n // already set, the `renderValue` might have incorrect value\n // due to the DOM update.\n this.requestUpdate()\n })\n }\n\n protected setCurrentOption(): void {\n const options = this.querySelectorAll<UiOption>('ui-option')\n if (this.value) {\n this.selectedOption = Array.from(options).find((option) => option.value === this.value) || null\n } else {\n const selected = Array.from(options).find((option) => option.selected)\n if (selected) {\n this.selectedOption = selected\n this.#value = selected.value\n } else {\n this.selectedOption = null\n }\n }\n }\n\n protected handleKeydown(e: KeyboardEvent): void {\n if (this.disabled || e.defaultPrevented) return\n if (this.open) {\n switch (e.key) {\n case 'Tab': {\n // If menu is open and Tab is pressed, close it and allow normal tab navigation\n if (this.open) {\n this.open = false\n }\n break\n }\n case 'Escape': {\n if (this.open) {\n e.preventDefault()\n this.open = false\n this.focus() // Return focus to the select element\n }\n break\n }\n case 'ArrowDown':\n e.preventDefault()\n this.focusNextMenuItem()\n return\n case 'ArrowUp':\n e.preventDefault()\n this.focusPreviousMenuItem()\n return\n case 'Home':\n e.preventDefault()\n this.focusFirstMenuItem()\n return\n case 'End':\n e.preventDefault()\n this.focusLastMenuItem()\n return\n case 'Enter':\n case ' ': {\n const currentItem = this.querySelector<UiOption>(':focus')\n if (currentItem && this.isOptionSelectable(currentItem)) {\n e.preventDefault()\n this.menu.notifySelect(currentItem)\n }\n return\n }\n }\n } else {\n switch (e.key) {\n case 'Enter':\n case ' ': {\n if (!this.open) {\n e.preventDefault()\n this.open = true\n }\n break\n }\n case 'ArrowDown':\n case 'ArrowUp': {\n if (!this.open) {\n e.preventDefault()\n this.open = true\n }\n // If menu is open, let the menu handle arrow keys\n break\n }\n }\n }\n }\n\n protected handleBlur(e: FocusEvent): void {\n if (this.disabled) return\n\n // Check if focus is moving to the menu or one of its children\n const relatedTarget = e.relatedTarget as HTMLElement\n\n if (relatedTarget && this.contains(relatedTarget)) {\n // Focus is moving to the menu, keep it open\n return\n }\n\n // Close the menu when focus leaves the component\n this.open = false\n }\n\n override handleClick(e: Event): void {\n if (this.disabled || e.defaultPrevented) return\n e.preventDefault()\n e.stopPropagation()\n if (this.open && e.target === this) {\n // If the select is already open and clicked again, close it\n this.open = false\n return\n }\n this.open = true\n }\n\n protected async handleOpenChange(): Promise<void> {\n const menu = this.menu\n if (!menu) {\n // The status can be set before the menu is rendered\n return\n }\n this.setAttribute('aria-expanded', String(this.open))\n if (this.open) {\n menu.showPopover()\n // Focus on the selected option or first selectable option when menu opens\n if (this.selectedOption && this.isOptionSelectable(this.selectedOption)) {\n this.selectedOption.focus()\n } else {\n const firstSelectableOption = this.getFirstSelectableOption()\n if (firstSelectableOption) {\n firstSelectableOption.focus()\n }\n }\n this.dispatchEvent(new CustomEvent('open', { bubbles: false, composed: true }))\n } else {\n menu.hidePopover()\n this.dispatchEvent(new CustomEvent('close', { bubbles: false, composed: true }))\n // Return focus to the select element when menu closes\n this.focus()\n }\n }\n\n /**\n * Focus the next menu item in the dropdown, skipping disabled options\n */\n focusNextMenuItem(): void {\n const currentItem = this.querySelector<UiOption>(':focus')\n const nextItem = currentItem ? this.getNextSelectableOption(currentItem) : this.getFirstSelectableOption()\n if (nextItem) {\n nextItem.focus()\n }\n }\n\n /**\n * Focus the previous menu item in the dropdown, skipping disabled options\n */\n focusPreviousMenuItem(): void {\n const currentItem = this.querySelector<UiOption>(':focus')\n const previousItem = currentItem ? this.getPreviousSelectableOption(currentItem) : this.getLastSelectableOption()\n if (previousItem) {\n previousItem.focus()\n }\n }\n\n /**\n * Focus the first menu item in the dropdown, skipping disabled options\n */\n focusFirstMenuItem(): void {\n const firstItem = this.getFirstSelectableOption()\n if (firstItem) {\n firstItem.focus()\n }\n }\n\n /**\n * Focus the last menu item in the dropdown, skipping disabled options\n */\n focusLastMenuItem(): void {\n const lastItem = this.getLastSelectableOption()\n if (lastItem) {\n lastItem.focus()\n }\n }\n\n /**\n * Gets the first selectable (non-disabled) option\n */\n getFirstSelectableOption(): UiOption | null {\n const options = this.querySelectorAll<UiOption>('ui-option')\n for (const option of options) {\n if (this.isOptionSelectable(option)) {\n return option\n }\n }\n return null\n }\n\n /**\n * Gets the last selectable (non-disabled) option\n */\n getLastSelectableOption(): UiOption | null {\n const options = Array.from(this.querySelectorAll<UiOption>('ui-option')).reverse()\n for (const option of options) {\n if (this.isOptionSelectable(option)) {\n return option\n }\n }\n return null\n }\n\n /**\n * Gets the next selectable option after the current one, wrapping around if needed\n */\n protected getNextSelectableOption(currentOption: UiOption): UiOption | null {\n const options = Array.from(this.querySelectorAll<UiOption>('ui-option'))\n const currentIndex = options.indexOf(currentOption)\n\n if (currentIndex === -1) {\n return this.getFirstSelectableOption()\n }\n\n // Start from the next option and wrap around\n for (let i = 1; i < options.length; i++) {\n const nextIndex = (currentIndex + i) % options.length\n const option = options[nextIndex]\n if (this.isOptionSelectable(option)) {\n return option\n }\n }\n\n return currentOption // Return current if no other selectable option found\n }\n\n /**\n * Gets the previous selectable option before the current one, wrapping around if needed\n */\n protected getPreviousSelectableOption(currentOption: UiOption): UiOption | null {\n const options = Array.from(this.querySelectorAll<UiOption>('ui-option'))\n const currentIndex = options.indexOf(currentOption)\n\n if (currentIndex === -1) {\n return this.getLastSelectableOption()\n }\n\n // Start from the previous option and wrap around\n for (let i = 1; i < options.length; i++) {\n const prevIndex = (currentIndex - i + options.length) % options.length\n const option = options[prevIndex]\n if (this.isOptionSelectable(option)) {\n return option\n }\n }\n\n return currentOption // Return current if no other selectable option found\n }\n\n /**\n * Checks if an option is selectable (not disabled and not hidden)\n */\n protected isOptionSelectable(option: UiOption): boolean {\n if (option.disabled) {\n return false\n }\n if (option.hasAttribute('disabled')) {\n return false\n }\n if (option.hidden && option.hasAttribute('hidden')) {\n return false\n }\n return true\n }\n\n handleSelect(e: CustomEvent<{ item: UiOption }>): void {\n e.stopPropagation()\n const item = e.detail.item\n if (this.selectedOption && this.selectedOption !== item) {\n this.selectedOption.selected = false\n }\n item.selected = true\n this.selectedOption = item\n this.#value = item.value\n this.#internals.setFormValue(this.value ?? null)\n this.open = false\n\n // Dispatch change event\n const changeEvent = new CustomEvent<UiSelectChangeEvent>('change', {\n detail: { value: this.value, item: item },\n bubbles: false,\n composed: true,\n })\n this.dispatchEvent(changeEvent)\n // Focus will be returned to select element by handleOpenChange when open=false\n }\n\n handleMenuClose(): void {\n this.open = false\n // Focus will be returned to select element by handleOpenChange when open=false\n }\n\n handleMenuToggle(e: ToggleEvent): void {\n if (e.newState === 'closed') {\n this.open = false\n }\n }\n\n protected renderInput(): TemplateResult {\n const styles = {\n 'anchor-name': `--${this.id}`,\n }\n return html`<ui-outlined-text-field\n .name=${this.name}\n .label=${this.label}\n .value=${this.renderValue}\n .disabled=${this.disabled}\n .required=${this.required}\n readonly\n tabindex=\"-1\"\n .inert=${true}\n aria-hidden=\"true\"\n .invalid=${this.invalid}\n .invalidText=${this.invalidText || ''}\n .supportingText=${this.supportingText || ''}\n class=\"input\"\n style=${styleMap(styles)}\n part=\"input\"\n >\n <ui-icon part=\"icon\" slot=\"suffix\">arrow_drop_down</ui-icon>\n </ui-outlined-text-field>`\n }\n\n protected renderMenu(): TemplateResult {\n const styles = {\n 'position-anchor': `--${this.id}`,\n }\n return html`<ui-menu\n id=\"menu\"\n class=\"menu\"\n part=\"menu\"\n style=${styleMap(styles)}\n popover=\"auto\"\n selector=\"ui-option\"\n @select=\"${this.handleSelect}\"\n @close=\"${this.handleMenuClose}\"\n @toggle=\"${this.handleMenuToggle}\"\n >\n <slot @slotchange=\"${this.handleSlotChange}\"></slot>\n </ui-menu>`\n }\n\n protected async handleSlotChange(): Promise<void> {\n // When options change, re-evaluate the current selection\n // only if we don't have an explicit value set\n if (!this.value) {\n this.setCurrentOption()\n this.requestUpdate()\n }\n }\n\n protected renderFocusRing(): TemplateResult {\n return html`<ui-focus-ring part=\"focus-ring\" class=\"focus-ring\" .control=\"${this as HTMLElement}\"></ui-focus-ring>`\n }\n\n override render(): TemplateResult {\n const classes = classMap({\n 'ui-select': true,\n 'open': this.open,\n 'disabled': this.disabled,\n })\n return html`${this.renderFocusRing()}\n <div class=\"${classes}\">${this.renderInput()} ${this.renderMenu()}</div> `\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Select.js","sourceRoot":"","sources":["../../../../../src/md/select/internals/Select.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, PropertyValues, TemplateResult } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { styleMap } from 'lit/directives/style-map.js'\nimport { setDisabled } from '../../../lib/disabled.js'\nimport { UiElement } from '../../UiElement.js'\nimport type UiOption from './Option.js'\nimport type { UiMenuElement } from '../../menu/ui-menu.js'\nimport { nanoid } from 'nanoid'\n\nimport '../../text-field/ui-outlined-text-field.js'\nimport '../../menu/ui-menu.js'\nimport '../../icons/ui-icon.js'\nimport '../../focus-ring/ui-focus-ring.js'\n\nexport interface UiSelectChangeEvent {\n value: string | undefined\n item: UiOption | null\n}\n\n/**\n * Material Design 3 Select component that behaves like an outlined text field with dropdown.\n *\n * @fires change - Dispatched when the selection changes. The event is non-bubbling and non-cancelable.\n * The `event.detail` object contains the `value` and `item` properties.\n * @fires open - Dispatched when the dropdown opens\n * @fires close - Dispatched when the dropdown closes\n */\nexport default class UiSelect extends UiElement {\n static readonly formAssociated = true\n #internals = this.attachInternals()\n\n /**\n * The value has a private member so that we can set the value without triggering\n * the side effects.\n */\n #value: string | undefined\n\n /**\n * Type-ahead search string accumulated from user typing\n */\n #typeAheadString = ''\n\n /**\n * Timer for resetting the type-ahead search string\n */\n #typeAheadTimer: number | null = null\n\n /**\n * Timeout duration for type-ahead reset (in milliseconds)\n */\n static readonly TYPE_AHEAD_TIMEOUT = 1000\n\n /**\n * The currently selected value. Corresponds to the `value` attribute of the selected `ui-option`.\n * When set programmatically, it will update the selected option if a matching option exists.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select value=\"apple\">\n * <ui-option value=\"apple\">Apple</ui-option>\n * <ui-option value=\"banana\">Banana</ui-option>\n * </ui-select>\n * ```\n */\n get value(): string | undefined {\n return this.#value\n }\n\n @property({ type: String })\n set value(newValue: string | undefined) {\n const oldValue = this.#value\n if (newValue === oldValue) return\n this.#value = newValue\n this.requestUpdate()\n }\n\n /**\n * The name attribute for form submission. This value will be used as the key\n * when the form is submitted.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select name=\"country\" value=\"us\">\n * <ui-option value=\"us\">United States</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: String }) accessor name: string | undefined\n\n /**\n * The label text displayed in the select field. Provides accessible labeling\n * and is shown as the floating label in the outlined text field.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select label=\"Select a country\">\n * <ui-option value=\"us\">United States</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: String }) accessor label: string | undefined\n\n /**\n * Whether the select is required for form validation. When true, the select\n * must have a value selected for the form to be valid.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select required label=\"Required field\">\n * <ui-option value=\"option1\">Option 1</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: Boolean }) accessor required = false\n\n /**\n * Whether the select is in an invalid state. This is typically set automatically\n * during validation, but can be set manually to indicate validation errors.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select invalid invalidText=\"Please select a valid option\">\n * <ui-option value=\"option1\">Option 1</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: Boolean }) accessor invalid: boolean | undefined\n\n /**\n * The error message to display when the select is invalid. This text is shown\n * below the select field when `invalid` is true.\n *\n * @attribute\n * @example\n * ```html\n * <ui-select invalid invalidText=\"This field is required\">\n * <ui-option value=\"option1\">Option 1</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: String }) accessor invalidText: string | undefined\n\n /**\n * @attribute\n */\n @property({ type: String }) accessor supportingText: string | undefined\n\n /**\n * Whether the select is disabled. When disabled, the select cannot be interacted\n * with and will not receive focus or respond to user input.\n *\n * @default false\n * @attribute\n * @example\n * ```html\n * <ui-select disabled label=\"Disabled select\">\n * <ui-option value=\"option1\">Option 1</ui-option>\n * </ui-select>\n * ```\n */\n @property({ type: Boolean, reflect: true }) accessor disabled = false\n\n /**\n * Whether the dropdown menu is currently open. This property reflects the\n * current state of the dropdown and can be set programmatically to open/close it.\n *\n * @default false\n * @example\n * ```javascript\n * // Open the dropdown programmatically\n * selectElement.open = true;\n *\n * // Close the dropdown\n * selectElement.open = false;\n * ```\n */\n @property({ type: Boolean, reflect: true }) accessor open = false\n\n @state() accessor selectedOption: UiOption | null = null\n\n @query('.menu') accessor menu!: UiMenuElement\n\n /**\n * Returns the currently selected option element. This provides access to the\n * full `ui-option` element, not just its value.\n *\n * @readonly\n * @example\n * ```javascript\n * const select = document.querySelector('ui-select');\n * const selectedItem = select.selectedItem;\n * if (selectedItem) {\n * console.log('Selected option:', selectedItem.textContent);\n * }\n * ```\n */\n get selectedItem(): UiOption | null {\n return this.selectedOption\n }\n\n /**\n * Returns the text content that should be displayed in the select field.\n * This is the rendered value of the currently selected option.\n *\n * @readonly\n * @example\n * ```javascript\n * const select = document.querySelector('ui-select');\n * console.log('Display text:', select.renderValue);\n * ```\n */\n get renderValue(): string {\n const item = this.selectedOption\n return item ? item.renderValue : ''\n }\n\n /**\n * Returns the form element that contains this select, if any.\n * Part of the form-associated custom element API.\n *\n * @readonly\n */\n get form(): HTMLFormElement | null {\n return this.#internals.form\n }\n\n /**\n * Returns the validity state of the select element.\n * Part of the form-associated custom element API.\n *\n * @readonly\n */\n get validity(): ValidityState {\n return this.#internals.validity\n }\n\n /**\n * Returns the validation message for the select element.\n * Part of the form-associated custom element API.\n *\n * @readonly\n */\n get validationMessage(): string {\n return this.#internals.validationMessage\n }\n\n /**\n * Returns whether the select element will be validated when the form is submitted.\n * Part of the form-associated custom element API.\n *\n * @readonly\n */\n get willValidate(): boolean {\n return this.#internals.willValidate\n }\n\n /**\n * Checks the validity of the select element and returns true if valid.\n * Part of the form-associated custom element API.\n *\n * @returns {boolean} True if the element is valid, false otherwise\n * @example\n * ```javascript\n * const select = document.querySelector('ui-select');\n * if (!select.checkValidity()) {\n * console.log('Select is invalid:', select.validationMessage);\n * }\n * ```\n */\n checkValidity(): boolean {\n return this.#internals.checkValidity()\n }\n\n constructor() {\n super()\n this.addEventListener('click', this.handleClick.bind(this))\n this.addEventListener('blur', this.handleBlur.bind(this))\n this.addEventListener('keydown', this.handleKeydown.bind(this))\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.setAttribute('role', 'combobox')\n this.setAttribute('aria-haspopup', 'listbox')\n this.setAttribute('aria-controls', 'menu')\n if (!this.disabled) {\n this.setAttribute('tabindex', '0')\n }\n if (!this.id) {\n this.id = `select-${nanoid(6)}`\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // Clean up the type-ahead timer\n if (this.#typeAheadTimer) {\n clearTimeout(this.#typeAheadTimer)\n this.#typeAheadTimer = null\n }\n }\n\n /**\n * Resets the select to its initial state. Called automatically when the parent\n * form is reset. Part of the form-associated custom element API.\n *\n * @example\n * ```javascript\n * const select = document.querySelector('ui-select');\n * select.formResetCallback(); // Clears the selection\n * ```\n */\n formResetCallback(): void {\n this.value = undefined\n }\n\n /**\n * Restores the select's state from saved form data. Called automatically when\n * the browser restores form state. Part of the form-associated custom element API.\n *\n * @param {string | null} state - The saved state to restore\n */\n formStateRestoreCallback(state: string | null): void {\n this.value = state ?? undefined\n }\n\n /**\n * Validates the select element and updates its validity state. This is called\n * automatically during property changes, but can be called manually to trigger validation.\n *\n * @example\n * ```javascript\n * const select = document.querySelector('ui-select');\n * select.validate();\n * if (select.invalid) {\n * console.log('Validation failed:', select.invalidText);\n * }\n * ```\n */\n validate(): void {\n let message = ''\n if (this.required && !this.value) {\n message = 'Please select an item.'\n this.#internals.setValidity({ valueMissing: true }, message)\n } else {\n this.#internals.setValidity({})\n }\n this.invalid = !this.#internals.validity.valid\n this.invalidText = message\n }\n\n protected override willUpdate(changedProperties: PropertyValues<this>): void {\n super.willUpdate(changedProperties)\n if (changedProperties.has('disabled')) {\n setDisabled(this, this.disabled)\n }\n if (changedProperties.has('open')) {\n this.handleOpenChange()\n }\n if (changedProperties.has('value')) {\n this.setCurrentOption()\n this.#internals.setFormValue(this.value ?? null)\n this.validate()\n }\n if (changedProperties.has('label')) {\n if (this.label) {\n this.setAttribute('aria-label', this.label)\n } else {\n this.removeAttribute('aria-label')\n }\n }\n }\n\n protected override firstUpdated(cp: PropertyValues): void {\n super.firstUpdated(cp)\n this.updateComplete.then(() => {\n this.setCurrentOption()\n this.#internals.setFormValue(this.value ?? null)\n // We need to update here as event with `value` and `selectedOption`\n // already set, the `renderValue` might have incorrect value\n // due to the DOM update.\n this.requestUpdate()\n })\n }\n\n protected setCurrentOption(): void {\n const options = this.querySelectorAll<UiOption>('ui-option')\n if (this.value) {\n this.selectedOption = Array.from(options).find((option) => option.value === this.value) || null\n } else {\n const selected = Array.from(options).find((option) => option.selected)\n if (selected) {\n this.selectedOption = selected\n this.#value = selected.value\n } else {\n this.selectedOption = null\n }\n }\n }\n\n protected handleKeydown(e: KeyboardEvent): void {\n if (this.disabled || e.defaultPrevented) return\n\n // Handle type-ahead for printable characters\n if (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {\n this.handleTypeAhead(e.key.toLowerCase())\n return\n }\n\n if (this.open) {\n switch (e.key) {\n case 'Tab': {\n // If menu is open and Tab is pressed, close it and allow normal tab navigation\n if (this.open) {\n this.open = false\n }\n break\n }\n case 'Escape': {\n if (this.open) {\n e.preventDefault()\n this.open = false\n this.focus() // Return focus to the select element\n }\n break\n }\n case 'ArrowDown':\n e.preventDefault()\n this.focusNextMenuItem()\n return\n case 'ArrowUp':\n e.preventDefault()\n this.focusPreviousMenuItem()\n return\n case 'Home':\n e.preventDefault()\n this.focusFirstMenuItem()\n return\n case 'End':\n e.preventDefault()\n this.focusLastMenuItem()\n return\n case 'Enter':\n case ' ': {\n const currentItem = this.querySelector<UiOption>(':focus')\n if (currentItem && this.isOptionSelectable(currentItem)) {\n e.preventDefault()\n this.menu.notifySelect(currentItem)\n }\n return\n }\n }\n } else {\n switch (e.key) {\n case 'Enter':\n case ' ': {\n if (!this.open) {\n e.preventDefault()\n this.open = true\n }\n break\n }\n case 'ArrowDown':\n case 'ArrowUp': {\n if (!this.open) {\n e.preventDefault()\n this.open = true\n }\n // If menu is open, let the menu handle arrow keys\n break\n }\n }\n }\n }\n\n protected handleBlur(e: FocusEvent): void {\n if (this.disabled) return\n\n // Check if focus is moving to the menu or one of its children\n const relatedTarget = e.relatedTarget as HTMLElement\n\n if (relatedTarget && this.contains(relatedTarget)) {\n // Focus is moving to the menu, keep it open\n return\n }\n\n // Close the menu when focus leaves the component\n this.open = false\n }\n\n override handleClick(e: Event): void {\n if (this.disabled || e.defaultPrevented) return\n e.preventDefault()\n e.stopPropagation()\n if (this.open && e.target === this) {\n // If the select is already open and clicked again, close it\n this.open = false\n return\n }\n this.open = true\n }\n\n protected async handleOpenChange(): Promise<void> {\n const menu = this.menu\n if (!menu) {\n // The status can be set before the menu is rendered\n return\n }\n this.setAttribute('aria-expanded', String(this.open))\n if (this.open) {\n menu.showPopover()\n // Focus on the selected option or first selectable option when menu opens\n if (this.selectedOption && this.isOptionSelectable(this.selectedOption)) {\n this.selectedOption.focus()\n this.selectedOption.scrollIntoView({ behavior: 'instant', block: 'nearest', inline: 'nearest' })\n } else {\n const firstSelectableOption = this.getFirstSelectableOption()\n if (firstSelectableOption) {\n firstSelectableOption.focus()\n firstSelectableOption.scrollIntoView({ behavior: 'instant', block: 'nearest', inline: 'nearest' })\n }\n }\n this.dispatchEvent(new CustomEvent('open', { bubbles: false, composed: true }))\n } else {\n menu.hidePopover()\n this.dispatchEvent(new CustomEvent('close', { bubbles: false, composed: true }))\n // Return focus to the select element when menu closes\n this.focus()\n }\n }\n\n /**\n * Focus the next menu item in the dropdown, skipping disabled options\n */\n focusNextMenuItem(): void {\n const currentItem = this.querySelector<UiOption>(':focus')\n const nextItem = currentItem ? this.getNextSelectableOption(currentItem) : this.getFirstSelectableOption()\n if (nextItem) {\n nextItem.focus()\n }\n }\n\n /**\n * Focus the previous menu item in the dropdown, skipping disabled options\n */\n focusPreviousMenuItem(): void {\n const currentItem = this.querySelector<UiOption>(':focus')\n const previousItem = currentItem ? this.getPreviousSelectableOption(currentItem) : this.getLastSelectableOption()\n if (previousItem) {\n previousItem.focus()\n }\n }\n\n /**\n * Focus the first menu item in the dropdown, skipping disabled options\n */\n focusFirstMenuItem(): void {\n const firstItem = this.getFirstSelectableOption()\n if (firstItem) {\n firstItem.focus()\n }\n }\n\n /**\n * Focus the last menu item in the dropdown, skipping disabled options\n */\n focusLastMenuItem(): void {\n const lastItem = this.getLastSelectableOption()\n if (lastItem) {\n lastItem.focus()\n }\n }\n\n /**\n * Gets the first selectable (non-disabled) option\n */\n getFirstSelectableOption(): UiOption | null {\n const options = this.querySelectorAll<UiOption>('ui-option')\n for (const option of options) {\n if (this.isOptionSelectable(option)) {\n return option\n }\n }\n return null\n }\n\n /**\n * Gets the last selectable (non-disabled) option\n */\n getLastSelectableOption(): UiOption | null {\n const options = Array.from(this.querySelectorAll<UiOption>('ui-option')).reverse()\n for (const option of options) {\n if (this.isOptionSelectable(option)) {\n return option\n }\n }\n return null\n }\n\n /**\n * Gets the next selectable option after the current one, wrapping around if needed\n */\n protected getNextSelectableOption(currentOption: UiOption): UiOption | null {\n const options = Array.from(this.querySelectorAll<UiOption>('ui-option'))\n const currentIndex = options.indexOf(currentOption)\n\n if (currentIndex === -1) {\n return this.getFirstSelectableOption()\n }\n\n // Start from the next option and wrap around\n for (let i = 1; i < options.length; i++) {\n const nextIndex = (currentIndex + i) % options.length\n const option = options[nextIndex]\n if (this.isOptionSelectable(option)) {\n return option\n }\n }\n\n return currentOption // Return current if no other selectable option found\n }\n\n /**\n * Gets the previous selectable option before the current one, wrapping around if needed\n */\n protected getPreviousSelectableOption(currentOption: UiOption): UiOption | null {\n const options = Array.from(this.querySelectorAll<UiOption>('ui-option'))\n const currentIndex = options.indexOf(currentOption)\n\n if (currentIndex === -1) {\n return this.getLastSelectableOption()\n }\n\n // Start from the previous option and wrap around\n for (let i = 1; i < options.length; i++) {\n const prevIndex = (currentIndex - i + options.length) % options.length\n const option = options[prevIndex]\n if (this.isOptionSelectable(option)) {\n return option\n }\n }\n\n return currentOption // Return current if no other selectable option found\n }\n\n /**\n * Checks if an option is selectable (not disabled and not hidden)\n */\n protected isOptionSelectable(option: UiOption): boolean {\n if (option.disabled) {\n return false\n }\n if (option.hasAttribute('disabled')) {\n return false\n }\n if (option.hidden && option.hasAttribute('hidden')) {\n return false\n }\n return true\n }\n\n /**\n * Handles type-ahead functionality for keyboard navigation\n */\n protected handleTypeAhead(char: string): void {\n // Clear the existing timer\n if (this.#typeAheadTimer) {\n clearTimeout(this.#typeAheadTimer)\n }\n\n // Add the character to the search string\n this.#typeAheadString += char\n\n // Find the matching option\n const matchingOption = this.findOptionByTypeAhead(this.#typeAheadString)\n if (matchingOption) {\n if (this.open) {\n // If menu is open, focus the matching option\n matchingOption.focus()\n } else {\n // If menu is closed, select the matching option\n this.selectOption(matchingOption)\n }\n }\n\n // Set a timer to reset the search string\n this.#typeAheadTimer = window.setTimeout(() => {\n this.#typeAheadString = ''\n this.#typeAheadTimer = null\n }, UiSelect.TYPE_AHEAD_TIMEOUT)\n }\n\n /**\n * Finds an option that matches the type-ahead search string\n */\n protected findOptionByTypeAhead(searchString: string): UiOption | null {\n const options = this.querySelectorAll<UiOption>('ui-option')\n\n for (const option of options) {\n if (!this.isOptionSelectable(option)) {\n continue\n }\n\n // Get the option's text content for comparison\n const optionText = this.getOptionDisplayText(option).toLowerCase()\n\n if (optionText.startsWith(searchString)) {\n return option\n }\n }\n\n return null\n }\n\n /**\n * Gets the display text for an option (either textContent or renderValue)\n */\n protected getOptionDisplayText(option: UiOption): string {\n // Use renderValue if available, otherwise fall back to textContent\n return option.renderValue || option.textContent?.trim() || ''\n }\n\n /**\n * Selects an option and updates the component state\n */\n protected selectOption(option: UiOption): void {\n if (this.selectedOption && this.selectedOption !== option) {\n this.selectedOption.selected = false\n }\n\n option.selected = true\n this.selectedOption = option\n this.#value = option.value\n this.#internals.setFormValue(this.value ?? null)\n\n // Dispatch change event\n const changeEvent = new CustomEvent<UiSelectChangeEvent>('change', {\n detail: { value: this.value, item: option },\n bubbles: false,\n composed: true,\n })\n this.dispatchEvent(changeEvent)\n }\n\n handleSelect(e: CustomEvent<{ item: UiOption }>): void {\n e.stopPropagation()\n const item = e.detail.item\n if (this.selectedOption && this.selectedOption !== item) {\n this.selectedOption.selected = false\n }\n item.selected = true\n this.selectedOption = item\n this.#value = item.value\n this.#internals.setFormValue(this.value ?? null)\n this.open = false\n\n // Dispatch change event\n const changeEvent = new CustomEvent<UiSelectChangeEvent>('change', {\n detail: { value: this.value, item: item },\n bubbles: false,\n composed: true,\n })\n this.dispatchEvent(changeEvent)\n // Focus will be returned to select element by handleOpenChange when open=false\n }\n\n handleMenuClose(): void {\n this.open = false\n // Focus will be returned to select element by handleOpenChange when open=false\n }\n\n handleMenuToggle(e: ToggleEvent): void {\n if (e.newState === 'closed') {\n this.open = false\n }\n }\n\n protected renderInput(): TemplateResult {\n const styles = {\n 'anchor-name': `--${this.id}`,\n }\n return html`<ui-outlined-text-field\n .name=${this.name}\n .label=${this.label}\n .value=${this.renderValue}\n .disabled=${this.disabled}\n .required=${this.required}\n readonly\n tabindex=\"-1\"\n .inert=${true}\n aria-hidden=\"true\"\n .invalid=${this.invalid}\n .invalidText=${this.invalidText || ''}\n .supportingText=${this.supportingText || ''}\n class=\"input\"\n style=${styleMap(styles)}\n part=\"input\"\n >\n <ui-icon part=\"icon\" slot=\"suffix\">arrow_drop_down</ui-icon>\n </ui-outlined-text-field>`\n }\n\n protected renderMenu(): TemplateResult {\n const styles = {\n 'position-anchor': `--${this.id}`,\n }\n return html`<ui-menu\n id=\"menu\"\n class=\"menu\"\n part=\"menu\"\n style=${styleMap(styles)}\n popover=\"auto\"\n selector=\"ui-option\"\n @select=\"${this.handleSelect}\"\n @close=\"${this.handleMenuClose}\"\n @toggle=\"${this.handleMenuToggle}\"\n >\n <slot @slotchange=\"${this.handleSlotChange}\"></slot>\n </ui-menu>`\n }\n\n protected async handleSlotChange(): Promise<void> {\n // When options change, re-evaluate the current selection\n // only if we don't have an explicit value set\n if (!this.value) {\n this.setCurrentOption()\n this.requestUpdate()\n }\n }\n\n protected renderFocusRing(): TemplateResult {\n return html`<ui-focus-ring part=\"focus-ring\" class=\"focus-ring\" .control=\"${this as HTMLElement}\"></ui-focus-ring>`\n }\n\n override render(): TemplateResult {\n const classes = classMap({\n 'ui-select': true,\n 'open': this.open,\n 'disabled': this.disabled,\n })\n return html`${this.renderFocusRing()}\n <div class=\"${classes}\">${this.renderInput()} ${this.renderMenu()}</div> `\n }\n}\n"]}
|