@api-client/ui 0.5.24 → 0.5.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.cursor/rules/lit-best-practices.mdc +12 -1
  2. package/.github/instructions/lit-best-practices.instructions.md +2 -0
  3. package/build/src/md/dropdown-list/internals/UiDropdownList.d.ts.map +1 -1
  4. package/build/src/md/dropdown-list/internals/UiDropdownList.js +4 -3
  5. package/build/src/md/dropdown-list/internals/UiDropdownList.js.map +1 -1
  6. package/build/src/md/input/Input.d.ts +8 -4
  7. package/build/src/md/input/Input.d.ts.map +1 -1
  8. package/build/src/md/input/Input.js +8 -36
  9. package/build/src/md/input/Input.js.map +1 -1
  10. package/build/src/md/list/internals/List.d.ts +3 -1
  11. package/build/src/md/list/internals/List.d.ts.map +1 -1
  12. package/build/src/md/list/internals/List.js +9 -4
  13. package/build/src/md/list/internals/List.js.map +1 -1
  14. package/build/src/md/menu/internal/Menu.d.ts +8 -7
  15. package/build/src/md/menu/internal/Menu.d.ts.map +1 -1
  16. package/build/src/md/menu/internal/Menu.js +26 -29
  17. package/build/src/md/menu/internal/Menu.js.map +1 -1
  18. package/build/src/md/select/index.d.ts +4 -0
  19. package/build/src/md/select/index.d.ts.map +1 -0
  20. package/build/src/md/select/index.js +3 -0
  21. package/build/src/md/select/index.js.map +1 -0
  22. package/build/src/md/select/internals/Option.d.ts +125 -0
  23. package/build/src/md/select/internals/Option.d.ts.map +1 -0
  24. package/build/src/md/select/internals/Option.js +242 -0
  25. package/build/src/md/select/internals/Option.js.map +1 -0
  26. package/build/src/md/select/internals/Option.styles.d.ts +3 -0
  27. package/build/src/md/select/internals/Option.styles.d.ts.map +1 -0
  28. package/build/src/md/select/internals/Option.styles.js +139 -0
  29. package/build/src/md/select/internals/Option.styles.js.map +1 -0
  30. package/build/src/md/select/internals/Select.d.ts +250 -0
  31. package/build/src/md/select/internals/Select.d.ts.map +1 -0
  32. package/build/src/md/select/internals/Select.js +606 -0
  33. package/build/src/md/select/internals/Select.js.map +1 -0
  34. package/build/src/md/select/internals/Select.styles.d.ts +3 -0
  35. package/build/src/md/select/internals/Select.styles.d.ts.map +1 -0
  36. package/build/src/md/select/internals/Select.styles.js +22 -0
  37. package/build/src/md/select/internals/Select.styles.js.map +1 -0
  38. package/build/src/md/select/ui-option.d.ts +12 -0
  39. package/build/src/md/select/ui-option.d.ts.map +1 -0
  40. package/build/src/md/select/ui-option.js +29 -0
  41. package/build/src/md/select/ui-option.js.map +1 -0
  42. package/build/src/md/select/ui-select.d.ts +12 -0
  43. package/build/src/md/select/ui-select.d.ts.map +1 -0
  44. package/build/src/md/select/ui-select.js +27 -0
  45. package/build/src/md/select/ui-select.js.map +1 -0
  46. package/build/src/md/text-field/internals/TextField.d.ts.map +1 -1
  47. package/build/src/md/text-field/internals/TextField.js +1 -0
  48. package/build/src/md/text-field/internals/TextField.js.map +1 -1
  49. package/demo/md/index.html +2 -0
  50. package/demo/md/inputs/input.ts +4 -0
  51. package/demo/md/select/index.html +16 -0
  52. package/demo/md/select/index.ts +202 -0
  53. package/package.json +1 -1
  54. package/src/md/dropdown-list/internals/UiDropdownList.ts +4 -3
  55. package/src/md/input/Input.ts +8 -37
  56. package/src/md/list/internals/List.ts +12 -5
  57. package/src/md/menu/internal/Menu.ts +27 -18
  58. package/src/md/select/index.ts +3 -0
  59. package/src/md/select/internals/Option.styles.ts +139 -0
  60. package/src/md/select/internals/Option.ts +210 -0
  61. package/src/md/select/internals/Select.styles.ts +22 -0
  62. package/src/md/select/internals/Select.ts +534 -0
  63. package/src/md/select/ui-option.ts +18 -0
  64. package/src/md/select/ui-select.ts +17 -0
  65. package/src/md/text-field/internals/TextField.ts +1 -0
  66. package/test/md/menu/SubMenu.test.ts +2 -3
  67. package/test/md/select/Select.test.ts +667 -0
@@ -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, queryAssignedElements } 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 * Currently active sub-menu\n */\n @state() accessor activeSubMenu: UiSubMenu | null = null\n\n /**\n * Assigned menu items from light DOM\n */\n @queryAssignedElements({ selector: 'ui-menu-item' }) protected accessor assignedMenuItems!: UiMenuItem[]\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 /**\n * Shows the menu\n */\n show(): void {\n this.tabIndex = 0 // Make menu focusable\n this.ariaExpanded = 'true'\n this.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 hide(): void {\n this.tabIndex = -1\n this.ariaExpanded = 'false'\n this.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 const menuBottom = box.top + box.height\n const menuRight = box.left + box.width\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\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\n if (menuBottom > innerHeight) {\n const availableHeight = innerHeight - box.top\n this.style.maxHeight = `${Math.max(200, availableHeight - 20)}px`\n }\n\n if (menuRight > innerWidth) {\n const availableWidth = innerWidth - box.left\n // Let CSS anchor positioning handle horizontal flipping\n // We could set max-width if needed\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, index?: number): boolean {\n // Handle single selection\n if (item instanceof UiMenuItem) {\n this.clearSelection()\n item.selected = true\n }\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 this.assignedMenuItems.forEach((menuItem) => {\n menuItem.selected = false\n })\n }\n\n /**\n * Gets the currently selected menu item\n */\n get selectedItem(): UiMenuItem | null {\n return this.assignedMenuItems.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 * 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 const menuBottom = box.top + box.height\n const menuRight = box.left + box.width\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\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\n if (menuBottom > innerHeight) {\n const availableHeight = innerHeight - box.top\n this.style.maxHeight = `${Math.max(200, availableHeight - 20)}px`\n }\n\n if (menuRight > innerWidth) {\n const availableWidth = innerWidth - box.left\n // Let CSS anchor positioning handle horizontal flipping\n // We could set max-width if needed\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 // Handle single selection\n this.clearSelection()\n item.selected = true\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"]}
@@ -0,0 +1,4 @@
1
+ export { UiSelectElement } from './ui-select.js';
2
+ export { UiOptionElement } from './ui-option.js';
3
+ export type { UiListItemsChange, UiListSelection } from '../list/internals/List.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/md/select/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { UiSelectElement } from './ui-select.js';
2
+ export { UiOptionElement } from './ui-option.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/md/select/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA","sourcesContent":["export { UiSelectElement } from './ui-select.js'\nexport { UiOptionElement } from './ui-option.js'\nexport type { UiListItemsChange, UiListSelection } from '../list/internals/List.js'\n"]}
@@ -0,0 +1,125 @@
1
+ import { PropertyValues, TemplateResult } from 'lit';
2
+ import UiListItem from '../../list/internals/ListItem.js';
3
+ /**
4
+ * Material Design 3 Select Option component.
5
+ *
6
+ * The `ui-option` component represents a selectable item within a `ui-select` dropdown.
7
+ * It extends `UiListItem` to provide consistent styling and behavior with other list components.
8
+ *
9
+ * @slot - The option content (label, icon, etc.)
10
+ * @slot start - Content to display at the start of the option (icon, avatar, etc.)
11
+ * @slot end - Content to display at the end of the option
12
+ * @slot supporting-text - Supporting text below the main content
13
+ * @fires select - Dispatched when the option is selected. Contains `{ item: UiOption, value: string }` in detail
14
+ *
15
+ * @example
16
+ * Basic option
17
+ * ```html
18
+ * <ui-option value="apple">Apple</ui-option>
19
+ * ```
20
+ *
21
+ * @example
22
+ * Option with supporting text
23
+ * ```html
24
+ * <ui-option value="john" lines="two">
25
+ * John Doe
26
+ * <span slot="supporting-text">john@example.com</span>
27
+ * </ui-option>
28
+ * ```
29
+ */
30
+ export default class UiOption extends UiListItem {
31
+ /**
32
+ * The value associated with this option. Used to identify the option when selected.
33
+ * This value is what gets set on the parent select element when this option is chosen.
34
+ *
35
+ * @example
36
+ * ```html
37
+ * <ui-option value="apple">Apple</ui-option>
38
+ * <ui-option value="banana">Banana</ui-option>
39
+ * ```
40
+ */
41
+ accessor value: string | undefined;
42
+ /**
43
+ * Whether this option is currently selected. This is typically managed automatically
44
+ * by the parent select component, but can be set manually for styling purposes.
45
+ *
46
+ * @default false
47
+ * @example
48
+ * ```html
49
+ * <ui-option value="apple" selected>Apple</ui-option>
50
+ * ```
51
+ */
52
+ accessor selected: boolean;
53
+ /**
54
+ * Returns the text representation of this option for display purposes.
55
+ * This method extracts and combines text content from all child nodes,
56
+ * including special handling for ui-icon elements.
57
+ *
58
+ * @readonly
59
+ * @returns {string} The rendered text value of the option
60
+ * @example
61
+ * ```javascript
62
+ * const option = document.querySelector('ui-option');
63
+ * console.log('Option text:', option.renderValue);
64
+ * ```
65
+ */
66
+ get renderValue(): string;
67
+ /**
68
+ * Initializes the option when it's connected to the DOM. Sets up ARIA attributes
69
+ * and generates a unique ID if one isn't provided.
70
+ *
71
+ * @protected
72
+ */
73
+ connectedCallback(): void;
74
+ /**
75
+ * Handles property updates and triggers appropriate side effects.
76
+ * Currently monitors the `selected` property to update selection state.
77
+ *
78
+ * @param {PropertyValues<this>} changedProperties - Map of changed properties
79
+ * @protected
80
+ */
81
+ protected updated(changedProperties: PropertyValues<this>): void;
82
+ /**
83
+ * Updates the visual and accessibility state when selection changes.
84
+ * Adds/removes CSS classes and ARIA attributes based on selection state.
85
+ *
86
+ * @protected
87
+ * @example
88
+ * ```javascript
89
+ * // This is called automatically when the selected property changes
90
+ * option.selected = true; // Will trigger updateSelectionState()
91
+ * ```
92
+ */
93
+ protected updateSelectionState(): void;
94
+ /**
95
+ * Handles click events on the option. Prevents default behavior and dispatches
96
+ * a custom 'select' event that the parent select component can listen to.
97
+ *
98
+ * @param {MouseEvent} e - The click event
99
+ * @protected
100
+ * @fires select - Custom event with option details in event.detail
101
+ * @example
102
+ * ```javascript
103
+ * // Listen for option selection
104
+ * option.addEventListener('select', (e) => {
105
+ * console.log('Selected option:', e.detail.item);
106
+ * console.log('Selected value:', e.detail.value);
107
+ * });
108
+ * ```
109
+ */
110
+ handleClick(e: MouseEvent): void;
111
+ /**
112
+ * Renders the option's template. Creates the main structure with focus ring,
113
+ * ripple effect, and content areas.
114
+ *
115
+ * @returns {TemplateResult} The rendered template
116
+ * @protected
117
+ */
118
+ protected render(): TemplateResult;
119
+ /**
120
+ * Renders the end section of the option, including the selection check icon
121
+ * when the option is selected.
122
+ */
123
+ protected renderEnd(): TemplateResult;
124
+ }
125
+ //# sourceMappingURL=Option.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Option.d.ts","sourceRoot":"","sources":["../../../../../src/md/select/internals/Option.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAG1D,OAAO,UAAU,MAAM,kCAAkC,CAAA;AAGzD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,UAAU;IAC9C;;;;;;;;;OASG;IACwC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IAE7E;;;;;;;;;OASG;IACyC,QAAQ,CAAC,QAAQ,UAAQ;IAErE;;;;;;;;;;;;OAYG;IACH,IAAI,WAAW,IAAI,MAAM,CAkBxB;IAED;;;;;OAKG;IACM,iBAAiB,IAAI,IAAI;IAQlC;;;;;;OAMG;cACgB,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI;IAQzE;;;;;;;;;;OAUG;IACH,SAAS,CAAC,oBAAoB,IAAI,IAAI;IAUtC;;;;;;;;;;;;;;;OAeG;IACM,WAAW,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI;IAoBzC;;;;;;OAMG;cACgB,MAAM,IAAI,cAAc;IAY3C;;;OAGG;cACgB,SAAS,IAAI,cAAc;CAS/C"}
@@ -0,0 +1,242 @@
1
+ import { __esDecorate, __runInitializers } from "tslib";
2
+ import { html } from 'lit';
3
+ import { property } from 'lit/decorators.js';
4
+ import { classMap } from 'lit/directives/class-map.js';
5
+ import UiListItem from '../../list/internals/ListItem.js';
6
+ import { nanoid } from 'nanoid';
7
+ let UiOption = (() => {
8
+ let _classSuper = UiListItem;
9
+ let _value_decorators;
10
+ let _value_initializers = [];
11
+ let _value_extraInitializers = [];
12
+ let _selected_decorators;
13
+ let _selected_initializers = [];
14
+ let _selected_extraInitializers = [];
15
+ return class UiOption extends _classSuper {
16
+ static {
17
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
18
+ _value_decorators = [property({ type: String, reflect: true })];
19
+ _selected_decorators = [property({ type: Boolean, reflect: true })];
20
+ __esDecorate(this, null, _value_decorators, { kind: "accessor", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, _value_initializers, _value_extraInitializers);
21
+ __esDecorate(this, null, _selected_decorators, { kind: "accessor", name: "selected", static: false, private: false, access: { has: obj => "selected" in obj, get: obj => obj.selected, set: (obj, value) => { obj.selected = value; } }, metadata: _metadata }, _selected_initializers, _selected_extraInitializers);
22
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
23
+ }
24
+ #value_accessor_storage = __runInitializers(this, _value_initializers, void 0);
25
+ /**
26
+ * The value associated with this option. Used to identify the option when selected.
27
+ * This value is what gets set on the parent select element when this option is chosen.
28
+ *
29
+ * @example
30
+ * ```html
31
+ * <ui-option value="apple">Apple</ui-option>
32
+ * <ui-option value="banana">Banana</ui-option>
33
+ * ```
34
+ */
35
+ get value() { return this.#value_accessor_storage; }
36
+ set value(value) { this.#value_accessor_storage = value; }
37
+ #selected_accessor_storage = (__runInitializers(this, _value_extraInitializers), __runInitializers(this, _selected_initializers, false
38
+ /**
39
+ * Returns the text representation of this option for display purposes.
40
+ * This method extracts and combines text content from all child nodes,
41
+ * including special handling for ui-icon elements.
42
+ *
43
+ * @readonly
44
+ * @returns {string} The rendered text value of the option
45
+ * @example
46
+ * ```javascript
47
+ * const option = document.querySelector('ui-option');
48
+ * console.log('Option text:', option.renderValue);
49
+ * ```
50
+ */
51
+ ));
52
+ /**
53
+ * Whether this option is currently selected. This is typically managed automatically
54
+ * by the parent select component, but can be set manually for styling purposes.
55
+ *
56
+ * @default false
57
+ * @example
58
+ * ```html
59
+ * <ui-option value="apple" selected>Apple</ui-option>
60
+ * ```
61
+ */
62
+ get selected() { return this.#selected_accessor_storage; }
63
+ set selected(value) { this.#selected_accessor_storage = value; }
64
+ /**
65
+ * Returns the text representation of this option for display purposes.
66
+ * This method extracts and combines text content from all child nodes,
67
+ * including special handling for ui-icon elements.
68
+ *
69
+ * @readonly
70
+ * @returns {string} The rendered text value of the option
71
+ * @example
72
+ * ```javascript
73
+ * const option = document.querySelector('ui-option');
74
+ * console.log('Option text:', option.renderValue);
75
+ * ```
76
+ */
77
+ get renderValue() {
78
+ const slot = this.shadowRoot?.querySelector('slot:not([name])');
79
+ if (!slot)
80
+ return this.value || '';
81
+ const nodes = slot.assignedNodes({ flatten: true });
82
+ const content = [];
83
+ for (const node of nodes) {
84
+ if (node.nodeType === Node.TEXT_NODE) {
85
+ content.push(node.textContent || '');
86
+ }
87
+ else if (node.nodeType === Node.ELEMENT_NODE) {
88
+ const element = node;
89
+ if (element.tagName.toLowerCase() === 'ui-icon') {
90
+ content.push(element.getAttribute('icon') || '');
91
+ }
92
+ else {
93
+ content.push(element.textContent || '');
94
+ }
95
+ }
96
+ }
97
+ return content.join(' ').trim() || this.value || '';
98
+ }
99
+ /**
100
+ * Initializes the option when it's connected to the DOM. Sets up ARIA attributes
101
+ * and generates a unique ID if one isn't provided.
102
+ *
103
+ * @protected
104
+ */
105
+ connectedCallback() {
106
+ super.connectedCallback();
107
+ this.setAttribute('role', 'option');
108
+ if (!this.id) {
109
+ this.id = `option-${nanoid(6)}`;
110
+ }
111
+ }
112
+ /**
113
+ * Handles property updates and triggers appropriate side effects.
114
+ * Currently monitors the `selected` property to update selection state.
115
+ *
116
+ * @param {PropertyValues<this>} changedProperties - Map of changed properties
117
+ * @protected
118
+ */
119
+ updated(changedProperties) {
120
+ super.updated(changedProperties);
121
+ if (changedProperties.has('selected')) {
122
+ this.updateSelectionState();
123
+ }
124
+ }
125
+ /**
126
+ * Updates the visual and accessibility state when selection changes.
127
+ * Adds/removes CSS classes and ARIA attributes based on selection state.
128
+ *
129
+ * @protected
130
+ * @example
131
+ * ```javascript
132
+ * // This is called automatically when the selected property changes
133
+ * option.selected = true; // Will trigger updateSelectionState()
134
+ * ```
135
+ */
136
+ updateSelectionState() {
137
+ if (this.selected) {
138
+ this.classList.add('selected');
139
+ this.setAttribute('aria-selected', 'true');
140
+ }
141
+ else {
142
+ this.classList.remove('selected');
143
+ this.setAttribute('aria-selected', 'false');
144
+ }
145
+ }
146
+ /**
147
+ * Handles click events on the option. Prevents default behavior and dispatches
148
+ * a custom 'select' event that the parent select component can listen to.
149
+ *
150
+ * @param {MouseEvent} e - The click event
151
+ * @protected
152
+ * @fires select - Custom event with option details in event.detail
153
+ * @example
154
+ * ```javascript
155
+ * // Listen for option selection
156
+ * option.addEventListener('select', (e) => {
157
+ * console.log('Selected option:', e.detail.item);
158
+ * console.log('Selected value:', e.detail.value);
159
+ * });
160
+ * ```
161
+ */
162
+ handleClick(e) {
163
+ e.preventDefault();
164
+ if (this.disabled) {
165
+ e.stopPropagation();
166
+ return;
167
+ }
168
+ // Let the parent handle the selection
169
+ this.dispatchEvent(new CustomEvent('select', {
170
+ detail: {
171
+ item: this,
172
+ value: this.value,
173
+ },
174
+ bubbles: true,
175
+ composed: true,
176
+ }));
177
+ }
178
+ /**
179
+ * Renders the option's template. Creates the main structure with focus ring,
180
+ * ripple effect, and content areas.
181
+ *
182
+ * @returns {TemplateResult} The rendered template
183
+ * @protected
184
+ */
185
+ render() {
186
+ const surfaceClasses = classMap({
187
+ surface: true,
188
+ selected: this.selected,
189
+ });
190
+ return html `
191
+ ${this.renderFocusRing()} ${this.renderRipple()}
192
+ <div class="${surfaceClasses}">${this.renderStart()} ${this.renderBody()} ${this.renderEnd()}</div>
193
+ `;
194
+ }
195
+ /**
196
+ * Renders the end section of the option, including the selection check icon
197
+ * when the option is selected.
198
+ */
199
+ renderEnd() {
200
+ return html `
201
+ <div class="end">
202
+ ${this.selected ? html `<ui-icon icon="check" class="selection-icon"></ui-icon>` : ''}
203
+ <slot name="end" @slotchange=${this.handleSlotChange}></slot>
204
+ <slot name="end-text" class="trailing-supporting-text"></slot>
205
+ </div>
206
+ `;
207
+ }
208
+ constructor() {
209
+ super(...arguments);
210
+ __runInitializers(this, _selected_extraInitializers);
211
+ }
212
+ };
213
+ })();
214
+ /**
215
+ * Material Design 3 Select Option component.
216
+ *
217
+ * The `ui-option` component represents a selectable item within a `ui-select` dropdown.
218
+ * It extends `UiListItem` to provide consistent styling and behavior with other list components.
219
+ *
220
+ * @slot - The option content (label, icon, etc.)
221
+ * @slot start - Content to display at the start of the option (icon, avatar, etc.)
222
+ * @slot end - Content to display at the end of the option
223
+ * @slot supporting-text - Supporting text below the main content
224
+ * @fires select - Dispatched when the option is selected. Contains `{ item: UiOption, value: string }` in detail
225
+ *
226
+ * @example
227
+ * Basic option
228
+ * ```html
229
+ * <ui-option value="apple">Apple</ui-option>
230
+ * ```
231
+ *
232
+ * @example
233
+ * Option with supporting text
234
+ * ```html
235
+ * <ui-option value="john" lines="two">
236
+ * John Doe
237
+ * <span slot="supporting-text">john@example.com</span>
238
+ * </ui-option>
239
+ * ```
240
+ */
241
+ export default UiOption;
242
+ //# sourceMappingURL=Option.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Option.js","sourceRoot":"","sources":["../../../../../src/md/select/internals/Option.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, PropertyValues, TemplateResult } from 'lit'\nimport { property } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport UiListItem from '../../list/internals/ListItem.js'\nimport { nanoid } from 'nanoid'\n\n/**\n * Material Design 3 Select Option component.\n *\n * The `ui-option` component represents a selectable item within a `ui-select` dropdown.\n * It extends `UiListItem` to provide consistent styling and behavior with other list components.\n *\n * @slot - The option content (label, icon, etc.)\n * @slot start - Content to display at the start of the option (icon, avatar, etc.)\n * @slot end - Content to display at the end of the option\n * @slot supporting-text - Supporting text below the main content\n * @fires select - Dispatched when the option is selected. Contains `{ item: UiOption, value: string }` in detail\n *\n * @example\n * Basic option\n * ```html\n * <ui-option value=\"apple\">Apple</ui-option>\n * ```\n *\n * @example\n * Option with supporting text\n * ```html\n * <ui-option value=\"john\" lines=\"two\">\n * John Doe\n * <span slot=\"supporting-text\">john@example.com</span>\n * </ui-option>\n * ```\n */\nexport default class UiOption extends UiListItem {\n /**\n * The value associated with this option. Used to identify the option when selected.\n * This value is what gets set on the parent select element when this option is chosen.\n *\n * @example\n * ```html\n * <ui-option value=\"apple\">Apple</ui-option>\n * <ui-option value=\"banana\">Banana</ui-option>\n * ```\n */\n @property({ type: String, reflect: true }) accessor value: string | undefined\n\n /**\n * Whether this option is currently selected. This is typically managed automatically\n * by the parent select component, but can be set manually for styling purposes.\n *\n * @default false\n * @example\n * ```html\n * <ui-option value=\"apple\" selected>Apple</ui-option>\n * ```\n */\n @property({ type: Boolean, reflect: true }) accessor selected = false\n\n /**\n * Returns the text representation of this option for display purposes.\n * This method extracts and combines text content from all child nodes,\n * including special handling for ui-icon elements.\n *\n * @readonly\n * @returns {string} The rendered text value of the option\n * @example\n * ```javascript\n * const option = document.querySelector('ui-option');\n * console.log('Option text:', option.renderValue);\n * ```\n */\n get renderValue(): string {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])')\n if (!slot) return this.value || ''\n const nodes = slot.assignedNodes({ flatten: true })\n const content: string[] = []\n for (const node of nodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n content.push(node.textContent || '')\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as HTMLElement\n if (element.tagName.toLowerCase() === 'ui-icon') {\n content.push(element.getAttribute('icon') || '')\n } else {\n content.push(element.textContent || '')\n }\n }\n }\n return content.join(' ').trim() || this.value || ''\n }\n\n /**\n * Initializes the option when it's connected to the DOM. Sets up ARIA attributes\n * and generates a unique ID if one isn't provided.\n *\n * @protected\n */\n override connectedCallback(): void {\n super.connectedCallback()\n this.setAttribute('role', 'option')\n if (!this.id) {\n this.id = `option-${nanoid(6)}`\n }\n }\n\n /**\n * Handles property updates and triggers appropriate side effects.\n * Currently monitors the `selected` property to update selection state.\n *\n * @param {PropertyValues<this>} changedProperties - Map of changed properties\n * @protected\n */\n protected override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties)\n\n if (changedProperties.has('selected')) {\n this.updateSelectionState()\n }\n }\n\n /**\n * Updates the visual and accessibility state when selection changes.\n * Adds/removes CSS classes and ARIA attributes based on selection state.\n *\n * @protected\n * @example\n * ```javascript\n * // This is called automatically when the selected property changes\n * option.selected = true; // Will trigger updateSelectionState()\n * ```\n */\n protected updateSelectionState(): void {\n if (this.selected) {\n this.classList.add('selected')\n this.setAttribute('aria-selected', 'true')\n } else {\n this.classList.remove('selected')\n this.setAttribute('aria-selected', 'false')\n }\n }\n\n /**\n * Handles click events on the option. Prevents default behavior and dispatches\n * a custom 'select' event that the parent select component can listen to.\n *\n * @param {MouseEvent} e - The click event\n * @protected\n * @fires select - Custom event with option details in event.detail\n * @example\n * ```javascript\n * // Listen for option selection\n * option.addEventListener('select', (e) => {\n * console.log('Selected option:', e.detail.item);\n * console.log('Selected value:', e.detail.value);\n * });\n * ```\n */\n override handleClick(e: MouseEvent): void {\n e.preventDefault()\n if (this.disabled) {\n e.stopPropagation()\n return\n }\n\n // Let the parent handle the selection\n this.dispatchEvent(\n new CustomEvent('select', {\n detail: {\n item: this,\n value: this.value,\n },\n bubbles: true,\n composed: true,\n })\n )\n }\n\n /**\n * Renders the option's template. Creates the main structure with focus ring,\n * ripple effect, and content areas.\n *\n * @returns {TemplateResult} The rendered template\n * @protected\n */\n protected override render(): TemplateResult {\n const surfaceClasses = classMap({\n surface: true,\n selected: this.selected,\n })\n\n return html`\n ${this.renderFocusRing()} ${this.renderRipple()}\n <div class=\"${surfaceClasses}\">${this.renderStart()} ${this.renderBody()} ${this.renderEnd()}</div>\n `\n }\n\n /**\n * Renders the end section of the option, including the selection check icon\n * when the option is selected.\n */\n protected override renderEnd(): TemplateResult {\n return html`\n <div class=\"end\">\n ${this.selected ? html`<ui-icon icon=\"check\" class=\"selection-icon\"></ui-icon>` : ''}\n <slot name=\"end\" @slotchange=${this.handleSlotChange}></slot>\n <slot name=\"end-text\" class=\"trailing-supporting-text\"></slot>\n </div>\n `\n }\n}\n"]}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("lit").CSSResult;
2
+ export default _default;
3
+ //# sourceMappingURL=Option.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Option.styles.d.ts","sourceRoot":"","sources":["../../../../../src/md/select/internals/Option.styles.ts"],"names":[],"mappings":";AAEA,wBAwIC"}
@@ -0,0 +1,139 @@
1
+ import { css } from 'lit';
2
+ export default css `
3
+ :host {
4
+ display: block;
5
+ height: 56px;
6
+ outline: none;
7
+ cursor: default;
8
+ position: relative;
9
+
10
+ --md-focus-ring-shape-end-end: 0px;
11
+ --md-focus-ring-shape-end-start: 0px;
12
+ --md-focus-ring-shape-start-end: 0px;
13
+ --md-focus-ring-shape-start-start: 0px;
14
+
15
+ color: var(--md-sys-color-on-surface);
16
+ }
17
+
18
+ :host([disabled]) {
19
+ cursor: not-allowed;
20
+ }
21
+
22
+ :host([hidden]) {
23
+ display: none;
24
+ }
25
+
26
+ .surface {
27
+ height: inherit;
28
+ box-sizing: border-box;
29
+
30
+ display: flex;
31
+ align-items: center;
32
+ overflow: hidden;
33
+
34
+ padding: 8px 16px 8px 16px;
35
+ gap: 12px;
36
+ }
37
+
38
+ .surface.selected {
39
+ background-color: var(--md-sys-color-secondary-container);
40
+ color: var(--md-sys-color-on-secondary-container);
41
+ }
42
+
43
+ .ripple {
44
+ z-index: 3;
45
+ }
46
+
47
+ .headline {
48
+ font-family: var(--md-sys-typescale-body-large-font);
49
+ font-weight: var(--md-sys-typescale-body-large-weight);
50
+ font-size: var(--md-sys-typescale-body-large-size);
51
+ letter-spacing: var(--md-sys-typescale-body-large-tracking);
52
+ line-height: var(--md-sys-typescale-body-large-height);
53
+
54
+ overflow: hidden;
55
+ text-overflow: ellipsis;
56
+ white-space: nowrap;
57
+
58
+ display: flex;
59
+ align-items: center;
60
+ }
61
+
62
+ .supporting-text {
63
+ color: var(--md-sys-color-on-surface-variant);
64
+
65
+ font-family: var(--md-sys-typescale-body-medium-font);
66
+ font-weight: var(--md-sys-typescale-body-medium-weight);
67
+ font-size: var(--md-sys-typescale-body-medium-size);
68
+ letter-spacing: var(--md-sys-typescale-body-medium-tracking);
69
+ line-height: var(--md-sys-typescale-body-medium-height);
70
+
71
+ overflow: hidden;
72
+ }
73
+
74
+ .supporting-text ::slotted(*),
75
+ slot[name='end-text']::slotted(*) {
76
+ margin: 0;
77
+ padding: 0;
78
+ overflow: hidden;
79
+ }
80
+
81
+ slot[name='end-text']::slotted(*) {
82
+ margin-right: 8px;
83
+ margin-left: 16px;
84
+ }
85
+
86
+ :host slot[name='end']::slotted(*) {
87
+ color: var(--md-sys-color-on-surface-variant);
88
+ fill: var(--md-sys-color-on-surface-variant);
89
+ margin-left: 16px;
90
+ }
91
+
92
+ :host slot[name='start']::slotted(*) {
93
+ display: block;
94
+ margin-right: 16px;
95
+ }
96
+
97
+ :host([image='icon']) slot[name='start']::slotted(*) {
98
+ width: 24px;
99
+ height: 24px;
100
+ }
101
+
102
+ :host([image='avatar']) slot[name='start']::slotted(*) {
103
+ width: 40px;
104
+ height: 40px;
105
+ }
106
+
107
+ :host([image='image']) slot[name='start']::slotted(*) {
108
+ width: 56px;
109
+ height: 56px;
110
+ }
111
+
112
+ :host([image='video']) slot[name='start']::slotted(*) {
113
+ width: 114px;
114
+ height: 64px;
115
+ }
116
+
117
+ .body {
118
+ flex: 1;
119
+ overflow: hidden;
120
+ display: flex;
121
+ flex-direction: column;
122
+ }
123
+
124
+ .end {
125
+ display: flex;
126
+ align-items: center;
127
+ gap: 8px;
128
+ }
129
+
130
+ .selection-icon {
131
+ color: var(--md-sys-color-on-surface);
132
+ }
133
+
134
+ :host(.highlight) .surface {
135
+ background-color: var(--md-sys-color-tertiary-container);
136
+ color: var(--md-sys-color-on-tertiary-container);
137
+ }
138
+ `;
139
+ //# sourceMappingURL=Option.styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Option.styles.js","sourceRoot":"","sources":["../../../../../src/md/select/internals/Option.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,eAAe,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwIjB,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport default css`\n :host {\n display: block;\n height: 56px;\n outline: none;\n cursor: default;\n position: relative;\n\n --md-focus-ring-shape-end-end: 0px;\n --md-focus-ring-shape-end-start: 0px;\n --md-focus-ring-shape-start-end: 0px;\n --md-focus-ring-shape-start-start: 0px;\n\n color: var(--md-sys-color-on-surface);\n }\n\n :host([disabled]) {\n cursor: not-allowed;\n }\n\n :host([hidden]) {\n display: none;\n }\n\n .surface {\n height: inherit;\n box-sizing: border-box;\n\n display: flex;\n align-items: center;\n overflow: hidden;\n\n padding: 8px 16px 8px 16px;\n gap: 12px;\n }\n\n .surface.selected {\n background-color: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n\n .ripple {\n z-index: 3;\n }\n\n .headline {\n font-family: var(--md-sys-typescale-body-large-font);\n font-weight: var(--md-sys-typescale-body-large-weight);\n font-size: var(--md-sys-typescale-body-large-size);\n letter-spacing: var(--md-sys-typescale-body-large-tracking);\n line-height: var(--md-sys-typescale-body-large-height);\n\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n display: flex;\n align-items: center;\n }\n\n .supporting-text {\n color: var(--md-sys-color-on-surface-variant);\n\n font-family: var(--md-sys-typescale-body-medium-font);\n font-weight: var(--md-sys-typescale-body-medium-weight);\n font-size: var(--md-sys-typescale-body-medium-size);\n letter-spacing: var(--md-sys-typescale-body-medium-tracking);\n line-height: var(--md-sys-typescale-body-medium-height);\n\n overflow: hidden;\n }\n\n .supporting-text ::slotted(*),\n slot[name='end-text']::slotted(*) {\n margin: 0;\n padding: 0;\n overflow: hidden;\n }\n\n slot[name='end-text']::slotted(*) {\n margin-right: 8px;\n margin-left: 16px;\n }\n\n :host slot[name='end']::slotted(*) {\n color: var(--md-sys-color-on-surface-variant);\n fill: var(--md-sys-color-on-surface-variant);\n margin-left: 16px;\n }\n\n :host slot[name='start']::slotted(*) {\n display: block;\n margin-right: 16px;\n }\n\n :host([image='icon']) slot[name='start']::slotted(*) {\n width: 24px;\n height: 24px;\n }\n\n :host([image='avatar']) slot[name='start']::slotted(*) {\n width: 40px;\n height: 40px;\n }\n\n :host([image='image']) slot[name='start']::slotted(*) {\n width: 56px;\n height: 56px;\n }\n\n :host([image='video']) slot[name='start']::slotted(*) {\n width: 114px;\n height: 64px;\n }\n\n .body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .end {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .selection-icon {\n color: var(--md-sys-color-on-surface);\n }\n\n :host(.highlight) .surface {\n background-color: var(--md-sys-color-tertiary-container);\n color: var(--md-sys-color-on-tertiary-container);\n }\n`\n"]}