@oicl/openbridge-webcomponents 2.1.0-next.9 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/openbridge-webcomponents.bundle.js +23 -32
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +42 -42
- package/dist/components/alert-menu/alert-menu.d.ts +5 -5
- package/dist/components/alert-menu/alert-menu.js.map +1 -1
- package/dist/components/app-menu/app-menu.d.ts +5 -5
- package/dist/components/app-menu/app-menu.js.map +1 -1
- package/dist/components/brilliance-menu/brilliance-menu.d.ts +5 -5
- package/dist/components/brilliance-menu/brilliance-menu.js.map +1 -1
- package/dist/components/command-menu/command-menu.d.ts +5 -5
- package/dist/components/command-menu/command-menu.js.map +1 -1
- package/dist/components/context-menu-input/context-menu-input.d.ts +5 -5
- package/dist/components/context-menu-input/context-menu-input.js.map +1 -1
- package/dist/components/navigation-menu/navigation-menu.d.ts +5 -5
- package/dist/components/navigation-menu/navigation-menu.js.map +1 -1
- package/dist/components/slide-button/slide-button.d.ts.map +1 -1
- package/dist/components/slide-button/slide-button.js +1 -1
- package/dist/components/slide-button/slide-button.js.map +1 -1
- package/dist/components/start-stop-switch/start-stop-switch.d.ts.map +1 -1
- package/dist/components/start-stop-switch/start-stop-switch.js +3 -10
- package/dist/components/start-stop-switch/start-stop-switch.js.map +1 -1
- package/dist/components/system-menu/system-menu.d.ts +5 -5
- package/dist/components/system-menu/system-menu.js.map +1 -1
- package/dist/components/user-menu/user-menu.d.ts +5 -5
- package/dist/components/user-menu/user-menu.js.map +1 -1
- package/dist/internal/popover-controller.d.ts +4 -0
- package/dist/internal/popover-controller.d.ts.map +1 -1
- package/dist/internal/popover-controller.js +4 -0
- package/dist/internal/popover-controller.js.map +1 -1
- package/dist/navigation-instruments/readout/readout.css.js +5 -4
- package/dist/navigation-instruments/readout/readout.css.js.map +1 -1
- package/dist/navigation-instruments/readout/readout.d.ts +3 -4
- package/dist/navigation-instruments/readout/readout.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout.js +3 -4
- package/dist/navigation-instruments/readout/readout.js.map +1 -1
- package/dist/navigation-instruments/readout-list/readout-list.css.js +3 -5
- package/dist/navigation-instruments/readout-list/readout-list.css.js.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.css.js +4 -4
- package/dist/navigation-instruments/readout-list-item/readout-list-item.css.js.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts +8 -7
- package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js +4 -4
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js.map +1 -1
- package/dist/openbridge.css +389 -263
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-menu.js","names":[],"sources":["../../../src/components/system-menu/system-menu.ts"],"sourcesContent":["import {LitElement, TemplateResult, html, nothing, unsafeCSS} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport compentStyle from './system-menu.css?inline';\nimport {property} from 'lit/decorators.js';\nimport {localized, msg} from '@lit/localize';\nimport '../../icons/icon-chevron-right-google.js';\nimport '../../icons/icon-wifi2-google.js';\nimport '../icon-check-button/icon-check-button.js';\nimport '../../icons/icon-wifi2-off-google.js';\nimport '../../icons/icon-sound-muted.js';\nimport '../../icons/icon-sound.js';\nimport '../../icons/icon-com-mic-muted-google.js';\nimport '../../icons/icon-com-microphone.js';\nimport '../slider/slider.js';\nimport {ObcSliderValueEvent} from '../slider/slider.js';\nimport '../audio-output/audio-output.js';\nimport '../battery-icon/battery-icon.js';\nimport '../../icons/icon-settings-iec.js';\nimport '../icon-button/icon-button.js';\nimport {IconButtonVariant} from '../icon-button/icon-button.js';\nimport '../../icons/icon-chevron-left-google.js';\nimport '../radio/radio.js';\nimport '../toggle-switch/toggle-switch.js';\nimport '../navigation-item/navigation-item.js';\nimport '../accordion-item/accordion-item.js';\nimport '../button/button.js';\nimport '../scrollbar/scrollbar.js';\nimport {PopoverController} from '../../internal/popover-controller.js';\n\nexport interface WifiState {\n enabled: boolean;\n connected: boolean;\n networkName?: string;\n strength: number; // 0-100, 0 is no signal, 100 is full signal\n status: string; // Example: \"Connected, Secure\"\n networks?: {\n name: string;\n signalStrength: number; // 0-100, 0 is no signal, 100 is full signal\n }[];\n otherNetworks?: {\n name: string;\n signalStrength: number; // 0-100, 0 is no signal, 100 is full signal\n }[];\n}\n\nexport interface AudioState {\n muted: boolean;\n volume: number; // 0-100, 0 is muted, 100 is full volume\n outputs?: {\n name: string;\n }[];\n selectedOutput?: string;\n controlMode?: SystemMenuControlMode;\n}\n\nexport interface MicrophoneState {\n muted: boolean;\n currentLevel: number; // 0-100, 0 is no sound, 100 is full sound\n inputs?: {\n name: string;\n }[];\n selectedInput?: string;\n pushToTalk?: boolean;\n controlMode?: SystemMenuControlMode;\n}\n\nexport interface BatteryState {\n level: number; // percent, 0 empty to 100 full\n charging: boolean;\n poweredNotCharging?: boolean;\n notification?: boolean;\n batterySavingMode?: boolean; // undefined where the platform cannot report it\n hasUsageButton: boolean;\n modes?: {\n name: string;\n }[];\n selectedMode?: string;\n}\n\nexport enum SystemSubMenu {\n main = 'main',\n wifi = 'wifi',\n audio = 'audio',\n microphone = 'microphone',\n battery = 'battery',\n}\n\nexport enum SystemMenuControlMode {\n muteButton = 'mute-button',\n iconOnly = 'icon-only',\n hidden = 'hidden',\n}\n\nexport type VolumeChangeEvent = CustomEvent<number>;\n\n/**\n * @property softDismiss - Let the browser close this menu on its own: on a click outside it, on `Escape`, or when another menu opens. Leave it off to keep showing and hiding the menu yourself.\n * @property open - Whether the menu is showing.\n * @availableWhen open softDismiss==true\n * @fires wifi-click - When the Wi-Fi button is clicked\n * @fires audio-click - When the Audio button is clicked\n * @fires {VolumeChangeEvent} audio-volume-change - When the Audio volume is changed\n * @fires microphone-click - When the Microphone button is clicked\n * @fires push-to-talk-change - When the push-to-talk toggle is changed\n * @fires battery-usage-click - When the Battery usage button is clicked\n * @fires battery-saving-mode-change - When the Battery saving mode is changed\n * @fires battery-mode-change - When the Battery mode is changed\n * @fires wifi-network-change - When the Wi-Fi network is changed\n * @fires audio-output-change - When the Audio output is changed\n * @fires microphone-input-change - When the Microphone input is changed\n * @fires settings-click - When the Settings button is clicked\n * @fires to-sub-menu-click - When the sub menu is clicked\n * @fires wifi-options-click - When the Wi-Fi options are clicked\n * @fires wifi-disconnect-click - When the Wi-Fi disconnect is clicked\n * @slot battery-status - Custom battery status text (falls back to the built-in charging/battery label).\n * @fires {CustomEvent<void>} close - Fired when the menu closed on its own, from a click outside, `Escape`, or another menu opening. `open` is already `false` by the time it arrives.\n * @stable\n */\n@customElement('obc-system-menu')\n@localized()\nexport class ObcSystemMenu extends LitElement {\n @property({type: Boolean}) softDismiss = false;\n\n @property({type: Boolean}) open = false;\n\n protected readonly softDismissController = new PopoverController(this);\n\n @property({attribute: false}) wifiState: WifiState | undefined;\n @property({attribute: false}) audioState: AudioState | undefined;\n @property({attribute: false}) microphoneState: MicrophoneState | undefined;\n @property({attribute: false}) batteryState: BatteryState | undefined;\n @property({type: Boolean}) condensed: boolean = false;\n @property({type: Boolean}) showSettingsButton: boolean = false;\n @property({type: String}) activeSubMenu: SystemSubMenu = SystemSubMenu.main;\n @property({type: Boolean}) externalControl: boolean = false;\n @property({type: Boolean}) smallScreen: boolean = false;\n private get audioControlMode(): SystemMenuControlMode {\n return this.audioState?.controlMode ?? SystemMenuControlMode.muteButton;\n }\n\n private get microphoneControlMode(): SystemMenuControlMode {\n return (\n this.microphoneState?.controlMode ?? SystemMenuControlMode.muteButton\n );\n }\n\n private renderAudioControl() {\n if (!this.audioState) {\n return nothing;\n }\n\n if (this.audioControlMode === SystemMenuControlMode.hidden) {\n return nothing;\n }\n\n if (this.audioControlMode === SystemMenuControlMode.iconOnly) {\n return html`<div\n class=\"content-item-icon ${this.audioState.muted ? 'is-muted' : ''}\"\n role=\"img\"\n aria-label=${\n this.audioState.muted ? msg('Audio muted') : msg('Audio on')\n }\n >\n ${\n this.audioState.muted\n ? html`<obi-sound-muted></obi-sound-muted>`\n : html`<obi-sound></obi-sound>`\n }\n </div>`;\n }\n\n return html`<obc-icon-check-button\n class=\"content-item-btn\"\n .checked=${!this.audioState.muted}\n @icon-check-button-click=${this.handleAudioClick}\n >\n ${\n this.audioState.muted\n ? html`<obi-sound-muted slot=\"icon\"></obi-sound-muted>`\n : html`<obi-sound slot=\"icon\"></obi-sound>`\n }\n </obc-icon-check-button>`;\n }\n\n private renderMicrophoneControl(options?: {externalControl?: boolean}) {\n if (!this.microphoneState) {\n return nothing;\n }\n\n if (this.microphoneControlMode === SystemMenuControlMode.hidden) {\n return nothing;\n }\n\n if (this.microphoneControlMode === SystemMenuControlMode.iconOnly) {\n return html`<div\n class=\"content-item-icon ${\n this.microphoneState.muted ? 'is-muted' : ''\n }\"\n role=\"img\"\n aria-label=${\n this.microphoneState.muted\n ? msg('Microphone muted')\n : msg('Microphone on')\n }\n >\n ${\n this.microphoneState.muted\n ? html`<obi-com-mic-muted-google></obi-com-mic-muted-google>`\n : html`<obi-com-microphone></obi-com-microphone>`\n }\n </div>`;\n }\n\n return html`<obc-icon-check-button\n class=\"content-item-btn\"\n .checked=${!this.microphoneState.muted}\n ?externalControl=${options?.externalControl ?? false}\n @icon-check-button-click=${this.handleMicrophoneClick}\n >\n ${\n this.microphoneState.muted\n ? html`<obi-com-mic-muted-google\n slot=\"icon\"\n ></obi-com-mic-muted-google>`\n : html`<obi-com-microphone slot=\"icon\"></obi-com-microphone>`\n }\n </obc-icon-check-button>`;\n }\n\n private get effectiveSubMenu(): SystemSubMenu {\n if (this.smallScreen && this.activeSubMenu === SystemSubMenu.main) {\n return SystemSubMenu.wifi;\n }\n return this.activeSubMenu;\n }\n\n override render() {\n if (this.smallScreen) {\n return this.renderSmallScreen();\n }\n\n let content: (TemplateResult | symbol)[];\n switch (this.activeSubMenu) {\n case SystemSubMenu.main:\n content = [\n this.renderWifi(),\n this.renderAudio(),\n this.renderMicrophone(),\n this.renderBattery(),\n this.renderSettingsButton(),\n ];\n break;\n case SystemSubMenu.wifi:\n content = [\n this.renderSubMenuTitle(msg('Wi-Fi')),\n this.renderWifiSubMenuHeader(),\n this.renderWifMenuOptions(),\n this.renderSettingsButton(),\n ];\n break;\n case SystemSubMenu.audio:\n content = [\n this.renderSubMenuTitle(msg('Audio')),\n this.renderAudioSubMenuHeader(),\n this.renderAudioSubMenuOptions(),\n this.renderSettingsButton(),\n ];\n break;\n case SystemSubMenu.microphone:\n content = [\n this.renderSubMenuTitle(msg('Microphone')),\n this.renderMicrophoneSubMenuHeader(),\n this.renderMicrophoneSubMenuOptions(),\n this.renderSettingsButton(),\n ];\n break;\n case SystemSubMenu.battery:\n content = [\n this.renderSubMenuTitle(msg('Battery')),\n this.renderBatterySubMenuHeader(),\n this.renderBatterySubMenuOptions(),\n this.renderSettingsButton(),\n ];\n break;\n }\n return html`<div class=\"wrapper ${this.condensed ? 'condensed' : ''}\">\n ${content}\n </div> `;\n }\n\n private dispatchClickEvent(eventName: string) {\n this.dispatchEvent(new CustomEvent(eventName));\n }\n\n private handleWifiClick(event: CustomEvent<{checked: boolean}>) {\n event.stopPropagation();\n this.wifiState!.enabled = event.detail.checked;\n this.dispatchEvent(\n new CustomEvent('wifi-click', {detail: {enabled: event.detail.checked}})\n );\n }\n\n private handleAudioClick(event: CustomEvent) {\n event.stopPropagation();\n this.audioState!.muted = !event.detail.checked;\n this.dispatchEvent(\n new CustomEvent('audio-click', {detail: {muted: !event.detail.checked}})\n );\n }\n\n private handleAudioVolumeChange(event: ObcSliderValueEvent) {\n this.dispatchEvent(\n new CustomEvent('audio-volume-change', {detail: {volume: event.detail}})\n );\n }\n\n private handleToSubMenuClick(subMenu: SystemSubMenu) {\n if (!this.externalControl) {\n this.activeSubMenu = subMenu;\n }\n this.dispatchClickEvent('to-sub-menu-click');\n }\n\n private renderWifi() {\n if (!this.wifiState) {\n return nothing;\n }\n const showMoreButton =\n this.wifiState.networks && this.wifiState.networks.length > 0;\n const title = showMoreButton\n ? html`<button\n class=\"title-container\"\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.wifi)}\n >\n <div class=\"title\">${msg('Wi-Fi')}</div>\n <div class=\"icon-container\">\n <obi-chevron-right-google class=\"icon\"></obi-chevron-right-google>\n </div>\n </button>`\n : html`<div class=\"title-container\">\n <div class=\"title\">${msg('Wi-Fi')}</div>\n </div>`;\n return html`<div class=\"group\">\n ${this.condensed ? nothing : title}\n <div class=\"content-container\">\n <div class=\"action-container\">\n <obc-icon-check-button\n class=\"content-item-btn\"\n .checked=${!!this.wifiState.enabled}\n @icon-check-button-click=${this.handleWifiClick}\n >\n ${\n this.wifiState?.enabled\n ? html`<obi-wifi2-google slot=\"icon\"></obi-wifi2-google>`\n : html`<obi-wifi2-off-google\n slot=\"icon\"\n ></obi-wifi2-off-google>`\n }\n </obc-icon-check-button>\n <div\n class=\"content-item-value ${\n this.wifiState.enabled ? 'enabled' : 'disabled'\n }\"\n >\n ${this.wifiState?.networkName}\n </div>\n </div>\n ${\n this.condensed && showMoreButton\n ? html` <obc-icon-button\n .variant=${IconButtonVariant.flat}\n aria-label=${msg('Wi-Fi settings')}\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.wifi)}\n >\n <obi-chevron-right-google></obi-chevron-right-google>\n </obc-icon-button>`\n : nothing\n }\n </div>\n </div>`;\n }\n\n private renderAudio() {\n if (!this.audioState) {\n return nothing;\n }\n const showMoreButton =\n this.audioState.outputs && this.audioState.outputs.length > 0;\n\n const title = showMoreButton\n ? html`<button\n class=\"title-container\"\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.audio)}\n >\n <div class=\"title\">${msg('Audio')}</div>\n <div class=\"icon-container\">\n <obi-chevron-right-google class=\"icon\"></obi-chevron-right-google>\n </div>\n </button>`\n : html`<div class=\"title-container\">\n <div class=\"title\">${msg('Audio')}</div>\n </div>`;\n return html`<div class=\"group\">\n ${this.condensed ? nothing : title}\n <div class=\"content-container\">\n <div\n class=\"action-container ${\n this.audioControlMode === SystemMenuControlMode.hidden\n ? 'control-hidden'\n : ''\n }\"\n >\n ${this.renderAudioControl()}\n <obc-slider\n class=\"content-item-slider\"\n .value=${this.audioState.volume}\n @value=${this.handleAudioVolumeChange}\n ></obc-slider>\n </div>\n ${\n this.condensed && showMoreButton\n ? html` <obc-icon-button\n .variant=${IconButtonVariant.flat}\n aria-label=${msg('Audio settings')}\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.audio)}\n >\n <obi-chevron-right-google></obi-chevron-right-google>\n </obc-icon-button>`\n : nothing\n }\n </div>\n </div>`;\n }\n\n private renderMicrophone() {\n if (!this.microphoneState) {\n return nothing;\n }\n const hasInputs =\n this.microphoneState.inputs && this.microphoneState.inputs.length > 0;\n const hasPushToTalk = this.microphoneState.pushToTalk !== undefined;\n const showMoreButton = hasInputs || hasPushToTalk;\n\n const title = showMoreButton\n ? html`<button\n class=\"title-container\"\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.microphone)}\n >\n <div class=\"title\">${msg('Microphone')}</div>\n <div class=\"icon-container\">\n <obi-chevron-right-google class=\"icon\"></obi-chevron-right-google>\n </div>\n </button>`\n : html`<div class=\"title-container\">\n <div class=\"title\">${msg('Microphone')}</div>\n </div>`;\n return html`<div class=\"group\">\n ${this.condensed ? nothing : title}\n <div class=\"content-container\">\n <div\n class=\"action-container ${\n this.microphoneControlMode === SystemMenuControlMode.hidden\n ? 'control-hidden'\n : ''\n }\"\n >\n ${this.renderMicrophoneControl()}\n <div class=\"content-item-value\">\n <obc-audio-output\n .volume=${(this.microphoneState.currentLevel / 100) * 8}\n ></obc-audio-output>\n </div>\n </div>\n ${\n this.condensed && showMoreButton\n ? html` <obc-icon-button\n .variant=${IconButtonVariant.flat}\n aria-label=${msg('Microphone settings')}\n @click=${() =>\n this.handleToSubMenuClick(SystemSubMenu.microphone)}\n >\n <obi-chevron-right-google></obi-chevron-right-google>\n </obc-icon-button>`\n : nothing\n }\n </div>\n </div>`;\n }\n\n private renderBattery() {\n if (!this.batteryState) {\n return nothing;\n }\n const hasModes =\n this.batteryState.modes && this.batteryState.modes.length > 0;\n const hasUsageButton = this.batteryState.hasUsageButton;\n const hasBatterySavingMode =\n this.batteryState.batterySavingMode !== undefined;\n const showMoreButton = hasModes || hasUsageButton || hasBatterySavingMode;\n const title = showMoreButton\n ? html`<button\n class=\"title-container\"\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.battery)}\n >\n <div class=\"title\">${msg('Battery')}</div>\n <div class=\"icon-container\">\n <obi-chevron-right-google class=\"icon\"></obi-chevron-right-google>\n </div>\n </button>`\n : html`<div class=\"title-container\">\n <div class=\"title\">${msg('Battery')}</div>\n </div>`;\n const batteryStatus = this.batteryState.charging\n ? msg('Charging')\n : this.batteryState.poweredNotCharging\n ? msg('Powered & not charging')\n : msg('On battery');\n return html`<div class=\"group\">\n ${this.condensed ? nothing : title}\n <div class=\"content-container battery-container\">\n <div class=\"action-container\">\n <div class=\"battery\">\n <obc-battery-icon\n .level=${this.batteryState.level}\n .charging=${this.batteryState.charging}\n .poweredNotCharging=${\n this.batteryState.poweredNotCharging ?? false\n }\n .notification=${this.batteryState.notification ?? false}\n ></obc-battery-icon>\n <div class=\"percentage\">${this.batteryState.level}%</div>\n <div class=\"status\">\n <slot name=\"battery-status\">${batteryStatus}</slot>\n </div>\n </div>\n </div>\n ${\n this.condensed && showMoreButton\n ? html` <obc-icon-button\n .variant=${IconButtonVariant.flat}\n aria-label=${msg('Battery settings')}\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.battery)}\n >\n <obi-chevron-right-google></obi-chevron-right-google>\n </obc-icon-button>`\n : nothing\n }\n </div>\n </div>`;\n }\n\n private renderSettingsButton() {\n if (!this.showSettingsButton) {\n return nothing;\n }\n return html`<div class=\"group\">\n <button\n class=\"title-container settings\"\n @click=${() => this.dispatchClickEvent('settings-click')}\n >\n <div class=\"icon-container\">\n <obi-settings-iec class=\"icon\"></obi-settings-iec>\n </div>\n <div class=\"title\">${msg('Settings')}</div>\n </button>\n </div>`;\n }\n\n private renderSubMenuTitle(title: string) {\n return html`\n <div class=\"title-container sub-menu-title\">\n <obc-icon-button\n .variant=${IconButtonVariant.normal}\n aria-label=${msg('Back')}\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.main)}\n >\n <obi-chevron-left-google></obi-chevron-left-google>\n </obc-icon-button>\n <div class=\"title\">${title}</div>\n </div>\n `;\n }\n\n private renderWifiSubMenuHeader() {\n return html` <div class=\"sub-container\">\n <div class=\"row wifi-container\">\n <obi-wifi2-google class=\"icon large\"></obi-wifi2-google>\n <div class=\"title wifi-name\">${this.wifiState?.networkName}</div>\n <div class=\"wifi-status\">${this.wifiState?.status}</div>\n </div>\n <div class=\"row\">\n <obc-button\n @click=${() => this.dispatchClickEvent('wifi-options-click')}\n fullWidth\n >${msg('Options')}</obc-button\n >\n ${\n this.wifiState?.connected\n ? html`<obc-button\n @click=${() => this.dispatchClickEvent('wifi-disconnect-click')}\n fullWidth\n >${msg('Disconnect')}</obc-button\n >`\n : nothing\n }\n </div>\n </div>`;\n }\n\n private renderAudioSubMenuHeader() {\n return html` <div class=\"sub-container\">\n <div class=\"row\">\n ${\n this.audioState?.muted\n ? html`<obi-sound-muted class=\"icon large off\"></obi-sound-muted>`\n : html`<obi-sound class=\"icon large\"></obi-sound>`\n }\n <div class=\"title\">\n ${this.audioState?.volume}\n <div class=\"unit\">%</div>\n </div>\n </div>\n <div class=\"row\">\n ${this.renderAudioControl()}\n <obc-slider\n class=\"content-item-slider\"\n .value=${this.audioState?.volume ?? 0}\n @value=${this.handleAudioVolumeChange}\n ></obc-slider>\n </div>\n </div>`;\n }\n\n private handleMicrophoneClick(event: CustomEvent<{checked: boolean}>) {\n event.stopPropagation();\n this.microphoneState!.muted = !event.detail.checked;\n this.dispatchEvent(\n new CustomEvent('microphone-click', {\n detail: {muted: !event.detail.checked},\n })\n );\n }\n\n private handlePushToTalkClick(event: InputEvent) {\n this.dispatchEvent(\n new CustomEvent('push-to-talk-change', {\n detail: {pushToTalk: (event.target as HTMLInputElement).checked},\n })\n );\n }\n\n private handleBatterySavingModeClick(event: CustomEvent<{checked: boolean}>) {\n this.dispatchEvent(\n new CustomEvent('battery-saving-mode-change', {\n detail: {batterySavingMode: event.detail.checked},\n })\n );\n }\n\n private renderMicrophoneSubMenuHeader() {\n const isNoMuteButton =\n this.microphoneControlMode === SystemMenuControlMode.iconOnly ||\n this.microphoneControlMode === SystemMenuControlMode.hidden;\n return html` <div class=\"sub-container\">\n <div class=\"row\">\n ${\n this.microphoneState?.muted\n ? html`<obi-com-mic-muted-google\n class=\"icon large\"\n ></obi-com-mic-muted-google>`\n : html`<obi-com-microphone class=\"icon large\"></obi-com-microphone>`\n }\n <div class=\"title\">\n ${this.microphoneState?.currentLevel}\n <div class=\"unit\">dB</div>\n </div>\n </div>\n <div class=\"row ${isNoMuteButton ? 'no-mute-button' : ''}\">\n ${this.renderMicrophoneControl({externalControl: true})}\n <obc-audio-output\n .volume=${((this.microphoneState?.currentLevel ?? 0) / 100) * 8}\n ></obc-audio-output>\n </div>\n ${\n this.microphoneState?.pushToTalk !== undefined\n ? html`<div class=\"row no-padding\">\n <obc-toggle-switch\n .checked=${this.microphoneState?.pushToTalk}\n @input=${this.handlePushToTalkClick}\n label=${msg('Push to talk')}\n ></obc-toggle-switch>\n </div>`\n : nothing\n }\n </div>`;\n }\n\n private handleBatteryUsageClick() {\n this.dispatchEvent(\n new CustomEvent('battery-usage-click', {detail: {usage: true}})\n );\n }\n\n private renderBatterySubMenuHeader() {\n if (!this.batteryState) {\n return nothing;\n }\n return html` <div class=\"sub-container\">\n <div class=\"row\">\n <obc-battery-icon\n class=\"icon large\"\n .level=${this.batteryState.level}\n .charging=${this.batteryState.charging}\n .poweredNotCharging=${this.batteryState.poweredNotCharging ?? false}\n .notification=${this.batteryState.notification ?? false}\n ></obc-battery-icon>\n <div class=\"title\">\n ${this.batteryState.level}\n <div class=\"unit\">%</div>\n </div>\n </div>\n <div class=\"row\">\n <obc-button @click=${this.handleBatteryUsageClick} fullWidth>\n ${msg('Usage')}\n </obc-button>\n </div>\n ${\n this.batteryState.batterySavingMode !== undefined\n ? html`<div class=\"row no-padding\">\n <obc-toggle-switch\n .checked=${this.batteryState.batterySavingMode}\n @toggle-switch-click=${this.handleBatterySavingModeClick}\n label=${msg('Battery saving mode')}\n ></obc-toggle-switch>\n </div>`\n : nothing\n }\n </div>`;\n }\n\n private handleWifiNetworkClick(name: string) {\n this.dispatchEvent(\n new CustomEvent('wifi-network-change', {detail: {network: name}})\n );\n }\n\n private renderWifMenuOptions() {\n if (this.wifiState?.networks?.length === 0) {\n return nothing;\n }\n return html`\n <div class=\"sub-container sub-container-title\">\n <div class=\"row title2\">${msg('Wi-Fi')}</div>\n </div>\n <div class=\"sub-container\">\n <div class=\"row navigation-items\">\n ${this.wifiState?.networks?.map(\n (option) => html`\n <obc-navigation-item\n .label=${option.name}\n .checked=${option.name === this.wifiState?.networkName}\n @click=${() => this.handleWifiNetworkClick(option.name)}\n hasIcon\n >\n <obi-wifi2-google slot=\"icon\"></obi-wifi2-google>\n </obc-navigation-item>\n `\n )}\n <obc-accordion-item title=${msg('Other networks')}>\n <div slot=\"expanded-content\">\n ${this.wifiState?.otherNetworks?.map(\n (option) => html`\n <obc-navigation-item\n .label=${option.name}\n .checked=${option.name === this.wifiState?.networkName}\n @click=${() => this.handleWifiNetworkClick(option.name)}\n hasIcon\n >\n <obi-wifi2-google slot=\"icon\"></obi-wifi2-google>\n </obc-navigation-item>\n `\n )}\n </div>\n </obc-accordion-item>\n </div>\n </div>\n `;\n }\n\n private handleAudioOutputClick(name: string) {\n this.dispatchEvent(\n new CustomEvent('audio-output-change', {detail: {output: name}})\n );\n }\n\n private handleMicrophoneInputClick(name: string) {\n this.dispatchEvent(\n new CustomEvent('microphone-input-change', {detail: {input: name}})\n );\n }\n\n private handleBatteryModeClick(name: string) {\n this.dispatchEvent(\n new CustomEvent('battery-mode-change', {detail: {mode: name}})\n );\n }\n\n private renderAudioSubMenuOptions() {\n return this.renderSubMenuOptions(\n msg('Output'),\n this.audioState?.outputs ?? [],\n this.audioState?.selectedOutput ?? '',\n (name: string) => this.handleAudioOutputClick(name)\n );\n }\n\n private renderMicrophoneSubMenuOptions() {\n return this.renderSubMenuOptions(\n msg('Input'),\n this.microphoneState?.inputs ?? [],\n this.microphoneState?.selectedInput ?? '',\n (name: string) => this.handleMicrophoneInputClick(name)\n );\n }\n\n private renderBatterySubMenuOptions() {\n return this.renderSubMenuOptions(\n msg('Mode'),\n this.batteryState?.modes ?? [],\n this.batteryState?.selectedMode ?? '',\n (name: string) => this.handleBatteryModeClick(name)\n );\n }\n\n private renderSubMenuOptions(\n title: string,\n options: {name: string}[],\n selectedOption: string,\n handleOptionClick: (name: string) => void\n ) {\n if (options.length === 0) {\n return nothing;\n }\n return html`\n <div class=\"sub-container sub-container-title\">\n <div class=\"row title2\">${title}</div>\n </div>\n <div class=\"sub-container\">\n <div class=\"row radio\">\n ${options.map(\n (option) => html`\n <obc-radio\n .name=${title}\n .label=${option.name}\n .checked=${option.name === selectedOption}\n @change=${() => handleOptionClick(option.name)}\n ></obc-radio>\n `\n )}\n </div>\n </div>\n `;\n }\n\n // --- Small screen methods ---\n\n private renderSmallScreen() {\n const activeTab = this.effectiveSubMenu;\n let content: TemplateResult | symbol = nothing;\n switch (activeTab) {\n case SystemSubMenu.wifi:\n content = this.renderSmallScreenWifi();\n break;\n case SystemSubMenu.audio:\n content = this.renderSmallScreenAudio();\n break;\n case SystemSubMenu.microphone:\n content = this.renderSmallScreenMicrophone();\n break;\n case SystemSubMenu.battery:\n content = this.renderSmallScreenBattery();\n break;\n }\n return html`<div class=\"wrapper small-screen\">\n <div class=\"small-screen-content\">${content}</div>\n ${this.renderMenuBar(activeTab)}\n </div>`;\n }\n\n private handleSmallScreenWifiToggle(event: InputEvent) {\n const enabled = (event.target as HTMLInputElement).checked;\n this.dispatchEvent(new CustomEvent('wifi-click', {detail: {enabled}}));\n }\n\n private renderSmallScreenWifi() {\n if (!this.wifiState) {\n return nothing;\n }\n return html`\n <div class=\"small-screen-header\">\n <div class=\"small-screen-title-row\">\n <span>${msg('Wi-Fi')}</span>\n <obc-toggle-switch\n .checked=${this.wifiState.enabled}\n @input=${this.handleSmallScreenWifiToggle}\n ></obc-toggle-switch>\n </div>\n </div>\n <div class=\"small-screen-divider\"></div>\n <obc-scrollbar class=\"small-screen-options\">\n <div class=\"small-screen-options-content\">\n ${this.wifiState.networks?.map(\n (network) => html`\n <obc-navigation-item\n .label=${network.name}\n .checked=${network.name === this.wifiState?.networkName}\n @click=${() => this.handleWifiNetworkClick(network.name)}\n hasIcon\n >\n <obi-wifi2-google slot=\"icon\"></obi-wifi2-google>\n </obc-navigation-item>\n `\n )}\n </div>\n </obc-scrollbar>\n `;\n }\n\n private renderSmallScreenAudio() {\n if (!this.audioState) {\n return nothing;\n }\n return html`\n <div class=\"small-screen-header\">\n <div class=\"small-screen-title-row\">\n <span>${msg('Audio')}</span>\n </div>\n <div class=\"small-screen-controls-row\">\n ${this.renderAudioControl()}\n <div class=\"small-screen-slider-container\">\n <obc-slider\n class=\"small-screen-slider\"\n .value=${this.audioState.volume}\n @value=${this.handleAudioVolumeChange}\n ></obc-slider>\n <span class=\"small-screen-volume-label\"\n >${this.audioState.volume}%</span\n >\n </div>\n </div>\n </div>\n <div class=\"small-screen-divider\"></div>\n <obc-scrollbar class=\"small-screen-options\">\n <div class=\"small-screen-options-content\">\n ${(this.audioState.outputs ?? []).map(\n (output) => html`\n <obc-radio\n name=\"output\"\n .label=${output.name}\n .checked=${output.name === this.audioState?.selectedOutput}\n @change=${() => this.handleAudioOutputClick(output.name)}\n ></obc-radio>\n `\n )}\n </div>\n </obc-scrollbar>\n `;\n }\n\n private renderSmallScreenMicrophone() {\n if (!this.microphoneState) {\n return nothing;\n }\n const isNoMuteButton =\n this.microphoneControlMode === SystemMenuControlMode.iconOnly ||\n this.microphoneControlMode === SystemMenuControlMode.hidden;\n return html`\n <div class=\"small-screen-header\">\n <div class=\"small-screen-title-row\">\n <span>${msg('Microphone')}</span>\n </div>\n <div\n class=\"small-screen-controls-row ${\n isNoMuteButton ? 'no-mute-button' : ''\n }\"\n >\n ${this.renderMicrophoneControl()}\n <obc-audio-output\n class=\"small-screen-audio-output\"\n .volume=${(this.microphoneState.currentLevel / 100) * 8}\n ></obc-audio-output>\n </div>\n ${\n this.microphoneState.pushToTalk !== undefined\n ? html`<div class=\"small-screen-toggle-row\">\n <obc-toggle-switch\n .checked=${this.microphoneState.pushToTalk}\n @input=${this.handlePushToTalkClick}\n label=${msg('Push to talk')}\n ></obc-toggle-switch>\n </div>`\n : nothing\n }\n </div>\n <div class=\"small-screen-divider\"></div>\n <obc-scrollbar class=\"small-screen-options\">\n <div class=\"small-screen-options-content\">\n ${(this.microphoneState.inputs ?? []).map(\n (input) => html`\n <obc-radio\n name=\"input\"\n .label=${input.name}\n .checked=${input.name === this.microphoneState?.selectedInput}\n @change=${() => this.handleMicrophoneInputClick(input.name)}\n ></obc-radio>\n `\n )}\n </div>\n </obc-scrollbar>\n `;\n }\n\n private renderSmallScreenBattery() {\n if (!this.batteryState) {\n return nothing;\n }\n return html`\n <div class=\"small-screen-header\">\n <div class=\"small-screen-title-row\">\n <span>${msg('Battery')}</span>\n <div class=\"small-screen-battery-info\">\n <obc-battery-icon\n .level=${this.batteryState.level}\n .charging=${this.batteryState.charging}\n .poweredNotCharging=${\n this.batteryState.poweredNotCharging ?? false\n }\n .notification=${this.batteryState.notification ?? false}\n ></obc-battery-icon>\n <span class=\"small-screen-battery-level\"\n >${this.batteryState.level}%</span\n >\n </div>\n </div>\n ${\n this.batteryState.hasUsageButton\n ? html`<div class=\"small-screen-button-row\">\n <obc-button @click=${this.handleBatteryUsageClick} fullWidth>\n ${msg('Usage')}\n </obc-button>\n </div>`\n : nothing\n }\n ${\n this.batteryState.batterySavingMode !== undefined\n ? html`<div class=\"small-screen-toggle-row\">\n <obc-toggle-switch\n .checked=${this.batteryState.batterySavingMode}\n @toggle-switch-click=${this.handleBatterySavingModeClick}\n label=${msg('Battery saving mode')}\n ></obc-toggle-switch>\n </div>`\n : nothing\n }\n </div>\n <div class=\"small-screen-divider\"></div>\n <obc-scrollbar class=\"small-screen-options\">\n <div class=\"small-screen-options-content\">\n ${(this.batteryState.modes ?? []).map(\n (mode) => html`\n <obc-radio\n name=\"mode\"\n .label=${mode.name}\n .checked=${mode.name === this.batteryState?.selectedMode}\n @change=${() => this.handleBatteryModeClick(mode.name)}\n ></obc-radio>\n `\n )}\n </div>\n </obc-scrollbar>\n `;\n }\n\n private renderMenuBarButton(\n subMenu: SystemSubMenu,\n activeTab: SystemSubMenu,\n label: string,\n icon: TemplateResult\n ) {\n return html`<button\n class=${activeTab === subMenu ? 'active' : ''}\n title=${label}\n @click=${() => this.handleToSubMenuClick(subMenu)}\n >\n ${icon}\n </button>`;\n }\n\n private renderMenuBar(activeTab: SystemSubMenu) {\n return html`\n <div class=\"menu-bar\">\n ${\n this.wifiState\n ? this.renderMenuBarButton(\n SystemSubMenu.wifi,\n activeTab,\n msg('Wi-Fi'),\n html`<obi-wifi2-google class=\"tab-icon\"></obi-wifi2-google>`\n )\n : nothing\n }\n ${\n this.audioState\n ? this.renderMenuBarButton(\n SystemSubMenu.audio,\n activeTab,\n msg('Audio'),\n html`<obi-sound class=\"tab-icon\"></obi-sound>`\n )\n : nothing\n }\n ${\n this.microphoneState\n ? this.renderMenuBarButton(\n SystemSubMenu.microphone,\n activeTab,\n msg('Microphone'),\n html`<obi-com-microphone class=\"tab-icon\"></obi-com-microphone>`\n )\n : nothing\n }\n ${\n this.batteryState\n ? this.renderMenuBarButton(\n SystemSubMenu.battery,\n activeTab,\n msg('Battery'),\n html`<obc-battery-icon\n class=\"tab-icon\"\n .level=${this.batteryState.level}\n .charging=${this.batteryState.charging}\n .poweredNotCharging=${\n this.batteryState.poweredNotCharging ?? false\n }\n .notification=${this.batteryState.notification ?? false}\n ></obc-battery-icon>`\n )\n : nothing\n }\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"system-menu.js","names":[],"sources":["../../../src/components/system-menu/system-menu.ts"],"sourcesContent":["import {LitElement, TemplateResult, html, nothing, unsafeCSS} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport compentStyle from './system-menu.css?inline';\nimport {property} from 'lit/decorators.js';\nimport {localized, msg} from '@lit/localize';\nimport '../../icons/icon-chevron-right-google.js';\nimport '../../icons/icon-wifi2-google.js';\nimport '../icon-check-button/icon-check-button.js';\nimport '../../icons/icon-wifi2-off-google.js';\nimport '../../icons/icon-sound-muted.js';\nimport '../../icons/icon-sound.js';\nimport '../../icons/icon-com-mic-muted-google.js';\nimport '../../icons/icon-com-microphone.js';\nimport '../slider/slider.js';\nimport {ObcSliderValueEvent} from '../slider/slider.js';\nimport '../audio-output/audio-output.js';\nimport '../battery-icon/battery-icon.js';\nimport '../../icons/icon-settings-iec.js';\nimport '../icon-button/icon-button.js';\nimport {IconButtonVariant} from '../icon-button/icon-button.js';\nimport '../../icons/icon-chevron-left-google.js';\nimport '../radio/radio.js';\nimport '../toggle-switch/toggle-switch.js';\nimport '../navigation-item/navigation-item.js';\nimport '../accordion-item/accordion-item.js';\nimport '../button/button.js';\nimport '../scrollbar/scrollbar.js';\nimport {PopoverController} from '../../internal/popover-controller.js';\n\nexport interface WifiState {\n enabled: boolean;\n connected: boolean;\n networkName?: string;\n strength: number; // 0-100, 0 is no signal, 100 is full signal\n status: string; // Example: \"Connected, Secure\"\n networks?: {\n name: string;\n signalStrength: number; // 0-100, 0 is no signal, 100 is full signal\n }[];\n otherNetworks?: {\n name: string;\n signalStrength: number; // 0-100, 0 is no signal, 100 is full signal\n }[];\n}\n\nexport interface AudioState {\n muted: boolean;\n volume: number; // 0-100, 0 is muted, 100 is full volume\n outputs?: {\n name: string;\n }[];\n selectedOutput?: string;\n controlMode?: SystemMenuControlMode;\n}\n\nexport interface MicrophoneState {\n muted: boolean;\n currentLevel: number; // 0-100, 0 is no sound, 100 is full sound\n inputs?: {\n name: string;\n }[];\n selectedInput?: string;\n pushToTalk?: boolean;\n controlMode?: SystemMenuControlMode;\n}\n\nexport interface BatteryState {\n level: number; // percent, 0 empty to 100 full\n charging: boolean;\n poweredNotCharging?: boolean;\n notification?: boolean;\n batterySavingMode?: boolean; // undefined where the platform cannot report it\n hasUsageButton: boolean;\n modes?: {\n name: string;\n }[];\n selectedMode?: string;\n}\n\nexport enum SystemSubMenu {\n main = 'main',\n wifi = 'wifi',\n audio = 'audio',\n microphone = 'microphone',\n battery = 'battery',\n}\n\nexport enum SystemMenuControlMode {\n muteButton = 'mute-button',\n iconOnly = 'icon-only',\n hidden = 'hidden',\n}\n\nexport type VolumeChangeEvent = CustomEvent<number>;\n\n/**\n * @property softDismiss - Lets the menu close itself on a click outside it, on `Escape`, or when another menu opens. The page is covered while the menu is open, so the closing click reaches nothing there; only the top bar's strip stays clickable, which is how its buttons switch or close menus in one click. Wire it with three bindings: set `softDismiss`, bind `open` to a flag you keep, and reset that flag on `close`. The button that opens the menu needs no wiring of its own: flip the flag from its click, or from the button event of `obc-top-bar` or `obc-integration-bar`. The user menu's *Soft Dismiss From A Bar Button* story shows that wiring, the brilliance menu's *Soft Dismiss* story the one for a button you hold yourself (`bindPopoverTrigger`), and the vue demo runs its top bar this way. Leave it off to show and hide the menu yourself.\n * @property open - Whether the menu is showing. Bind it to a flag you keep rather than toggling it from the menu's own value: when the menu closes itself, `open` is written back to `false` before the button's click reaches your handler, so `menu.open = !menu.open` gets out of step. Reset the flag on `close`.\n * @availableWhen open softDismiss==true\n * @fires wifi-click - When the Wi-Fi button is clicked\n * @fires audio-click - When the Audio button is clicked\n * @fires {VolumeChangeEvent} audio-volume-change - When the Audio volume is changed\n * @fires microphone-click - When the Microphone button is clicked\n * @fires push-to-talk-change - When the push-to-talk toggle is changed\n * @fires battery-usage-click - When the Battery usage button is clicked\n * @fires battery-saving-mode-change - When the Battery saving mode is changed\n * @fires battery-mode-change - When the Battery mode is changed\n * @fires wifi-network-change - When the Wi-Fi network is changed\n * @fires audio-output-change - When the Audio output is changed\n * @fires microphone-input-change - When the Microphone input is changed\n * @fires settings-click - When the Settings button is clicked\n * @fires to-sub-menu-click - When the sub menu is clicked\n * @fires wifi-options-click - When the Wi-Fi options are clicked\n * @fires wifi-disconnect-click - When the Wi-Fi disconnect is clicked\n * @slot battery-status - Custom battery status text (falls back to the built-in charging/battery label).\n * @fires {CustomEvent<void>} close - Fired when the menu closed on its own, from a click outside, `Escape`, or another menu opening. `open` is already `false` by the time it arrives; reset the flag you bind to `open` here, or the next click on the button finds it still set and asks a closed menu to close.\n * @stable\n */\n@customElement('obc-system-menu')\n@localized()\nexport class ObcSystemMenu extends LitElement {\n @property({type: Boolean}) softDismiss = false;\n\n @property({type: Boolean}) open = false;\n\n protected readonly softDismissController = new PopoverController(this);\n\n @property({attribute: false}) wifiState: WifiState | undefined;\n @property({attribute: false}) audioState: AudioState | undefined;\n @property({attribute: false}) microphoneState: MicrophoneState | undefined;\n @property({attribute: false}) batteryState: BatteryState | undefined;\n @property({type: Boolean}) condensed: boolean = false;\n @property({type: Boolean}) showSettingsButton: boolean = false;\n @property({type: String}) activeSubMenu: SystemSubMenu = SystemSubMenu.main;\n @property({type: Boolean}) externalControl: boolean = false;\n @property({type: Boolean}) smallScreen: boolean = false;\n private get audioControlMode(): SystemMenuControlMode {\n return this.audioState?.controlMode ?? SystemMenuControlMode.muteButton;\n }\n\n private get microphoneControlMode(): SystemMenuControlMode {\n return (\n this.microphoneState?.controlMode ?? SystemMenuControlMode.muteButton\n );\n }\n\n private renderAudioControl() {\n if (!this.audioState) {\n return nothing;\n }\n\n if (this.audioControlMode === SystemMenuControlMode.hidden) {\n return nothing;\n }\n\n if (this.audioControlMode === SystemMenuControlMode.iconOnly) {\n return html`<div\n class=\"content-item-icon ${this.audioState.muted ? 'is-muted' : ''}\"\n role=\"img\"\n aria-label=${\n this.audioState.muted ? msg('Audio muted') : msg('Audio on')\n }\n >\n ${\n this.audioState.muted\n ? html`<obi-sound-muted></obi-sound-muted>`\n : html`<obi-sound></obi-sound>`\n }\n </div>`;\n }\n\n return html`<obc-icon-check-button\n class=\"content-item-btn\"\n .checked=${!this.audioState.muted}\n @icon-check-button-click=${this.handleAudioClick}\n >\n ${\n this.audioState.muted\n ? html`<obi-sound-muted slot=\"icon\"></obi-sound-muted>`\n : html`<obi-sound slot=\"icon\"></obi-sound>`\n }\n </obc-icon-check-button>`;\n }\n\n private renderMicrophoneControl(options?: {externalControl?: boolean}) {\n if (!this.microphoneState) {\n return nothing;\n }\n\n if (this.microphoneControlMode === SystemMenuControlMode.hidden) {\n return nothing;\n }\n\n if (this.microphoneControlMode === SystemMenuControlMode.iconOnly) {\n return html`<div\n class=\"content-item-icon ${\n this.microphoneState.muted ? 'is-muted' : ''\n }\"\n role=\"img\"\n aria-label=${\n this.microphoneState.muted\n ? msg('Microphone muted')\n : msg('Microphone on')\n }\n >\n ${\n this.microphoneState.muted\n ? html`<obi-com-mic-muted-google></obi-com-mic-muted-google>`\n : html`<obi-com-microphone></obi-com-microphone>`\n }\n </div>`;\n }\n\n return html`<obc-icon-check-button\n class=\"content-item-btn\"\n .checked=${!this.microphoneState.muted}\n ?externalControl=${options?.externalControl ?? false}\n @icon-check-button-click=${this.handleMicrophoneClick}\n >\n ${\n this.microphoneState.muted\n ? html`<obi-com-mic-muted-google\n slot=\"icon\"\n ></obi-com-mic-muted-google>`\n : html`<obi-com-microphone slot=\"icon\"></obi-com-microphone>`\n }\n </obc-icon-check-button>`;\n }\n\n private get effectiveSubMenu(): SystemSubMenu {\n if (this.smallScreen && this.activeSubMenu === SystemSubMenu.main) {\n return SystemSubMenu.wifi;\n }\n return this.activeSubMenu;\n }\n\n override render() {\n if (this.smallScreen) {\n return this.renderSmallScreen();\n }\n\n let content: (TemplateResult | symbol)[];\n switch (this.activeSubMenu) {\n case SystemSubMenu.main:\n content = [\n this.renderWifi(),\n this.renderAudio(),\n this.renderMicrophone(),\n this.renderBattery(),\n this.renderSettingsButton(),\n ];\n break;\n case SystemSubMenu.wifi:\n content = [\n this.renderSubMenuTitle(msg('Wi-Fi')),\n this.renderWifiSubMenuHeader(),\n this.renderWifMenuOptions(),\n this.renderSettingsButton(),\n ];\n break;\n case SystemSubMenu.audio:\n content = [\n this.renderSubMenuTitle(msg('Audio')),\n this.renderAudioSubMenuHeader(),\n this.renderAudioSubMenuOptions(),\n this.renderSettingsButton(),\n ];\n break;\n case SystemSubMenu.microphone:\n content = [\n this.renderSubMenuTitle(msg('Microphone')),\n this.renderMicrophoneSubMenuHeader(),\n this.renderMicrophoneSubMenuOptions(),\n this.renderSettingsButton(),\n ];\n break;\n case SystemSubMenu.battery:\n content = [\n this.renderSubMenuTitle(msg('Battery')),\n this.renderBatterySubMenuHeader(),\n this.renderBatterySubMenuOptions(),\n this.renderSettingsButton(),\n ];\n break;\n }\n return html`<div class=\"wrapper ${this.condensed ? 'condensed' : ''}\">\n ${content}\n </div> `;\n }\n\n private dispatchClickEvent(eventName: string) {\n this.dispatchEvent(new CustomEvent(eventName));\n }\n\n private handleWifiClick(event: CustomEvent<{checked: boolean}>) {\n event.stopPropagation();\n this.wifiState!.enabled = event.detail.checked;\n this.dispatchEvent(\n new CustomEvent('wifi-click', {detail: {enabled: event.detail.checked}})\n );\n }\n\n private handleAudioClick(event: CustomEvent) {\n event.stopPropagation();\n this.audioState!.muted = !event.detail.checked;\n this.dispatchEvent(\n new CustomEvent('audio-click', {detail: {muted: !event.detail.checked}})\n );\n }\n\n private handleAudioVolumeChange(event: ObcSliderValueEvent) {\n this.dispatchEvent(\n new CustomEvent('audio-volume-change', {detail: {volume: event.detail}})\n );\n }\n\n private handleToSubMenuClick(subMenu: SystemSubMenu) {\n if (!this.externalControl) {\n this.activeSubMenu = subMenu;\n }\n this.dispatchClickEvent('to-sub-menu-click');\n }\n\n private renderWifi() {\n if (!this.wifiState) {\n return nothing;\n }\n const showMoreButton =\n this.wifiState.networks && this.wifiState.networks.length > 0;\n const title = showMoreButton\n ? html`<button\n class=\"title-container\"\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.wifi)}\n >\n <div class=\"title\">${msg('Wi-Fi')}</div>\n <div class=\"icon-container\">\n <obi-chevron-right-google class=\"icon\"></obi-chevron-right-google>\n </div>\n </button>`\n : html`<div class=\"title-container\">\n <div class=\"title\">${msg('Wi-Fi')}</div>\n </div>`;\n return html`<div class=\"group\">\n ${this.condensed ? nothing : title}\n <div class=\"content-container\">\n <div class=\"action-container\">\n <obc-icon-check-button\n class=\"content-item-btn\"\n .checked=${!!this.wifiState.enabled}\n @icon-check-button-click=${this.handleWifiClick}\n >\n ${\n this.wifiState?.enabled\n ? html`<obi-wifi2-google slot=\"icon\"></obi-wifi2-google>`\n : html`<obi-wifi2-off-google\n slot=\"icon\"\n ></obi-wifi2-off-google>`\n }\n </obc-icon-check-button>\n <div\n class=\"content-item-value ${\n this.wifiState.enabled ? 'enabled' : 'disabled'\n }\"\n >\n ${this.wifiState?.networkName}\n </div>\n </div>\n ${\n this.condensed && showMoreButton\n ? html` <obc-icon-button\n .variant=${IconButtonVariant.flat}\n aria-label=${msg('Wi-Fi settings')}\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.wifi)}\n >\n <obi-chevron-right-google></obi-chevron-right-google>\n </obc-icon-button>`\n : nothing\n }\n </div>\n </div>`;\n }\n\n private renderAudio() {\n if (!this.audioState) {\n return nothing;\n }\n const showMoreButton =\n this.audioState.outputs && this.audioState.outputs.length > 0;\n\n const title = showMoreButton\n ? html`<button\n class=\"title-container\"\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.audio)}\n >\n <div class=\"title\">${msg('Audio')}</div>\n <div class=\"icon-container\">\n <obi-chevron-right-google class=\"icon\"></obi-chevron-right-google>\n </div>\n </button>`\n : html`<div class=\"title-container\">\n <div class=\"title\">${msg('Audio')}</div>\n </div>`;\n return html`<div class=\"group\">\n ${this.condensed ? nothing : title}\n <div class=\"content-container\">\n <div\n class=\"action-container ${\n this.audioControlMode === SystemMenuControlMode.hidden\n ? 'control-hidden'\n : ''\n }\"\n >\n ${this.renderAudioControl()}\n <obc-slider\n class=\"content-item-slider\"\n .value=${this.audioState.volume}\n @value=${this.handleAudioVolumeChange}\n ></obc-slider>\n </div>\n ${\n this.condensed && showMoreButton\n ? html` <obc-icon-button\n .variant=${IconButtonVariant.flat}\n aria-label=${msg('Audio settings')}\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.audio)}\n >\n <obi-chevron-right-google></obi-chevron-right-google>\n </obc-icon-button>`\n : nothing\n }\n </div>\n </div>`;\n }\n\n private renderMicrophone() {\n if (!this.microphoneState) {\n return nothing;\n }\n const hasInputs =\n this.microphoneState.inputs && this.microphoneState.inputs.length > 0;\n const hasPushToTalk = this.microphoneState.pushToTalk !== undefined;\n const showMoreButton = hasInputs || hasPushToTalk;\n\n const title = showMoreButton\n ? html`<button\n class=\"title-container\"\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.microphone)}\n >\n <div class=\"title\">${msg('Microphone')}</div>\n <div class=\"icon-container\">\n <obi-chevron-right-google class=\"icon\"></obi-chevron-right-google>\n </div>\n </button>`\n : html`<div class=\"title-container\">\n <div class=\"title\">${msg('Microphone')}</div>\n </div>`;\n return html`<div class=\"group\">\n ${this.condensed ? nothing : title}\n <div class=\"content-container\">\n <div\n class=\"action-container ${\n this.microphoneControlMode === SystemMenuControlMode.hidden\n ? 'control-hidden'\n : ''\n }\"\n >\n ${this.renderMicrophoneControl()}\n <div class=\"content-item-value\">\n <obc-audio-output\n .volume=${(this.microphoneState.currentLevel / 100) * 8}\n ></obc-audio-output>\n </div>\n </div>\n ${\n this.condensed && showMoreButton\n ? html` <obc-icon-button\n .variant=${IconButtonVariant.flat}\n aria-label=${msg('Microphone settings')}\n @click=${() =>\n this.handleToSubMenuClick(SystemSubMenu.microphone)}\n >\n <obi-chevron-right-google></obi-chevron-right-google>\n </obc-icon-button>`\n : nothing\n }\n </div>\n </div>`;\n }\n\n private renderBattery() {\n if (!this.batteryState) {\n return nothing;\n }\n const hasModes =\n this.batteryState.modes && this.batteryState.modes.length > 0;\n const hasUsageButton = this.batteryState.hasUsageButton;\n const hasBatterySavingMode =\n this.batteryState.batterySavingMode !== undefined;\n const showMoreButton = hasModes || hasUsageButton || hasBatterySavingMode;\n const title = showMoreButton\n ? html`<button\n class=\"title-container\"\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.battery)}\n >\n <div class=\"title\">${msg('Battery')}</div>\n <div class=\"icon-container\">\n <obi-chevron-right-google class=\"icon\"></obi-chevron-right-google>\n </div>\n </button>`\n : html`<div class=\"title-container\">\n <div class=\"title\">${msg('Battery')}</div>\n </div>`;\n const batteryStatus = this.batteryState.charging\n ? msg('Charging')\n : this.batteryState.poweredNotCharging\n ? msg('Powered & not charging')\n : msg('On battery');\n return html`<div class=\"group\">\n ${this.condensed ? nothing : title}\n <div class=\"content-container battery-container\">\n <div class=\"action-container\">\n <div class=\"battery\">\n <obc-battery-icon\n .level=${this.batteryState.level}\n .charging=${this.batteryState.charging}\n .poweredNotCharging=${\n this.batteryState.poweredNotCharging ?? false\n }\n .notification=${this.batteryState.notification ?? false}\n ></obc-battery-icon>\n <div class=\"percentage\">${this.batteryState.level}%</div>\n <div class=\"status\">\n <slot name=\"battery-status\">${batteryStatus}</slot>\n </div>\n </div>\n </div>\n ${\n this.condensed && showMoreButton\n ? html` <obc-icon-button\n .variant=${IconButtonVariant.flat}\n aria-label=${msg('Battery settings')}\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.battery)}\n >\n <obi-chevron-right-google></obi-chevron-right-google>\n </obc-icon-button>`\n : nothing\n }\n </div>\n </div>`;\n }\n\n private renderSettingsButton() {\n if (!this.showSettingsButton) {\n return nothing;\n }\n return html`<div class=\"group\">\n <button\n class=\"title-container settings\"\n @click=${() => this.dispatchClickEvent('settings-click')}\n >\n <div class=\"icon-container\">\n <obi-settings-iec class=\"icon\"></obi-settings-iec>\n </div>\n <div class=\"title\">${msg('Settings')}</div>\n </button>\n </div>`;\n }\n\n private renderSubMenuTitle(title: string) {\n return html`\n <div class=\"title-container sub-menu-title\">\n <obc-icon-button\n .variant=${IconButtonVariant.normal}\n aria-label=${msg('Back')}\n @click=${() => this.handleToSubMenuClick(SystemSubMenu.main)}\n >\n <obi-chevron-left-google></obi-chevron-left-google>\n </obc-icon-button>\n <div class=\"title\">${title}</div>\n </div>\n `;\n }\n\n private renderWifiSubMenuHeader() {\n return html` <div class=\"sub-container\">\n <div class=\"row wifi-container\">\n <obi-wifi2-google class=\"icon large\"></obi-wifi2-google>\n <div class=\"title wifi-name\">${this.wifiState?.networkName}</div>\n <div class=\"wifi-status\">${this.wifiState?.status}</div>\n </div>\n <div class=\"row\">\n <obc-button\n @click=${() => this.dispatchClickEvent('wifi-options-click')}\n fullWidth\n >${msg('Options')}</obc-button\n >\n ${\n this.wifiState?.connected\n ? html`<obc-button\n @click=${() => this.dispatchClickEvent('wifi-disconnect-click')}\n fullWidth\n >${msg('Disconnect')}</obc-button\n >`\n : nothing\n }\n </div>\n </div>`;\n }\n\n private renderAudioSubMenuHeader() {\n return html` <div class=\"sub-container\">\n <div class=\"row\">\n ${\n this.audioState?.muted\n ? html`<obi-sound-muted class=\"icon large off\"></obi-sound-muted>`\n : html`<obi-sound class=\"icon large\"></obi-sound>`\n }\n <div class=\"title\">\n ${this.audioState?.volume}\n <div class=\"unit\">%</div>\n </div>\n </div>\n <div class=\"row\">\n ${this.renderAudioControl()}\n <obc-slider\n class=\"content-item-slider\"\n .value=${this.audioState?.volume ?? 0}\n @value=${this.handleAudioVolumeChange}\n ></obc-slider>\n </div>\n </div>`;\n }\n\n private handleMicrophoneClick(event: CustomEvent<{checked: boolean}>) {\n event.stopPropagation();\n this.microphoneState!.muted = !event.detail.checked;\n this.dispatchEvent(\n new CustomEvent('microphone-click', {\n detail: {muted: !event.detail.checked},\n })\n );\n }\n\n private handlePushToTalkClick(event: InputEvent) {\n this.dispatchEvent(\n new CustomEvent('push-to-talk-change', {\n detail: {pushToTalk: (event.target as HTMLInputElement).checked},\n })\n );\n }\n\n private handleBatterySavingModeClick(event: CustomEvent<{checked: boolean}>) {\n this.dispatchEvent(\n new CustomEvent('battery-saving-mode-change', {\n detail: {batterySavingMode: event.detail.checked},\n })\n );\n }\n\n private renderMicrophoneSubMenuHeader() {\n const isNoMuteButton =\n this.microphoneControlMode === SystemMenuControlMode.iconOnly ||\n this.microphoneControlMode === SystemMenuControlMode.hidden;\n return html` <div class=\"sub-container\">\n <div class=\"row\">\n ${\n this.microphoneState?.muted\n ? html`<obi-com-mic-muted-google\n class=\"icon large\"\n ></obi-com-mic-muted-google>`\n : html`<obi-com-microphone class=\"icon large\"></obi-com-microphone>`\n }\n <div class=\"title\">\n ${this.microphoneState?.currentLevel}\n <div class=\"unit\">dB</div>\n </div>\n </div>\n <div class=\"row ${isNoMuteButton ? 'no-mute-button' : ''}\">\n ${this.renderMicrophoneControl({externalControl: true})}\n <obc-audio-output\n .volume=${((this.microphoneState?.currentLevel ?? 0) / 100) * 8}\n ></obc-audio-output>\n </div>\n ${\n this.microphoneState?.pushToTalk !== undefined\n ? html`<div class=\"row no-padding\">\n <obc-toggle-switch\n .checked=${this.microphoneState?.pushToTalk}\n @input=${this.handlePushToTalkClick}\n label=${msg('Push to talk')}\n ></obc-toggle-switch>\n </div>`\n : nothing\n }\n </div>`;\n }\n\n private handleBatteryUsageClick() {\n this.dispatchEvent(\n new CustomEvent('battery-usage-click', {detail: {usage: true}})\n );\n }\n\n private renderBatterySubMenuHeader() {\n if (!this.batteryState) {\n return nothing;\n }\n return html` <div class=\"sub-container\">\n <div class=\"row\">\n <obc-battery-icon\n class=\"icon large\"\n .level=${this.batteryState.level}\n .charging=${this.batteryState.charging}\n .poweredNotCharging=${this.batteryState.poweredNotCharging ?? false}\n .notification=${this.batteryState.notification ?? false}\n ></obc-battery-icon>\n <div class=\"title\">\n ${this.batteryState.level}\n <div class=\"unit\">%</div>\n </div>\n </div>\n <div class=\"row\">\n <obc-button @click=${this.handleBatteryUsageClick} fullWidth>\n ${msg('Usage')}\n </obc-button>\n </div>\n ${\n this.batteryState.batterySavingMode !== undefined\n ? html`<div class=\"row no-padding\">\n <obc-toggle-switch\n .checked=${this.batteryState.batterySavingMode}\n @toggle-switch-click=${this.handleBatterySavingModeClick}\n label=${msg('Battery saving mode')}\n ></obc-toggle-switch>\n </div>`\n : nothing\n }\n </div>`;\n }\n\n private handleWifiNetworkClick(name: string) {\n this.dispatchEvent(\n new CustomEvent('wifi-network-change', {detail: {network: name}})\n );\n }\n\n private renderWifMenuOptions() {\n if (this.wifiState?.networks?.length === 0) {\n return nothing;\n }\n return html`\n <div class=\"sub-container sub-container-title\">\n <div class=\"row title2\">${msg('Wi-Fi')}</div>\n </div>\n <div class=\"sub-container\">\n <div class=\"row navigation-items\">\n ${this.wifiState?.networks?.map(\n (option) => html`\n <obc-navigation-item\n .label=${option.name}\n .checked=${option.name === this.wifiState?.networkName}\n @click=${() => this.handleWifiNetworkClick(option.name)}\n hasIcon\n >\n <obi-wifi2-google slot=\"icon\"></obi-wifi2-google>\n </obc-navigation-item>\n `\n )}\n <obc-accordion-item title=${msg('Other networks')}>\n <div slot=\"expanded-content\">\n ${this.wifiState?.otherNetworks?.map(\n (option) => html`\n <obc-navigation-item\n .label=${option.name}\n .checked=${option.name === this.wifiState?.networkName}\n @click=${() => this.handleWifiNetworkClick(option.name)}\n hasIcon\n >\n <obi-wifi2-google slot=\"icon\"></obi-wifi2-google>\n </obc-navigation-item>\n `\n )}\n </div>\n </obc-accordion-item>\n </div>\n </div>\n `;\n }\n\n private handleAudioOutputClick(name: string) {\n this.dispatchEvent(\n new CustomEvent('audio-output-change', {detail: {output: name}})\n );\n }\n\n private handleMicrophoneInputClick(name: string) {\n this.dispatchEvent(\n new CustomEvent('microphone-input-change', {detail: {input: name}})\n );\n }\n\n private handleBatteryModeClick(name: string) {\n this.dispatchEvent(\n new CustomEvent('battery-mode-change', {detail: {mode: name}})\n );\n }\n\n private renderAudioSubMenuOptions() {\n return this.renderSubMenuOptions(\n msg('Output'),\n this.audioState?.outputs ?? [],\n this.audioState?.selectedOutput ?? '',\n (name: string) => this.handleAudioOutputClick(name)\n );\n }\n\n private renderMicrophoneSubMenuOptions() {\n return this.renderSubMenuOptions(\n msg('Input'),\n this.microphoneState?.inputs ?? [],\n this.microphoneState?.selectedInput ?? '',\n (name: string) => this.handleMicrophoneInputClick(name)\n );\n }\n\n private renderBatterySubMenuOptions() {\n return this.renderSubMenuOptions(\n msg('Mode'),\n this.batteryState?.modes ?? [],\n this.batteryState?.selectedMode ?? '',\n (name: string) => this.handleBatteryModeClick(name)\n );\n }\n\n private renderSubMenuOptions(\n title: string,\n options: {name: string}[],\n selectedOption: string,\n handleOptionClick: (name: string) => void\n ) {\n if (options.length === 0) {\n return nothing;\n }\n return html`\n <div class=\"sub-container sub-container-title\">\n <div class=\"row title2\">${title}</div>\n </div>\n <div class=\"sub-container\">\n <div class=\"row radio\">\n ${options.map(\n (option) => html`\n <obc-radio\n .name=${title}\n .label=${option.name}\n .checked=${option.name === selectedOption}\n @change=${() => handleOptionClick(option.name)}\n ></obc-radio>\n `\n )}\n </div>\n </div>\n `;\n }\n\n // --- Small screen methods ---\n\n private renderSmallScreen() {\n const activeTab = this.effectiveSubMenu;\n let content: TemplateResult | symbol = nothing;\n switch (activeTab) {\n case SystemSubMenu.wifi:\n content = this.renderSmallScreenWifi();\n break;\n case SystemSubMenu.audio:\n content = this.renderSmallScreenAudio();\n break;\n case SystemSubMenu.microphone:\n content = this.renderSmallScreenMicrophone();\n break;\n case SystemSubMenu.battery:\n content = this.renderSmallScreenBattery();\n break;\n }\n return html`<div class=\"wrapper small-screen\">\n <div class=\"small-screen-content\">${content}</div>\n ${this.renderMenuBar(activeTab)}\n </div>`;\n }\n\n private handleSmallScreenWifiToggle(event: InputEvent) {\n const enabled = (event.target as HTMLInputElement).checked;\n this.dispatchEvent(new CustomEvent('wifi-click', {detail: {enabled}}));\n }\n\n private renderSmallScreenWifi() {\n if (!this.wifiState) {\n return nothing;\n }\n return html`\n <div class=\"small-screen-header\">\n <div class=\"small-screen-title-row\">\n <span>${msg('Wi-Fi')}</span>\n <obc-toggle-switch\n .checked=${this.wifiState.enabled}\n @input=${this.handleSmallScreenWifiToggle}\n ></obc-toggle-switch>\n </div>\n </div>\n <div class=\"small-screen-divider\"></div>\n <obc-scrollbar class=\"small-screen-options\">\n <div class=\"small-screen-options-content\">\n ${this.wifiState.networks?.map(\n (network) => html`\n <obc-navigation-item\n .label=${network.name}\n .checked=${network.name === this.wifiState?.networkName}\n @click=${() => this.handleWifiNetworkClick(network.name)}\n hasIcon\n >\n <obi-wifi2-google slot=\"icon\"></obi-wifi2-google>\n </obc-navigation-item>\n `\n )}\n </div>\n </obc-scrollbar>\n `;\n }\n\n private renderSmallScreenAudio() {\n if (!this.audioState) {\n return nothing;\n }\n return html`\n <div class=\"small-screen-header\">\n <div class=\"small-screen-title-row\">\n <span>${msg('Audio')}</span>\n </div>\n <div class=\"small-screen-controls-row\">\n ${this.renderAudioControl()}\n <div class=\"small-screen-slider-container\">\n <obc-slider\n class=\"small-screen-slider\"\n .value=${this.audioState.volume}\n @value=${this.handleAudioVolumeChange}\n ></obc-slider>\n <span class=\"small-screen-volume-label\"\n >${this.audioState.volume}%</span\n >\n </div>\n </div>\n </div>\n <div class=\"small-screen-divider\"></div>\n <obc-scrollbar class=\"small-screen-options\">\n <div class=\"small-screen-options-content\">\n ${(this.audioState.outputs ?? []).map(\n (output) => html`\n <obc-radio\n name=\"output\"\n .label=${output.name}\n .checked=${output.name === this.audioState?.selectedOutput}\n @change=${() => this.handleAudioOutputClick(output.name)}\n ></obc-radio>\n `\n )}\n </div>\n </obc-scrollbar>\n `;\n }\n\n private renderSmallScreenMicrophone() {\n if (!this.microphoneState) {\n return nothing;\n }\n const isNoMuteButton =\n this.microphoneControlMode === SystemMenuControlMode.iconOnly ||\n this.microphoneControlMode === SystemMenuControlMode.hidden;\n return html`\n <div class=\"small-screen-header\">\n <div class=\"small-screen-title-row\">\n <span>${msg('Microphone')}</span>\n </div>\n <div\n class=\"small-screen-controls-row ${\n isNoMuteButton ? 'no-mute-button' : ''\n }\"\n >\n ${this.renderMicrophoneControl()}\n <obc-audio-output\n class=\"small-screen-audio-output\"\n .volume=${(this.microphoneState.currentLevel / 100) * 8}\n ></obc-audio-output>\n </div>\n ${\n this.microphoneState.pushToTalk !== undefined\n ? html`<div class=\"small-screen-toggle-row\">\n <obc-toggle-switch\n .checked=${this.microphoneState.pushToTalk}\n @input=${this.handlePushToTalkClick}\n label=${msg('Push to talk')}\n ></obc-toggle-switch>\n </div>`\n : nothing\n }\n </div>\n <div class=\"small-screen-divider\"></div>\n <obc-scrollbar class=\"small-screen-options\">\n <div class=\"small-screen-options-content\">\n ${(this.microphoneState.inputs ?? []).map(\n (input) => html`\n <obc-radio\n name=\"input\"\n .label=${input.name}\n .checked=${input.name === this.microphoneState?.selectedInput}\n @change=${() => this.handleMicrophoneInputClick(input.name)}\n ></obc-radio>\n `\n )}\n </div>\n </obc-scrollbar>\n `;\n }\n\n private renderSmallScreenBattery() {\n if (!this.batteryState) {\n return nothing;\n }\n return html`\n <div class=\"small-screen-header\">\n <div class=\"small-screen-title-row\">\n <span>${msg('Battery')}</span>\n <div class=\"small-screen-battery-info\">\n <obc-battery-icon\n .level=${this.batteryState.level}\n .charging=${this.batteryState.charging}\n .poweredNotCharging=${\n this.batteryState.poweredNotCharging ?? false\n }\n .notification=${this.batteryState.notification ?? false}\n ></obc-battery-icon>\n <span class=\"small-screen-battery-level\"\n >${this.batteryState.level}%</span\n >\n </div>\n </div>\n ${\n this.batteryState.hasUsageButton\n ? html`<div class=\"small-screen-button-row\">\n <obc-button @click=${this.handleBatteryUsageClick} fullWidth>\n ${msg('Usage')}\n </obc-button>\n </div>`\n : nothing\n }\n ${\n this.batteryState.batterySavingMode !== undefined\n ? html`<div class=\"small-screen-toggle-row\">\n <obc-toggle-switch\n .checked=${this.batteryState.batterySavingMode}\n @toggle-switch-click=${this.handleBatterySavingModeClick}\n label=${msg('Battery saving mode')}\n ></obc-toggle-switch>\n </div>`\n : nothing\n }\n </div>\n <div class=\"small-screen-divider\"></div>\n <obc-scrollbar class=\"small-screen-options\">\n <div class=\"small-screen-options-content\">\n ${(this.batteryState.modes ?? []).map(\n (mode) => html`\n <obc-radio\n name=\"mode\"\n .label=${mode.name}\n .checked=${mode.name === this.batteryState?.selectedMode}\n @change=${() => this.handleBatteryModeClick(mode.name)}\n ></obc-radio>\n `\n )}\n </div>\n </obc-scrollbar>\n `;\n }\n\n private renderMenuBarButton(\n subMenu: SystemSubMenu,\n activeTab: SystemSubMenu,\n label: string,\n icon: TemplateResult\n ) {\n return html`<button\n class=${activeTab === subMenu ? 'active' : ''}\n title=${label}\n @click=${() => this.handleToSubMenuClick(subMenu)}\n >\n ${icon}\n </button>`;\n }\n\n private renderMenuBar(activeTab: SystemSubMenu) {\n return html`\n <div class=\"menu-bar\">\n ${\n this.wifiState\n ? this.renderMenuBarButton(\n SystemSubMenu.wifi,\n activeTab,\n msg('Wi-Fi'),\n html`<obi-wifi2-google class=\"tab-icon\"></obi-wifi2-google>`\n )\n : nothing\n }\n ${\n this.audioState\n ? this.renderMenuBarButton(\n SystemSubMenu.audio,\n activeTab,\n msg('Audio'),\n html`<obi-sound class=\"tab-icon\"></obi-sound>`\n )\n : nothing\n }\n ${\n this.microphoneState\n ? this.renderMenuBarButton(\n SystemSubMenu.microphone,\n activeTab,\n msg('Microphone'),\n html`<obi-com-microphone class=\"tab-icon\"></obi-com-microphone>`\n )\n : nothing\n }\n ${\n this.batteryState\n ? this.renderMenuBarButton(\n SystemSubMenu.battery,\n activeTab,\n msg('Battery'),\n html`<obc-battery-icon\n class=\"tab-icon\"\n .level=${this.batteryState.level}\n .charging=${this.batteryState.charging}\n .poweredNotCharging=${\n this.batteryState.poweredNotCharging ?? false\n }\n .notification=${this.batteryState.notification ?? false}\n ></obc-battery-icon>`\n )\n : nothing\n }\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n"],"mappings":"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"}
|
|
@@ -128,8 +128,8 @@ export type ObcUserMenuSignedInAction = {
|
|
|
128
128
|
* @availableWhen primaryActionId type==signedIn && size==small
|
|
129
129
|
* @property showUseAnotherAccount - Controls the visibility of the "Use another account" button.
|
|
130
130
|
* @availableWhen showUseAnotherAccount type==userSignIn
|
|
131
|
-
* @property softDismiss -
|
|
132
|
-
* @property open - Whether the menu is showing.
|
|
131
|
+
* @property softDismiss - Lets the menu close itself on a click outside it, on `Escape`, or when another menu opens. The page is covered while the menu is open, so the closing click reaches nothing there; only the top bar's strip stays clickable, which is how its buttons switch or close menus in one click. Wire it with three bindings: set `softDismiss`, bind `open` to a flag you keep, and reset that flag on `close`. The button that opens the menu needs no wiring of its own: flip the flag from its click, or from the button event of `obc-top-bar` or `obc-integration-bar`. The user menu's *Soft Dismiss From A Bar Button* story shows that wiring, the brilliance menu's *Soft Dismiss* story the one for a button you hold yourself (`bindPopoverTrigger`), and the vue demo runs its top bar this way. Leave it off to show and hide the menu yourself.
|
|
132
|
+
* @property open - Whether the menu is showing. Bind it to a flag you keep rather than toggling it from the menu's own value: when the menu closes itself, `open` is written back to `false` before the button's click reaches your handler, so `menu.open = !menu.open` gets out of step. Reset the flag on `close`.
|
|
133
133
|
* @availableWhen open softDismiss==true
|
|
134
134
|
* @slot signed-in-action-icon-<id> - Optional icon for a signed-in action, one per action; `<id>` is the normalized action id (shown in the `signed-in` type).
|
|
135
135
|
* @fires {CustomEvent<{username?: string, password?: string}>} sign-in-click - Fired when a sign-in button is clicked.
|
|
@@ -137,14 +137,14 @@ export type ObcUserMenuSignedInAction = {
|
|
|
137
137
|
* @fires {CustomEvent<void>} use-another-account-click - Fired when the "Use another account" button is clicked.
|
|
138
138
|
* @fires {CustomEvent<{id: string, label: string}>} signed-in-action-click - Fired when a signed-in action is clicked.
|
|
139
139
|
* @fires {ObcUserMenuRecentUserClickEvent} recent-user-click - Fired when a recent user button is clicked, carrying that user's entry.
|
|
140
|
-
* @fires {CustomEvent<void>} close - Fired when the menu closed on its own, from a click outside, `Escape`, or another menu opening. `open` is already `false` by the time it arrives.
|
|
140
|
+
* @fires {CustomEvent<void>} close - Fired when the menu closed on its own, from a click outside, `Escape`, or another menu opening. `open` is already `false` by the time it arrives; reset the flag you bind to `open` here, or the next click on the button finds it still set and asks a closed menu to close.
|
|
141
141
|
* @stable
|
|
142
142
|
*/
|
|
143
143
|
export declare class ObcUserMenu extends LitElement {
|
|
144
|
-
/**
|
|
144
|
+
/** Lets the menu close itself on a click outside it, on `Escape`, or when another menu opens. The page is covered while the menu is open, so the closing click reaches nothing there; only the top bar's strip stays clickable, which is how its buttons switch or close menus in one click. Wire it with three bindings: set `softDismiss`, bind `open` to a flag you keep, and reset that flag on `close`. The button that opens the menu needs no wiring of its own: flip the flag from its click, or from the button event of `obc-top-bar` or `obc-integration-bar`. The user menu's *Soft Dismiss From A Bar Button* story shows that wiring, the brilliance menu's *Soft Dismiss* story the one for a button you hold yourself (`bindPopoverTrigger`), and the vue demo runs its top bar this way. Leave it off to show and hide the menu yourself. */
|
|
145
145
|
softDismiss: boolean;
|
|
146
146
|
/**
|
|
147
|
-
* Whether the menu is showing.
|
|
147
|
+
* Whether the menu is showing. Bind it to a flag you keep rather than toggling it from the menu's own value: when the menu closes itself, `open` is written back to `false` before the button's click reaches your handler, so `menu.open = !menu.open` gets out of step. Reset the flag on `close`.
|
|
148
148
|
*
|
|
149
149
|
* Available when `softDismiss==true`.
|
|
150
150
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-menu.js","names":[],"sources":["../../../src/components/user-menu/user-menu.ts"],"sourcesContent":["import {LitElement, TemplateResult, html, nothing, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {customElement} from '../../decorator.js';\nimport componentStyle from './user-menu.css?inline';\nimport '../text-input-field/text-input-field.js';\nimport '../button/button.js';\nimport '../user-button/user-button.js';\nimport '../progress-bar/progress-bar.js';\nimport '../navigation-item/navigation-item.js';\nimport '../../icons/icon-calendar-google.js';\nimport '../../icons/icon-log-open.js';\nimport '../../icons/icon-settings-iec.js';\nimport '../../icons/icon-user.js';\nimport {\n HTMLInputTypeAttribute,\n ObcTextInputFieldTextAlign,\n} from '../text-input-field/text-input-field.js';\nimport {ButtonVariant} from '../button/button.js';\nimport {\n ProgressBarMode,\n ProgressBarType,\n} from '../progress-bar/progress-bar.js';\nimport {Size, StyleType, Variant} from '../user-button/user-button.js';\nimport {localized, msg} from '@lit/localize';\nimport {stopPropagation} from '../../internal/events.js';\nimport {PopoverController} from '../../internal/popover-controller.js';\n\nexport enum ObcUserMenuType {\n signIn = 'sign-in',\n userSignIn = 'user-sign-in',\n loadingSignIn = 'loading-sign-in',\n signedIn = 'signed-in',\n}\n\nexport enum ObcUserMenuSize {\n regular = 'regular',\n small = 'small',\n}\n\nexport type ObcUserMenuUser = {\n initials: string;\n label: string;\n role?: string;\n};\n\nexport type ObcUserMenuRecentUserClickEvent = CustomEvent<ObcUserMenuUser>;\n\nexport type ObcUserMenuSignedInAction = {\n id: string;\n label: string;\n};\n\n/**\n * `<obc-user-menu>` – A user menu component with sign-in and signed-in layouts.\n *\n * Provides multiple layouts for authentication and account access states, including\n * sign-in forms, user-specific sign-in, loading states, and signed-in navigation.\n *\n * ### Features\n * - **Multiple States:** Supports sign-in, user sign-in, loading, and signed-in layouts.\n * - **Size Options:** Regular and small sizes for compact layouts.\n * - **Recent Users:** Optional \"Recently signed in\" section for quick access.\n * - **Navigation Actions:** Signed-in state lists the actions it is given.\n *\n * ### Variants\n * - `type`: `sign-in`, `user-sign-in`, `loading-sign-in`, `signed-in`\n * - `size`: `regular`, `small`\n *\n * ### Usage Guidelines\n * Use `obc-user-menu` in authentication or account panels where quick access to\n * sign-in, profile, or account actions is needed. The `user-sign-in` type is\n * best for fast re-auth flows; `loading-sign-in` is for pending auth states.\n *\n * ### Properties and Configuration\n * - `type` (`ObcUserMenuType`): Controls the layout state. Defaults to `sign-in`.\n * - `size` (`ObcUserMenuSize`): Controls the overall size. Defaults to `regular`.\n * - `hasRecentlySignedIn` (`boolean`): Toggles the recent users section.\n * Defaults to `false`.\n * - `showUsername` (`boolean`): Toggles the username field. Defaults to `true`.\n * - `showPassword` (`boolean`): Toggles the password field. Defaults to `true`.\n * - `username` (`string`): Current username value for sign-in layouts.\n * - `password` (`string`): Current password value for sign-in layouts.\n * - `usernameError` (`string`): Error message for the username field.\n * - `passwordError` (`string`): Error message for the password field.\n * - `userInitials` (`string`): Initials for the primary user profile.\n * - `userLabel` (`string`): Label for the primary user profile.\n * - `userRole` (`string`): Role shown under the primary user's label. Omit it\n * to show no role; only the regular size draws one.\n * - `recentUsers` (`ObcUserMenuUser[]`): List of recent users shown in the\n * \"Recently signed in\" section. Empty renders no section. Each user may\n * carry its own `role`.\n * - `showUseAnotherAccount` (`boolean`): Toggles the \"Use another account\"\n * button in the `user-sign-in` layouts, both sizes. Defaults to `true`.\n * - `signedInActions` (`ObcUserMenuSignedInAction[]`): Actions shown in the\n * signed-in navigation list. Empty renders no actions.\n * - `primaryActionId` (`string`): Id of the action promoted to a button in the\n * small signed-in layout.\n *\n * ### Events\n * - `sign-in-click` – Fired when a sign-in button is clicked.\n * - `sign-out-click` – Fired when the sign-out button is clicked.\n * - `use-another-account-click` – Fired when the \"Use another account\" button\n * is clicked. The menu does not change its own type; set it to `sign-in` in\n * the handler to show the full form.\n * - `signed-in-action-click` – Fired when a signed-in action is clicked.\n * - `recent-user-click` – Fired when a recent user button is clicked.\n *\n * ### Slots\n * - `signed-in-action-icon-{id}`: Optional icon for a signed-in action. The\n * `{id}` is the normalized action id.\n *\n * ### Example\n * ```html\n * <obc-user-menu\n * type=\"user-sign-in\"\n * size=\"small\"\n * hasRecentlySignedIn=\"false\"\n * userInitials=\"JD\"\n * userLabel=\"John Doe\"\n * ></obc-user-menu>\n * ```\n *\n * @property type - Controls the visual layout of the user menu.\n * @property size - Controls the overall size of the user menu.\n * @property hasRecentlySignedIn - Toggles the \"Recently signed in\" section visibility.\n * @availableWhen hasRecentlySignedIn type in [signIn, userSignIn]\n * @property username - Current username value for sign-in layouts.\n * @availableWhen username showUsername==true && type==signIn\n * @property password - Current password value for sign-in layouts.\n * @availableWhen password showPassword==true && type in [signIn, userSignIn]\n * @property usernameError - Error message for the username field.\n * @availableWhen usernameError type==signIn\n * @property passwordError - Error message for the password field.\n * @availableWhen passwordError type in [signIn, userSignIn]\n * @property userInitials - Initials for the primary user profile.\n * @availableWhen userInitials type!=signIn\n * @property userLabel - Label for the primary user profile.\n * @availableWhen userLabel type!=signIn\n * @property userRole - Role shown under the primary user's label; omit it to show no role.\n * @availableWhen userRole type!=signIn && size==regular\n * @property recentUsers - Recent users for the \"Recently signed in\" section.\n * @property signedInActions - Actions shown in the signed-in navigation list.\n * @availableWhen signedInActions type==signedIn\n * @property showUsername - Controls the visibility of the username field.\n * @availableWhen showUsername type==signIn\n * @property showPassword - Controls the visibility of the password field.\n * @availableWhen showPassword type in [signIn, userSignIn]\n * @property primaryActionId - Id of the action promoted to a button in the small signed-in layout.\n * @availableWhen primaryActionId type==signedIn && size==small\n * @property showUseAnotherAccount - Controls the visibility of the \"Use another account\" button.\n * @availableWhen showUseAnotherAccount type==userSignIn\n * @property softDismiss - Let the browser close this menu on its own: on a click outside it, on `Escape`, or when another menu opens. Leave it off to keep showing and hiding the menu yourself.\n * @property open - Whether the menu is showing.\n * @availableWhen open softDismiss==true\n * @slot signed-in-action-icon-<id> - Optional icon for a signed-in action, one per action; `<id>` is the normalized action id (shown in the `signed-in` type).\n * @fires {CustomEvent<{username?: string, password?: string}>} sign-in-click - Fired when a sign-in button is clicked.\n * @fires {CustomEvent<void>} sign-out-click - Fired when the sign-out button is clicked.\n * @fires {CustomEvent<void>} use-another-account-click - Fired when the \"Use another account\" button is clicked.\n * @fires {CustomEvent<{id: string, label: string}>} signed-in-action-click - Fired when a signed-in action is clicked.\n * @fires {ObcUserMenuRecentUserClickEvent} recent-user-click - Fired when a recent user button is clicked, carrying that user's entry.\n * @fires {CustomEvent<void>} close - Fired when the menu closed on its own, from a click outside, `Escape`, or another menu opening. `open` is already `false` by the time it arrives.\n * @stable\n */\n@customElement('obc-user-menu')\n@localized()\nexport class ObcUserMenu extends LitElement {\n @property({type: Boolean}) softDismiss = false;\n\n @property({type: Boolean}) open = false;\n\n protected readonly softDismissController = new PopoverController(this);\n\n @property({type: String}) type: ObcUserMenuType = ObcUserMenuType.signIn;\n\n @property({type: String}) size: ObcUserMenuSize = ObcUserMenuSize.regular;\n\n @property({type: Boolean})\n hasRecentlySignedIn = false;\n\n @property({type: Boolean, attribute: false})\n showUsername = true;\n\n @property({type: String}) username = '';\n\n @property({type: Boolean, attribute: false})\n showPassword = true;\n\n @property({type: String}) password = '';\n\n @property({type: String}) usernameError = '';\n\n @property({type: String}) passwordError = '';\n\n @property({type: String}) userInitials?: string;\n\n @property({type: String}) userLabel?: string;\n\n @property({type: String}) userRole?: string;\n\n @property({type: Array, attribute: false})\n recentUsers: ObcUserMenuUser[] = [];\n\n @property({type: Array, attribute: false})\n signedInActions: ObcUserMenuSignedInAction[] = [];\n\n @property({type: String}) primaryActionId?: string;\n\n @property({type: Boolean, attribute: false})\n showUseAnotherAccount = true;\n\n private get showRecentUsers() {\n return this.hasRecentlySignedIn && this.recentUsers.length > 0;\n }\n\n private renderTextInput(\n placeholder: string,\n type: HTMLInputTypeAttribute = HTMLInputTypeAttribute.Text,\n value = '',\n onInput?: (event: Event) => void,\n errorText = ''\n ) {\n const isPassword = type === HTMLInputTypeAttribute.Password;\n return html`\n <obc-text-input-field\n .placeholder=${placeholder}\n .type=${type}\n .textAlign=${ObcTextInputFieldTextAlign.Left}\n .value=${value}\n .error=${Boolean(errorText)}\n .errorText=${errorText}\n .required=${true}\n .hasClearButton=${!isPassword}\n @input=${onInput}\n @change=${stopPropagation}\n @clear=${stopPropagation}\n >\n </obc-text-input-field>\n `;\n }\n\n private renderUserButtons(count: number, isLarge: boolean) {\n const size = isLarge ? Size.large : Size.regular;\n const users = this.recentUsers.slice(0, count);\n return html`\n <div\n class=${classMap({\n users: true,\n large: isLarge,\n single: users.length === 1,\n })}\n >\n ${users.map(\n (user) => html`\n <obc-user-button\n .variant=${Variant.initials}\n .styleType=${StyleType.normal}\n .size=${size}\n .initials=${user.initials}\n .label=${user.label}\n .sublabel=${isLarge ? user.role : undefined}\n @click=${() => this.handleRecentUserClick(user)}\n ></obc-user-button>\n `\n )}\n </div>\n `;\n }\n\n private renderUserProfile(\n layout: 'vertical' | 'horizontal',\n size: 'large' | 'regular'\n ) {\n if (!this.userInitials && !this.userLabel) {\n return nothing;\n }\n const userButtonSize = size === 'large' ? Size.large : Size.regular;\n const role = size === 'large' ? this.userRole : undefined;\n return html`\n <div\n class=${classMap({\n 'user-profile': true,\n [layout]: true,\n })}\n >\n <obc-user-button\n class=${classMap({\n 'user-avatar': true,\n [`size-${size}`]: true,\n 'has-role': Boolean(role),\n })}\n .variant=${Variant.initials}\n .styleType=${StyleType.normal}\n .size=${userButtonSize}\n .initials=${this.userInitials ?? ''}\n .label=${this.userLabel ?? ''}\n .sublabel=${role}\n ></obc-user-button>\n </div>\n `;\n }\n\n private getSignedInActionIcon(actionId: string) {\n switch (actionId) {\n case 'calendar':\n return html`<obi-calendar-google></obi-calendar-google>`;\n case 'log':\n return html`<obi-log-open></obi-log-open>`;\n case 'preferences':\n return html`<obi-settings-iec></obi-settings-iec>`;\n case 'user-account':\n return html`<obi-user></obi-user>`;\n default:\n return nothing;\n }\n }\n\n private normalizeActionId(actionId: string) {\n return actionId\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-');\n }\n\n private handleSignedInActionClick(action: ObcUserMenuSignedInAction) {\n this.dispatchEvent(\n new CustomEvent('signed-in-action-click', {\n detail: {id: action.id, label: action.label},\n })\n );\n }\n\n private handleRecentUserClick(user: ObcUserMenuUser) {\n this.dispatchEvent(\n new CustomEvent<ObcUserMenuUser>('recent-user-click', {\n detail: {...user},\n })\n );\n }\n\n private handleUsernameInput(event: Event) {\n const target = event.target as {value?: string};\n this.username = target.value ?? '';\n if (this.username) {\n this.usernameError = '';\n }\n }\n\n private handlePasswordInput(event: Event) {\n const target = event.target as {value?: string};\n this.password = target.value ?? '';\n if (this.password) {\n this.passwordError = '';\n }\n }\n\n private validateSignIn() {\n let valid = true;\n const needsUsername =\n this.type === ObcUserMenuType.signIn && this.showUsername;\n const needsPassword = this.showPassword;\n\n if (needsUsername && !this.username) {\n this.usernameError = msg('Username is required');\n valid = false;\n }\n\n if (needsPassword && !this.password) {\n this.passwordError = msg('Password is required');\n valid = false;\n }\n\n return valid;\n }\n\n private handleSignInClick() {\n if (!this.validateSignIn()) {\n return;\n }\n this.dispatchEvent(\n new CustomEvent('sign-in-click', {\n detail: {\n username: this.showUsername ? this.username : undefined,\n password: this.showPassword ? this.password : undefined,\n },\n })\n );\n }\n\n private handleSignOutClick() {\n this.dispatchEvent(new CustomEvent('sign-out-click'));\n }\n\n private handleUseAnotherAccountClick() {\n this.dispatchEvent(new CustomEvent('use-another-account-click'));\n }\n\n private renderSignIn() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div\n class=${classMap({\n 'login-container': true,\n 'signin-only': !this.showRecentUsers,\n })}\n >\n ${\n this.showUsername\n ? this.renderTextInput(\n msg('Username'),\n HTMLInputTypeAttribute.Text,\n this.username,\n this.handleUsernameInput.bind(this),\n this.usernameError\n )\n : nothing\n }\n ${\n this.showPassword\n ? this.renderTextInput(\n msg('Password'),\n HTMLInputTypeAttribute.Password,\n this.password,\n this.handlePasswordInput.bind(this),\n this.passwordError\n )\n : nothing\n }\n <obc-button\n variant=${ButtonVariant.raised}\n fullWidth\n @click=${this.handleSignInClick}\n >\n ${msg('Sign in')}\n </obc-button>\n </div>\n ${\n this.showRecentUsers\n ? html`\n <div class=\"recent-container\">\n <div class=\"title-container\">\n <div class=\"subtitle\">${msg('Recently signed in')}</div>\n </div>\n <div class=\"actions-container\">\n ${this.renderUserButtons(3, true)}\n </div>\n </div>\n `\n : nothing\n }\n `;\n }\n\n private renderSignInSmall() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div\n class=${classMap({\n 'login-container': true,\n 'signin-only': !this.showRecentUsers,\n })}\n >\n ${\n this.showUsername\n ? this.renderTextInput(\n msg('Username'),\n HTMLInputTypeAttribute.Text,\n this.username,\n this.handleUsernameInput.bind(this),\n this.usernameError\n )\n : nothing\n }\n ${\n this.showPassword\n ? this.renderTextInput(\n msg('Password'),\n HTMLInputTypeAttribute.Password,\n this.password,\n this.handlePasswordInput.bind(this),\n this.passwordError\n )\n : nothing\n }\n <obc-button\n variant=${ButtonVariant.raised}\n fullWidth\n @click=${this.handleSignInClick}\n >\n ${msg('Sign in')}\n </obc-button>\n </div>\n ${\n this.showRecentUsers\n ? html`\n <div class=\"divider\" aria-hidden=\"true\"></div>\n <div class=\"recent-container recent\">\n <div class=\"title-container\">\n <div class=\"subtitle\">${msg('Recent')}</div>\n </div>\n <div class=\"actions-container\">\n ${this.renderUserButtons(3, false)}\n </div>\n </div>\n `\n : nothing\n }\n `;\n }\n\n private renderUserSignIn() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div\n class=${classMap({\n 'login-container': true,\n 'signin-only': !this.showRecentUsers,\n })}\n >\n <div class=\"user-primary\">\n ${this.renderUserProfile('vertical', 'large')}\n </div>\n <div class=\"fields\">\n ${\n this.showPassword\n ? this.renderTextInput(\n msg('Password'),\n HTMLInputTypeAttribute.Password,\n this.password,\n this.handlePasswordInput.bind(this),\n this.passwordError\n )\n : nothing\n }\n <obc-button\n variant=${ButtonVariant.raised}\n fullWidth\n @click=${this.handleSignInClick}\n >\n ${msg('Sign in')}\n </obc-button>\n ${\n this.showUseAnotherAccount\n ? html`\n <obc-button\n variant=${ButtonVariant.normal}\n fullWidth\n @click=${this.handleUseAnotherAccountClick}\n >\n ${msg('Use another account')}\n </obc-button>\n `\n : nothing\n }\n </div>\n </div>\n ${\n this.showRecentUsers\n ? html`\n <div class=\"recent-container\">\n <div class=\"title-container\">\n <div class=\"subtitle\">${msg('Recently signed in')}</div>\n </div>\n <div class=\"actions-container\">\n ${this.renderUserButtons(3, true)}\n </div>\n </div>\n `\n : nothing\n }\n `;\n }\n\n private renderUserSignInSmall() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div class=\"user-container\">\n ${this.renderUserProfile('horizontal', 'regular')}\n </div>\n <div\n class=${classMap({\n 'login-container': true,\n 'signin-only': !this.showRecentUsers,\n })}\n >\n ${\n this.showPassword\n ? this.renderTextInput(\n msg('Password'),\n HTMLInputTypeAttribute.Password,\n this.password,\n this.handlePasswordInput.bind(this),\n this.passwordError\n )\n : nothing\n }\n <obc-button\n variant=${ButtonVariant.raised}\n fullWidth\n @click=${this.handleSignInClick}\n >\n ${msg('Sign in')}\n </obc-button>\n ${\n this.showUseAnotherAccount\n ? html`\n <obc-button\n variant=${ButtonVariant.normal}\n fullWidth\n @click=${this.handleUseAnotherAccountClick}\n >\n ${msg('Use another account')}\n </obc-button>\n `\n : nothing\n }\n </div>\n ${\n this.showRecentUsers\n ? html`\n <div class=\"divider\" aria-hidden=\"true\"></div>\n <div class=\"recent-container recent\">\n <div class=\"title-container\">\n <div class=\"subtitle\">${msg('Recent')}</div>\n </div>\n <div class=\"actions-container\">\n ${this.renderUserButtons(3, false)}\n </div>\n </div>\n `\n : nothing\n }\n `;\n }\n\n private renderLoadingSignIn() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div class=\"user-primary loading\">\n ${this.renderUserProfile('vertical', 'large')}\n <obc-progress-bar\n class=\"progress\"\n type=${ProgressBarType.linear}\n mode=${ProgressBarMode.indeterminate}\n .showValue=${false}\n ></obc-progress-bar>\n </div>\n `;\n }\n\n private renderLoadingSignInSmall() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div class=\"user-primary loading\">\n ${this.renderUserProfile('horizontal', 'regular')}\n <obc-progress-bar\n class=\"progress\"\n type=${ProgressBarType.linear}\n mode=${ProgressBarMode.indeterminate}\n .showValue=${false}\n ></obc-progress-bar>\n </div>\n `;\n }\n\n private renderSignedIn() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('User')}</h3>\n </div>\n <div class=\"user-primary signed-in\">\n ${this.renderUserProfile('vertical', 'large')}\n </div>\n <div class=\"divider\" aria-hidden=\"true\"></div>\n ${\n this.signedInActions.length\n ? html`\n <div class=\"nav-container\">\n ${this.signedInActions.map((action) => {\n const normalizedId = this.normalizeActionId(action.id);\n return html`\n <obc-navigation-item\n .label=${action.label}\n hasIcon\n @click=${() => this.handleSignedInActionClick(action)}\n >\n <span slot=\"icon\">\n <slot name=\"signed-in-action-icon-${normalizedId}\">\n ${this.getSignedInActionIcon(normalizedId)}\n </slot>\n </span>\n </obc-navigation-item>\n `;\n })}\n </div>\n `\n : nothing\n }\n <div class=\"button-container\">\n <obc-button\n variant=${ButtonVariant.normal}\n fullWidth\n @click=${this.handleSignOutClick}\n >\n ${msg('Sign out')}\n </obc-button>\n </div>\n `;\n }\n\n private renderSignedInSmall() {\n const primaryAction = this.signedInActions.find(\n (action) => action.id === this.primaryActionId\n );\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('User')}</h3>\n </div>\n <div class=\"user-container\">\n ${this.renderUserProfile('horizontal', 'regular')}\n </div>\n <div class=\"button-container\">\n ${\n primaryAction\n ? html`\n <obc-button\n variant=${ButtonVariant.normal}\n fullWidth\n @click=${() => this.handleSignedInActionClick(primaryAction)}\n >\n ${primaryAction.label}\n </obc-button>\n `\n : nothing\n }\n <obc-button\n variant=${ButtonVariant.normal}\n fullWidth\n @click=${this.handleSignOutClick}\n >\n ${msg('Sign out')}\n </obc-button>\n </div>\n `;\n }\n\n override render() {\n let content: TemplateResult | symbol = nothing;\n if (this.type === ObcUserMenuType.signIn) {\n content =\n this.size === ObcUserMenuSize.small\n ? this.renderSignInSmall()\n : this.renderSignIn();\n }\n if (this.type === ObcUserMenuType.userSignIn) {\n content =\n this.size === ObcUserMenuSize.small\n ? this.renderUserSignInSmall()\n : this.renderUserSignIn();\n }\n if (this.type === ObcUserMenuType.loadingSignIn) {\n content =\n this.size === ObcUserMenuSize.small\n ? this.renderLoadingSignInSmall()\n : this.renderLoadingSignIn();\n }\n if (this.type === ObcUserMenuType.signedIn) {\n content =\n this.size === ObcUserMenuSize.small\n ? this.renderSignedInSmall()\n : this.renderSignedIn();\n }\n\n return html`\n <div\n class=${classMap({\n card: true,\n [`size-${this.size}`]: true,\n [`type-${this.type}`]: true,\n })}\n >\n ${content}\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-user-menu': ObcUserMenu;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"user-menu.js","names":[],"sources":["../../../src/components/user-menu/user-menu.ts"],"sourcesContent":["import {LitElement, TemplateResult, html, nothing, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {customElement} from '../../decorator.js';\nimport componentStyle from './user-menu.css?inline';\nimport '../text-input-field/text-input-field.js';\nimport '../button/button.js';\nimport '../user-button/user-button.js';\nimport '../progress-bar/progress-bar.js';\nimport '../navigation-item/navigation-item.js';\nimport '../../icons/icon-calendar-google.js';\nimport '../../icons/icon-log-open.js';\nimport '../../icons/icon-settings-iec.js';\nimport '../../icons/icon-user.js';\nimport {\n HTMLInputTypeAttribute,\n ObcTextInputFieldTextAlign,\n} from '../text-input-field/text-input-field.js';\nimport {ButtonVariant} from '../button/button.js';\nimport {\n ProgressBarMode,\n ProgressBarType,\n} from '../progress-bar/progress-bar.js';\nimport {Size, StyleType, Variant} from '../user-button/user-button.js';\nimport {localized, msg} from '@lit/localize';\nimport {stopPropagation} from '../../internal/events.js';\nimport {PopoverController} from '../../internal/popover-controller.js';\n\nexport enum ObcUserMenuType {\n signIn = 'sign-in',\n userSignIn = 'user-sign-in',\n loadingSignIn = 'loading-sign-in',\n signedIn = 'signed-in',\n}\n\nexport enum ObcUserMenuSize {\n regular = 'regular',\n small = 'small',\n}\n\nexport type ObcUserMenuUser = {\n initials: string;\n label: string;\n role?: string;\n};\n\nexport type ObcUserMenuRecentUserClickEvent = CustomEvent<ObcUserMenuUser>;\n\nexport type ObcUserMenuSignedInAction = {\n id: string;\n label: string;\n};\n\n/**\n * `<obc-user-menu>` – A user menu component with sign-in and signed-in layouts.\n *\n * Provides multiple layouts for authentication and account access states, including\n * sign-in forms, user-specific sign-in, loading states, and signed-in navigation.\n *\n * ### Features\n * - **Multiple States:** Supports sign-in, user sign-in, loading, and signed-in layouts.\n * - **Size Options:** Regular and small sizes for compact layouts.\n * - **Recent Users:** Optional \"Recently signed in\" section for quick access.\n * - **Navigation Actions:** Signed-in state lists the actions it is given.\n *\n * ### Variants\n * - `type`: `sign-in`, `user-sign-in`, `loading-sign-in`, `signed-in`\n * - `size`: `regular`, `small`\n *\n * ### Usage Guidelines\n * Use `obc-user-menu` in authentication or account panels where quick access to\n * sign-in, profile, or account actions is needed. The `user-sign-in` type is\n * best for fast re-auth flows; `loading-sign-in` is for pending auth states.\n *\n * ### Properties and Configuration\n * - `type` (`ObcUserMenuType`): Controls the layout state. Defaults to `sign-in`.\n * - `size` (`ObcUserMenuSize`): Controls the overall size. Defaults to `regular`.\n * - `hasRecentlySignedIn` (`boolean`): Toggles the recent users section.\n * Defaults to `false`.\n * - `showUsername` (`boolean`): Toggles the username field. Defaults to `true`.\n * - `showPassword` (`boolean`): Toggles the password field. Defaults to `true`.\n * - `username` (`string`): Current username value for sign-in layouts.\n * - `password` (`string`): Current password value for sign-in layouts.\n * - `usernameError` (`string`): Error message for the username field.\n * - `passwordError` (`string`): Error message for the password field.\n * - `userInitials` (`string`): Initials for the primary user profile.\n * - `userLabel` (`string`): Label for the primary user profile.\n * - `userRole` (`string`): Role shown under the primary user's label. Omit it\n * to show no role; only the regular size draws one.\n * - `recentUsers` (`ObcUserMenuUser[]`): List of recent users shown in the\n * \"Recently signed in\" section. Empty renders no section. Each user may\n * carry its own `role`.\n * - `showUseAnotherAccount` (`boolean`): Toggles the \"Use another account\"\n * button in the `user-sign-in` layouts, both sizes. Defaults to `true`.\n * - `signedInActions` (`ObcUserMenuSignedInAction[]`): Actions shown in the\n * signed-in navigation list. Empty renders no actions.\n * - `primaryActionId` (`string`): Id of the action promoted to a button in the\n * small signed-in layout.\n *\n * ### Events\n * - `sign-in-click` – Fired when a sign-in button is clicked.\n * - `sign-out-click` – Fired when the sign-out button is clicked.\n * - `use-another-account-click` – Fired when the \"Use another account\" button\n * is clicked. The menu does not change its own type; set it to `sign-in` in\n * the handler to show the full form.\n * - `signed-in-action-click` – Fired when a signed-in action is clicked.\n * - `recent-user-click` – Fired when a recent user button is clicked.\n *\n * ### Slots\n * - `signed-in-action-icon-{id}`: Optional icon for a signed-in action. The\n * `{id}` is the normalized action id.\n *\n * ### Example\n * ```html\n * <obc-user-menu\n * type=\"user-sign-in\"\n * size=\"small\"\n * hasRecentlySignedIn=\"false\"\n * userInitials=\"JD\"\n * userLabel=\"John Doe\"\n * ></obc-user-menu>\n * ```\n *\n * @property type - Controls the visual layout of the user menu.\n * @property size - Controls the overall size of the user menu.\n * @property hasRecentlySignedIn - Toggles the \"Recently signed in\" section visibility.\n * @availableWhen hasRecentlySignedIn type in [signIn, userSignIn]\n * @property username - Current username value for sign-in layouts.\n * @availableWhen username showUsername==true && type==signIn\n * @property password - Current password value for sign-in layouts.\n * @availableWhen password showPassword==true && type in [signIn, userSignIn]\n * @property usernameError - Error message for the username field.\n * @availableWhen usernameError type==signIn\n * @property passwordError - Error message for the password field.\n * @availableWhen passwordError type in [signIn, userSignIn]\n * @property userInitials - Initials for the primary user profile.\n * @availableWhen userInitials type!=signIn\n * @property userLabel - Label for the primary user profile.\n * @availableWhen userLabel type!=signIn\n * @property userRole - Role shown under the primary user's label; omit it to show no role.\n * @availableWhen userRole type!=signIn && size==regular\n * @property recentUsers - Recent users for the \"Recently signed in\" section.\n * @property signedInActions - Actions shown in the signed-in navigation list.\n * @availableWhen signedInActions type==signedIn\n * @property showUsername - Controls the visibility of the username field.\n * @availableWhen showUsername type==signIn\n * @property showPassword - Controls the visibility of the password field.\n * @availableWhen showPassword type in [signIn, userSignIn]\n * @property primaryActionId - Id of the action promoted to a button in the small signed-in layout.\n * @availableWhen primaryActionId type==signedIn && size==small\n * @property showUseAnotherAccount - Controls the visibility of the \"Use another account\" button.\n * @availableWhen showUseAnotherAccount type==userSignIn\n * @property softDismiss - Lets the menu close itself on a click outside it, on `Escape`, or when another menu opens. The page is covered while the menu is open, so the closing click reaches nothing there; only the top bar's strip stays clickable, which is how its buttons switch or close menus in one click. Wire it with three bindings: set `softDismiss`, bind `open` to a flag you keep, and reset that flag on `close`. The button that opens the menu needs no wiring of its own: flip the flag from its click, or from the button event of `obc-top-bar` or `obc-integration-bar`. The user menu's *Soft Dismiss From A Bar Button* story shows that wiring, the brilliance menu's *Soft Dismiss* story the one for a button you hold yourself (`bindPopoverTrigger`), and the vue demo runs its top bar this way. Leave it off to show and hide the menu yourself.\n * @property open - Whether the menu is showing. Bind it to a flag you keep rather than toggling it from the menu's own value: when the menu closes itself, `open` is written back to `false` before the button's click reaches your handler, so `menu.open = !menu.open` gets out of step. Reset the flag on `close`.\n * @availableWhen open softDismiss==true\n * @slot signed-in-action-icon-<id> - Optional icon for a signed-in action, one per action; `<id>` is the normalized action id (shown in the `signed-in` type).\n * @fires {CustomEvent<{username?: string, password?: string}>} sign-in-click - Fired when a sign-in button is clicked.\n * @fires {CustomEvent<void>} sign-out-click - Fired when the sign-out button is clicked.\n * @fires {CustomEvent<void>} use-another-account-click - Fired when the \"Use another account\" button is clicked.\n * @fires {CustomEvent<{id: string, label: string}>} signed-in-action-click - Fired when a signed-in action is clicked.\n * @fires {ObcUserMenuRecentUserClickEvent} recent-user-click - Fired when a recent user button is clicked, carrying that user's entry.\n * @fires {CustomEvent<void>} close - Fired when the menu closed on its own, from a click outside, `Escape`, or another menu opening. `open` is already `false` by the time it arrives; reset the flag you bind to `open` here, or the next click on the button finds it still set and asks a closed menu to close.\n * @stable\n */\n@customElement('obc-user-menu')\n@localized()\nexport class ObcUserMenu extends LitElement {\n @property({type: Boolean}) softDismiss = false;\n\n @property({type: Boolean}) open = false;\n\n protected readonly softDismissController = new PopoverController(this);\n\n @property({type: String}) type: ObcUserMenuType = ObcUserMenuType.signIn;\n\n @property({type: String}) size: ObcUserMenuSize = ObcUserMenuSize.regular;\n\n @property({type: Boolean})\n hasRecentlySignedIn = false;\n\n @property({type: Boolean, attribute: false})\n showUsername = true;\n\n @property({type: String}) username = '';\n\n @property({type: Boolean, attribute: false})\n showPassword = true;\n\n @property({type: String}) password = '';\n\n @property({type: String}) usernameError = '';\n\n @property({type: String}) passwordError = '';\n\n @property({type: String}) userInitials?: string;\n\n @property({type: String}) userLabel?: string;\n\n @property({type: String}) userRole?: string;\n\n @property({type: Array, attribute: false})\n recentUsers: ObcUserMenuUser[] = [];\n\n @property({type: Array, attribute: false})\n signedInActions: ObcUserMenuSignedInAction[] = [];\n\n @property({type: String}) primaryActionId?: string;\n\n @property({type: Boolean, attribute: false})\n showUseAnotherAccount = true;\n\n private get showRecentUsers() {\n return this.hasRecentlySignedIn && this.recentUsers.length > 0;\n }\n\n private renderTextInput(\n placeholder: string,\n type: HTMLInputTypeAttribute = HTMLInputTypeAttribute.Text,\n value = '',\n onInput?: (event: Event) => void,\n errorText = ''\n ) {\n const isPassword = type === HTMLInputTypeAttribute.Password;\n return html`\n <obc-text-input-field\n .placeholder=${placeholder}\n .type=${type}\n .textAlign=${ObcTextInputFieldTextAlign.Left}\n .value=${value}\n .error=${Boolean(errorText)}\n .errorText=${errorText}\n .required=${true}\n .hasClearButton=${!isPassword}\n @input=${onInput}\n @change=${stopPropagation}\n @clear=${stopPropagation}\n >\n </obc-text-input-field>\n `;\n }\n\n private renderUserButtons(count: number, isLarge: boolean) {\n const size = isLarge ? Size.large : Size.regular;\n const users = this.recentUsers.slice(0, count);\n return html`\n <div\n class=${classMap({\n users: true,\n large: isLarge,\n single: users.length === 1,\n })}\n >\n ${users.map(\n (user) => html`\n <obc-user-button\n .variant=${Variant.initials}\n .styleType=${StyleType.normal}\n .size=${size}\n .initials=${user.initials}\n .label=${user.label}\n .sublabel=${isLarge ? user.role : undefined}\n @click=${() => this.handleRecentUserClick(user)}\n ></obc-user-button>\n `\n )}\n </div>\n `;\n }\n\n private renderUserProfile(\n layout: 'vertical' | 'horizontal',\n size: 'large' | 'regular'\n ) {\n if (!this.userInitials && !this.userLabel) {\n return nothing;\n }\n const userButtonSize = size === 'large' ? Size.large : Size.regular;\n const role = size === 'large' ? this.userRole : undefined;\n return html`\n <div\n class=${classMap({\n 'user-profile': true,\n [layout]: true,\n })}\n >\n <obc-user-button\n class=${classMap({\n 'user-avatar': true,\n [`size-${size}`]: true,\n 'has-role': Boolean(role),\n })}\n .variant=${Variant.initials}\n .styleType=${StyleType.normal}\n .size=${userButtonSize}\n .initials=${this.userInitials ?? ''}\n .label=${this.userLabel ?? ''}\n .sublabel=${role}\n ></obc-user-button>\n </div>\n `;\n }\n\n private getSignedInActionIcon(actionId: string) {\n switch (actionId) {\n case 'calendar':\n return html`<obi-calendar-google></obi-calendar-google>`;\n case 'log':\n return html`<obi-log-open></obi-log-open>`;\n case 'preferences':\n return html`<obi-settings-iec></obi-settings-iec>`;\n case 'user-account':\n return html`<obi-user></obi-user>`;\n default:\n return nothing;\n }\n }\n\n private normalizeActionId(actionId: string) {\n return actionId\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-');\n }\n\n private handleSignedInActionClick(action: ObcUserMenuSignedInAction) {\n this.dispatchEvent(\n new CustomEvent('signed-in-action-click', {\n detail: {id: action.id, label: action.label},\n })\n );\n }\n\n private handleRecentUserClick(user: ObcUserMenuUser) {\n this.dispatchEvent(\n new CustomEvent<ObcUserMenuUser>('recent-user-click', {\n detail: {...user},\n })\n );\n }\n\n private handleUsernameInput(event: Event) {\n const target = event.target as {value?: string};\n this.username = target.value ?? '';\n if (this.username) {\n this.usernameError = '';\n }\n }\n\n private handlePasswordInput(event: Event) {\n const target = event.target as {value?: string};\n this.password = target.value ?? '';\n if (this.password) {\n this.passwordError = '';\n }\n }\n\n private validateSignIn() {\n let valid = true;\n const needsUsername =\n this.type === ObcUserMenuType.signIn && this.showUsername;\n const needsPassword = this.showPassword;\n\n if (needsUsername && !this.username) {\n this.usernameError = msg('Username is required');\n valid = false;\n }\n\n if (needsPassword && !this.password) {\n this.passwordError = msg('Password is required');\n valid = false;\n }\n\n return valid;\n }\n\n private handleSignInClick() {\n if (!this.validateSignIn()) {\n return;\n }\n this.dispatchEvent(\n new CustomEvent('sign-in-click', {\n detail: {\n username: this.showUsername ? this.username : undefined,\n password: this.showPassword ? this.password : undefined,\n },\n })\n );\n }\n\n private handleSignOutClick() {\n this.dispatchEvent(new CustomEvent('sign-out-click'));\n }\n\n private handleUseAnotherAccountClick() {\n this.dispatchEvent(new CustomEvent('use-another-account-click'));\n }\n\n private renderSignIn() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div\n class=${classMap({\n 'login-container': true,\n 'signin-only': !this.showRecentUsers,\n })}\n >\n ${\n this.showUsername\n ? this.renderTextInput(\n msg('Username'),\n HTMLInputTypeAttribute.Text,\n this.username,\n this.handleUsernameInput.bind(this),\n this.usernameError\n )\n : nothing\n }\n ${\n this.showPassword\n ? this.renderTextInput(\n msg('Password'),\n HTMLInputTypeAttribute.Password,\n this.password,\n this.handlePasswordInput.bind(this),\n this.passwordError\n )\n : nothing\n }\n <obc-button\n variant=${ButtonVariant.raised}\n fullWidth\n @click=${this.handleSignInClick}\n >\n ${msg('Sign in')}\n </obc-button>\n </div>\n ${\n this.showRecentUsers\n ? html`\n <div class=\"recent-container\">\n <div class=\"title-container\">\n <div class=\"subtitle\">${msg('Recently signed in')}</div>\n </div>\n <div class=\"actions-container\">\n ${this.renderUserButtons(3, true)}\n </div>\n </div>\n `\n : nothing\n }\n `;\n }\n\n private renderSignInSmall() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div\n class=${classMap({\n 'login-container': true,\n 'signin-only': !this.showRecentUsers,\n })}\n >\n ${\n this.showUsername\n ? this.renderTextInput(\n msg('Username'),\n HTMLInputTypeAttribute.Text,\n this.username,\n this.handleUsernameInput.bind(this),\n this.usernameError\n )\n : nothing\n }\n ${\n this.showPassword\n ? this.renderTextInput(\n msg('Password'),\n HTMLInputTypeAttribute.Password,\n this.password,\n this.handlePasswordInput.bind(this),\n this.passwordError\n )\n : nothing\n }\n <obc-button\n variant=${ButtonVariant.raised}\n fullWidth\n @click=${this.handleSignInClick}\n >\n ${msg('Sign in')}\n </obc-button>\n </div>\n ${\n this.showRecentUsers\n ? html`\n <div class=\"divider\" aria-hidden=\"true\"></div>\n <div class=\"recent-container recent\">\n <div class=\"title-container\">\n <div class=\"subtitle\">${msg('Recent')}</div>\n </div>\n <div class=\"actions-container\">\n ${this.renderUserButtons(3, false)}\n </div>\n </div>\n `\n : nothing\n }\n `;\n }\n\n private renderUserSignIn() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div\n class=${classMap({\n 'login-container': true,\n 'signin-only': !this.showRecentUsers,\n })}\n >\n <div class=\"user-primary\">\n ${this.renderUserProfile('vertical', 'large')}\n </div>\n <div class=\"fields\">\n ${\n this.showPassword\n ? this.renderTextInput(\n msg('Password'),\n HTMLInputTypeAttribute.Password,\n this.password,\n this.handlePasswordInput.bind(this),\n this.passwordError\n )\n : nothing\n }\n <obc-button\n variant=${ButtonVariant.raised}\n fullWidth\n @click=${this.handleSignInClick}\n >\n ${msg('Sign in')}\n </obc-button>\n ${\n this.showUseAnotherAccount\n ? html`\n <obc-button\n variant=${ButtonVariant.normal}\n fullWidth\n @click=${this.handleUseAnotherAccountClick}\n >\n ${msg('Use another account')}\n </obc-button>\n `\n : nothing\n }\n </div>\n </div>\n ${\n this.showRecentUsers\n ? html`\n <div class=\"recent-container\">\n <div class=\"title-container\">\n <div class=\"subtitle\">${msg('Recently signed in')}</div>\n </div>\n <div class=\"actions-container\">\n ${this.renderUserButtons(3, true)}\n </div>\n </div>\n `\n : nothing\n }\n `;\n }\n\n private renderUserSignInSmall() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div class=\"user-container\">\n ${this.renderUserProfile('horizontal', 'regular')}\n </div>\n <div\n class=${classMap({\n 'login-container': true,\n 'signin-only': !this.showRecentUsers,\n })}\n >\n ${\n this.showPassword\n ? this.renderTextInput(\n msg('Password'),\n HTMLInputTypeAttribute.Password,\n this.password,\n this.handlePasswordInput.bind(this),\n this.passwordError\n )\n : nothing\n }\n <obc-button\n variant=${ButtonVariant.raised}\n fullWidth\n @click=${this.handleSignInClick}\n >\n ${msg('Sign in')}\n </obc-button>\n ${\n this.showUseAnotherAccount\n ? html`\n <obc-button\n variant=${ButtonVariant.normal}\n fullWidth\n @click=${this.handleUseAnotherAccountClick}\n >\n ${msg('Use another account')}\n </obc-button>\n `\n : nothing\n }\n </div>\n ${\n this.showRecentUsers\n ? html`\n <div class=\"divider\" aria-hidden=\"true\"></div>\n <div class=\"recent-container recent\">\n <div class=\"title-container\">\n <div class=\"subtitle\">${msg('Recent')}</div>\n </div>\n <div class=\"actions-container\">\n ${this.renderUserButtons(3, false)}\n </div>\n </div>\n `\n : nothing\n }\n `;\n }\n\n private renderLoadingSignIn() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div class=\"user-primary loading\">\n ${this.renderUserProfile('vertical', 'large')}\n <obc-progress-bar\n class=\"progress\"\n type=${ProgressBarType.linear}\n mode=${ProgressBarMode.indeterminate}\n .showValue=${false}\n ></obc-progress-bar>\n </div>\n `;\n }\n\n private renderLoadingSignInSmall() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('Sign in')}</h3>\n </div>\n <div class=\"user-primary loading\">\n ${this.renderUserProfile('horizontal', 'regular')}\n <obc-progress-bar\n class=\"progress\"\n type=${ProgressBarType.linear}\n mode=${ProgressBarMode.indeterminate}\n .showValue=${false}\n ></obc-progress-bar>\n </div>\n `;\n }\n\n private renderSignedIn() {\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('User')}</h3>\n </div>\n <div class=\"user-primary signed-in\">\n ${this.renderUserProfile('vertical', 'large')}\n </div>\n <div class=\"divider\" aria-hidden=\"true\"></div>\n ${\n this.signedInActions.length\n ? html`\n <div class=\"nav-container\">\n ${this.signedInActions.map((action) => {\n const normalizedId = this.normalizeActionId(action.id);\n return html`\n <obc-navigation-item\n .label=${action.label}\n hasIcon\n @click=${() => this.handleSignedInActionClick(action)}\n >\n <span slot=\"icon\">\n <slot name=\"signed-in-action-icon-${normalizedId}\">\n ${this.getSignedInActionIcon(normalizedId)}\n </slot>\n </span>\n </obc-navigation-item>\n `;\n })}\n </div>\n `\n : nothing\n }\n <div class=\"button-container\">\n <obc-button\n variant=${ButtonVariant.normal}\n fullWidth\n @click=${this.handleSignOutClick}\n >\n ${msg('Sign out')}\n </obc-button>\n </div>\n `;\n }\n\n private renderSignedInSmall() {\n const primaryAction = this.signedInActions.find(\n (action) => action.id === this.primaryActionId\n );\n return html`\n <div class=\"title-container\">\n <h3 class=\"title\">${msg('User')}</h3>\n </div>\n <div class=\"user-container\">\n ${this.renderUserProfile('horizontal', 'regular')}\n </div>\n <div class=\"button-container\">\n ${\n primaryAction\n ? html`\n <obc-button\n variant=${ButtonVariant.normal}\n fullWidth\n @click=${() => this.handleSignedInActionClick(primaryAction)}\n >\n ${primaryAction.label}\n </obc-button>\n `\n : nothing\n }\n <obc-button\n variant=${ButtonVariant.normal}\n fullWidth\n @click=${this.handleSignOutClick}\n >\n ${msg('Sign out')}\n </obc-button>\n </div>\n `;\n }\n\n override render() {\n let content: TemplateResult | symbol = nothing;\n if (this.type === ObcUserMenuType.signIn) {\n content =\n this.size === ObcUserMenuSize.small\n ? this.renderSignInSmall()\n : this.renderSignIn();\n }\n if (this.type === ObcUserMenuType.userSignIn) {\n content =\n this.size === ObcUserMenuSize.small\n ? this.renderUserSignInSmall()\n : this.renderUserSignIn();\n }\n if (this.type === ObcUserMenuType.loadingSignIn) {\n content =\n this.size === ObcUserMenuSize.small\n ? this.renderLoadingSignInSmall()\n : this.renderLoadingSignIn();\n }\n if (this.type === ObcUserMenuType.signedIn) {\n content =\n this.size === ObcUserMenuSize.small\n ? this.renderSignedInSmall()\n : this.renderSignedIn();\n }\n\n return html`\n <div\n class=${classMap({\n card: true,\n [`size-${this.size}`]: true,\n [`type-${this.type}`]: true,\n })}\n >\n ${content}\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-user-menu': ObcUserMenu;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA4BA,IAAY,kBAAL,yBAAA,iBAAA;CACL,gBAAA,YAAA;CACA,gBAAA,gBAAA;CACA,gBAAA,mBAAA;CACA,gBAAA,cAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAY,kBAAL,yBAAA,iBAAA;CACL,gBAAA,aAAA;CACA,gBAAA,WAAA;;AACF,EAAA,CAAA,CAAA;AAgIO,IAAM,cAAN,MAAM,oBAAoB,WAAW;;;EACD,KAAA,cAAA;EAEP,KAAA,OAAA;EAES,KAAA,wBAAA,IAAI,kBAAkB,IAAI;;;EAO/C,KAAA,sBAAA;EAGP,KAAA,eAAA;EAEsB,KAAA,WAAA;EAGtB,KAAA,eAAA;EAEsB,KAAA,WAAA;EAEK,KAAA,gBAAA;EAEA,KAAA,gBAAA;EAST,KAAA,cAAA,CAAC;EAGa,KAAA,kBAAA,CAAC;EAKxB,KAAA,wBAAA;;CAExB,IAAY,kBAAkB;EAC5B,OAAO,KAAK,uBAAuB,KAAK,YAAY,SAAS;CAC/D;CAEA,gBACE,aACA,OAA+B,uBAAuB,MACtD,QAAQ,IACR,SACA,YAAY,IACZ;EACA,MAAM,aAAa,SAAS,uBAAuB;EACnD,OAAO,IAAI;;uBAEQ,YAAY;gBACnB,KAAK;qBACA,2BAA2B,KAAK;iBACpC,MAAM;iBACN,QAAQ,SAAS,EAAE;qBACf,UAAU;oBACX,KAAK;0BACC,CAAC,WAAW;iBACrB,QAAQ;kBACP,gBAAgB;iBACjB,gBAAgB;;;;CAI/B;CAEA,kBAA0B,OAAe,SAAkB;EACzD,MAAM,OAAO,UAAU,KAAK,QAAQ,KAAK;EACzC,MAAM,QAAQ,KAAK,YAAY,MAAM,GAAG,KAAK;EAC7C,OAAO,IAAI;;gBAEC,SAAS;GACf,OAAO;GACP,OAAO;GACP,QAAQ,MAAM,WAAW;EAC3B,CAAC,EAAE;;UAED,MAAM,KACL,SAAS,IAAI;;yBAEC,QAAQ,SAAS;2BACf,UAAU,OAAO;sBACtB,KAAK;0BACD,KAAK,SAAS;uBACjB,KAAK,MAAM;0BACR,UAAU,KAAK,OAAO,KAAA,EAAU;6BAC7B,KAAK,sBAAsB,IAAI,EAAE;;WAGtD,EAAE;;;CAGR;CAEA,kBACE,QACA,MACA;EACA,IAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,WAC9B,OAAO;EAET,MAAM,iBAAiB,SAAS,UAAU,KAAK,QAAQ,KAAK;EAC5D,MAAM,OAAO,SAAS,UAAU,KAAK,WAAW,KAAA;EAChD,OAAO,IAAI;;gBAEC,SAAS;GACf,gBAAgB;IACf,SAAS;EACZ,CAAC,EAAE;;;kBAGO,SAAS;GACf,eAAe;IACd,QAAQ,SAAS;GAClB,YAAY,QAAQ,IAAI;EAC1B,CAAC,EAAE;qBACQ,QAAQ,SAAS;uBACf,UAAU,OAAO;kBACtB,eAAe;sBACX,KAAK,gBAAgB,GAAG;mBAC3B,KAAK,aAAa,GAAG;sBAClB,KAAK;;;;CAIzB;CAEA,sBAA8B,UAAkB;EAC9C,QAAQ,UAAR;GACE,KAAK,YACH,OAAO,IAAI;GACb,KAAK,OACH,OAAO,IAAI;GACb,KAAK,eACH,OAAO,IAAI;GACb,KAAK,gBACH,OAAO,IAAI;GACb,SACE,OAAO;EACX;CACF;CAEA,kBAA0B,UAAkB;EAC1C,OAAO,SACJ,KAAK,CAAC,CACN,YAAY,CAAC,CACb,QAAQ,eAAe,GAAG;CAC/B;CAEA,0BAAkC,QAAmC;EACnE,KAAK,cACH,IAAI,YAAY,0BAA0B,EACxC,QAAQ;GAAC,IAAI,OAAO;GAAI,OAAO,OAAO;EAAK,EAC7C,CAAC,CACH;CACF;CAEA,sBAA8B,MAAuB;EACnD,KAAK,cACH,IAAI,YAA6B,qBAAqB,EACpD,QAAQ,EAAC,GAAG,KAAI,EAClB,CAAC,CACH;CACF;CAEA,oBAA4B,OAAc;EACxC,MAAM,SAAS,MAAM;EACrB,KAAK,WAAW,OAAO,SAAS;EAChC,IAAI,KAAK,UACP,KAAK,gBAAgB;CAEzB;CAEA,oBAA4B,OAAc;EACxC,MAAM,SAAS,MAAM;EACrB,KAAK,WAAW,OAAO,SAAS;EAChC,IAAI,KAAK,UACP,KAAK,gBAAgB;CAEzB;CAEA,iBAAyB;EACvB,IAAI,QAAQ;EACZ,MAAM,gBACJ,KAAK,SAAA,aAAmC,KAAK;EAC/C,MAAM,gBAAgB,KAAK;EAE3B,IAAI,iBAAiB,CAAC,KAAK,UAAU;GACnC,KAAK,gBAAgB,IAAI,sBAAsB;GAC/C,QAAQ;EACV;EAEA,IAAI,iBAAiB,CAAC,KAAK,UAAU;GACnC,KAAK,gBAAgB,IAAI,sBAAsB;GAC/C,QAAQ;EACV;EAEA,OAAO;CACT;CAEA,oBAA4B;EAC1B,IAAI,CAAC,KAAK,eAAe,GACvB;EAEF,KAAK,cACH,IAAI,YAAY,iBAAiB,EAC/B,QAAQ;GACN,UAAU,KAAK,eAAe,KAAK,WAAW,KAAA;GAC9C,UAAU,KAAK,eAAe,KAAK,WAAW,KAAA;EAChD,EACF,CAAC,CACH;CACF;CAEA,qBAA6B;EAC3B,KAAK,cAAc,IAAI,YAAY,gBAAgB,CAAC;CACtD;CAEA,+BAAuC;EACrC,KAAK,cAAc,IAAI,YAAY,2BAA2B,CAAC;CACjE;CAEA,eAAuB;EACrB,OAAO,IAAI;;4BAEa,IAAI,SAAS,EAAE;;;gBAG3B,SAAS;GACf,mBAAmB;GACnB,eAAe,CAAC,KAAK;EACvB,CAAC,EAAE;;UAGD,KAAK,eACD,KAAK,gBACH,IAAI,UAAU,GACd,uBAAuB,MACvB,KAAK,UACL,KAAK,oBAAoB,KAAK,IAAI,GAClC,KAAK,aACP,IACA,QACL;UAEC,KAAK,eACD,KAAK,gBACH,IAAI,UAAU,GACd,uBAAuB,UACvB,KAAK,UACL,KAAK,oBAAoB,KAAK,IAAI,GAClC,KAAK,aACP,IACA,QACL;;oBAEW,cAAc,OAAO;;mBAEtB,KAAK,kBAAkB;;YAE9B,IAAI,SAAS,EAAE;;;QAInB,KAAK,kBACD,IAAI;;;0CAG0B,IAAI,oBAAoB,EAAE;;;oBAGhD,KAAK,kBAAkB,GAAG,IAAI,EAAE;;;gBAIxC,QACL;;CAEL;CAEA,oBAA4B;EAC1B,OAAO,IAAI;;4BAEa,IAAI,SAAS,EAAE;;;gBAG3B,SAAS;GACf,mBAAmB;GACnB,eAAe,CAAC,KAAK;EACvB,CAAC,EAAE;;UAGD,KAAK,eACD,KAAK,gBACH,IAAI,UAAU,GACd,uBAAuB,MACvB,KAAK,UACL,KAAK,oBAAoB,KAAK,IAAI,GAClC,KAAK,aACP,IACA,QACL;UAEC,KAAK,eACD,KAAK,gBACH,IAAI,UAAU,GACd,uBAAuB,UACvB,KAAK,UACL,KAAK,oBAAoB,KAAK,IAAI,GAClC,KAAK,aACP,IACA,QACL;;oBAEW,cAAc,OAAO;;mBAEtB,KAAK,kBAAkB;;YAE9B,IAAI,SAAS,EAAE;;;QAInB,KAAK,kBACD,IAAI;;;;0CAI0B,IAAI,QAAQ,EAAE;;;oBAGpC,KAAK,kBAAkB,GAAG,KAAK,EAAE;;;gBAIzC,QACL;;CAEL;CAEA,mBAA2B;EACzB,OAAO,IAAI;;4BAEa,IAAI,SAAS,EAAE;;;gBAG3B,SAAS;GACf,mBAAmB;GACnB,eAAe,CAAC,KAAK;EACvB,CAAC,EAAE;;;YAGC,KAAK,kBAAkB,YAAY,OAAO,EAAE;;;YAI5C,KAAK,eACD,KAAK,gBACH,IAAI,UAAU,GACd,uBAAuB,UACvB,KAAK,UACL,KAAK,oBAAoB,KAAK,IAAI,GAClC,KAAK,aACP,IACA,QACL;;sBAEW,cAAc,OAAO;;qBAEtB,KAAK,kBAAkB;;cAE9B,IAAI,SAAS,EAAE;;YAGjB,KAAK,wBACD,IAAI;;8BAEU,cAAc,OAAO;;6BAEtB,KAAK,6BAA6B;;sBAEzC,IAAI,qBAAqB,EAAE;;oBAGjC,QACL;;;QAIH,KAAK,kBACD,IAAI;;;0CAG0B,IAAI,oBAAoB,EAAE;;;oBAGhD,KAAK,kBAAkB,GAAG,IAAI,EAAE;;;gBAIxC,QACL;;CAEL;CAEA,wBAAgC;EAC9B,OAAO,IAAI;;4BAEa,IAAI,SAAS,EAAE;;;UAGjC,KAAK,kBAAkB,cAAc,SAAS,EAAE;;;gBAG1C,SAAS;GACf,mBAAmB;GACnB,eAAe,CAAC,KAAK;EACvB,CAAC,EAAE;;UAGD,KAAK,eACD,KAAK,gBACH,IAAI,UAAU,GACd,uBAAuB,UACvB,KAAK,UACL,KAAK,oBAAoB,KAAK,IAAI,GAClC,KAAK,aACP,IACA,QACL;;oBAEW,cAAc,OAAO;;mBAEtB,KAAK,kBAAkB;;YAE9B,IAAI,SAAS,EAAE;;UAGjB,KAAK,wBACD,IAAI;;4BAEU,cAAc,OAAO;;2BAEtB,KAAK,6BAA6B;;oBAEzC,IAAI,qBAAqB,EAAE;;kBAGjC,QACL;;QAGD,KAAK,kBACD,IAAI;;;;0CAI0B,IAAI,QAAQ,EAAE;;;oBAGpC,KAAK,kBAAkB,GAAG,KAAK,EAAE;;;gBAIzC,QACL;;CAEL;CAEA,sBAA8B;EAC5B,OAAO,IAAI;;4BAEa,IAAI,SAAS,EAAE;;;UAGjC,KAAK,kBAAkB,YAAY,OAAO,EAAE;;;iBAGrC,gBAAgB,OAAO;iBACvB,gBAAgB,cAAc;uBACxB,MAAM;;;;CAI3B;CAEA,2BAAmC;EACjC,OAAO,IAAI;;4BAEa,IAAI,SAAS,EAAE;;;UAGjC,KAAK,kBAAkB,cAAc,SAAS,EAAE;;;iBAGzC,gBAAgB,OAAO;iBACvB,gBAAgB,cAAc;uBACxB,MAAM;;;;CAI3B;CAEA,iBAAyB;EACvB,OAAO,IAAI;;4BAEa,IAAI,MAAM,EAAE;;;UAG9B,KAAK,kBAAkB,YAAY,OAAO,EAAE;;;QAI9C,KAAK,gBAAgB,SACjB,IAAI;;kBAEE,KAAK,gBAAgB,KAAK,WAAW;GACrC,MAAM,eAAe,KAAK,kBAAkB,OAAO,EAAE;GACrD,OAAO,IAAI;;+BAEE,OAAO,MAAM;;qCAEP,KAAK,0BAA0B,MAAM,EAAE;;;4DAGhB,aAAa;4BAC7C,KAAK,sBAAsB,YAAY,EAAE;;;;;EAKrD,CAAC,EAAE;;gBAGP,QACL;;;oBAGa,cAAc,OAAO;;mBAEtB,KAAK,mBAAmB;;YAE/B,IAAI,UAAU,EAAE;;;;CAI1B;CAEA,sBAA8B;EAC5B,MAAM,gBAAgB,KAAK,gBAAgB,MACxC,WAAW,OAAO,OAAO,KAAK,eACjC;EACA,OAAO,IAAI;;4BAEa,IAAI,MAAM,EAAE;;;UAG9B,KAAK,kBAAkB,cAAc,SAAS,EAAE;;;UAIhD,gBACI,IAAI;;4BAEU,cAAc,OAAO;;iCAEhB,KAAK,0BAA0B,aAAa,EAAE;;oBAE3D,cAAc,MAAM;;kBAG1B,QACL;;oBAEW,cAAc,OAAO;;mBAEtB,KAAK,mBAAmB;;YAE/B,IAAI,UAAU,EAAE;;;;CAI1B;CAEA,SAAkB;EAChB,IAAI,UAAmC;EACvC,IAAI,KAAK,SAAA,WACP,UACE,KAAK,SAAA,UACD,KAAK,kBAAkB,IACvB,KAAK,aAAa;EAE1B,IAAI,KAAK,SAAA,gBACP,UACE,KAAK,SAAA,UACD,KAAK,sBAAsB,IAC3B,KAAK,iBAAiB;EAE9B,IAAI,KAAK,SAAA,mBACP,UACE,KAAK,SAAA,UACD,KAAK,yBAAyB,IAC9B,KAAK,oBAAoB;EAEjC,IAAI,KAAK,SAAA,aACP,UACE,KAAK,SAAA,UACD,KAAK,oBAAoB,IACzB,KAAK,eAAe;EAG5B,OAAO,IAAI;;gBAEC,SAAS;GACf,MAAM;IACL,QAAQ,KAAK,SAAS;IACtB,QAAQ,KAAK,SAAS;EACzB,CAAC,EAAE;;UAED,QAAQ;;;CAGhB;;EAEyB,KAAA,SAAA,UAAU,iBAAc;;AACnD;AAxnBG,WAAA,CAAA,SAAS,EAAC,MAAM,QAAO,CAAC,CAAA,GAAA,YAAA,WAAA,eAAA,KAAA,CAAA;AAExB,WAAA,CAAA,SAAS,EAAC,MAAM,QAAO,CAAC,CAAA,GAAA,YAAA,WAAA,QAAA,KAAA,CAAA;AAIxB,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,YAAA,WAAA,QAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,YAAA,WAAA,QAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS,EAAC,MAAM,QAAO,CAAC,CAAA,GAAA,YAAA,WAAA,uBAAA,KAAA,CAAA;AAGxB,WAAA,CAAA,SAAS;CAAC,MAAM;CAAS,WAAW;AAAK,CAAC,CAAA,GAAA,YAAA,WAAA,gBAAA,KAAA,CAAA;AAG1C,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,YAAA,WAAA,YAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS;CAAC,MAAM;CAAS,WAAW;AAAK,CAAC,CAAA,GAAA,YAAA,WAAA,gBAAA,KAAA,CAAA;AAG1C,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,YAAA,WAAA,YAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,YAAA,WAAA,iBAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,YAAA,WAAA,iBAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,YAAA,WAAA,gBAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,YAAA,WAAA,aAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,YAAA,WAAA,YAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS;CAAC,MAAM;CAAO,WAAW;AAAK,CAAC,CAAA,GAAA,YAAA,WAAA,eAAA,KAAA,CAAA;AAGxC,WAAA,CAAA,SAAS;CAAC,MAAM;CAAO,WAAW;AAAK,CAAC,CAAA,GAAA,YAAA,WAAA,mBAAA,KAAA,CAAA;AAGxC,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,YAAA,WAAA,mBAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS;CAAC,MAAM;CAAS,WAAW;AAAK,CAAC,CAAA,GAAA,YAAA,WAAA,yBAAA,KAAA,CAAA;AA5C5C,cAAA,WAAA,CAAA,cAAc,eAAe,GAC7B,UAAU,CAAA,GAAA,WAAA"}
|
|
@@ -123,6 +123,10 @@ export declare class PopoverController implements ReactiveController {
|
|
|
123
123
|
*
|
|
124
124
|
* HTML can pair a button with a popover on its own, but only inside the same
|
|
125
125
|
* component. Reach for this when the button and the menu live apart.
|
|
126
|
+
*
|
|
127
|
+
* A bar that reports its buttons as events, `obc-top-bar` or
|
|
128
|
+
* `obc-integration-bar`, needs none of this: flip a flag of your own from the
|
|
129
|
+
* event, bind it to `open` and reset it on `close`.
|
|
126
130
|
*/
|
|
127
131
|
export declare function bindPopoverTrigger(trigger: HTMLElement, panel: SoftDismissHost): () => void;
|
|
128
132
|
//# sourceMappingURL=popover-controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popover-controller.d.ts","sourceRoot":"","sources":["../../src/internal/popover-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAE,kBAAkB,EAAC,MAAM,KAAK,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,wEAAwE;IACxE,WAAW,EAAE,OAAO,CAAC;IACrB,wEAAwE;IACxE,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,iBAAkB,YAAW,kBAAkB;IAa9C,OAAO,CAAC,QAAQ,CAAC,IAAI;IAZjC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,CAAc;IAC/B,2EAA2E;IAC3E,OAAO,CAAC,SAAS,CAAS;IAC1B;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAS;gBAEI,IAAI,EAAE,eAAe;IAIlD,aAAa,IAAI,IAAI;IAQrB,WAAW,IAAI,IAAI;IAInB,gBAAgB,IAAI,IAAI;IAMxB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAkB7B;IAEF;;;;;;;;;OASG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAavB;IAEF,OAAO,CAAC,IAAI;IAiCZ;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,WAAW;CAiBpB;AAED
|
|
1
|
+
{"version":3,"file":"popover-controller.d.ts","sourceRoot":"","sources":["../../src/internal/popover-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAE,kBAAkB,EAAC,MAAM,KAAK,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,wEAAwE;IACxE,WAAW,EAAE,OAAO,CAAC;IACrB,wEAAwE;IACxE,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,iBAAkB,YAAW,kBAAkB;IAa9C,OAAO,CAAC,QAAQ,CAAC,IAAI;IAZjC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,CAAc;IAC/B,2EAA2E;IAC3E,OAAO,CAAC,SAAS,CAAS;IAC1B;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAS;gBAEI,IAAI,EAAE,eAAe;IAIlD,aAAa,IAAI,IAAI;IAQrB,WAAW,IAAI,IAAI;IAInB,gBAAgB,IAAI,IAAI;IAMxB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAkB7B;IAEF;;;;;;;;;OASG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAavB;IAEF,OAAO,CAAC,IAAI;IAiCZ;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,WAAW;CAiBpB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,eAAe,GACrB,MAAM,IAAI,CAwBZ"}
|
|
@@ -148,6 +148,10 @@ var PopoverController = class {
|
|
|
148
148
|
*
|
|
149
149
|
* HTML can pair a button with a popover on its own, but only inside the same
|
|
150
150
|
* component. Reach for this when the button and the menu live apart.
|
|
151
|
+
*
|
|
152
|
+
* A bar that reports its buttons as events, `obc-top-bar` or
|
|
153
|
+
* `obc-integration-bar`, needs none of this: flip a flag of your own from the
|
|
154
|
+
* event, bind it to `open` and reset it on `close`.
|
|
151
155
|
*/
|
|
152
156
|
function bindPopoverTrigger(trigger, panel) {
|
|
153
157
|
let openBeforeAutoClose = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popover-controller.js","names":[],"sources":["../../src/internal/popover-controller.ts"],"sourcesContent":["import type {LitElement, ReactiveController} from 'lit';\n\n/**\n * What {@link PopoverController} needs a component to have.\n *\n * `softDismiss` has to be something a component opts into. The browser hides\n * a popover until it is opened, so switching this on for everyone would make\n * every menu that a consumer already shows and positions disappear.\n */\nexport interface SoftDismissHost extends LitElement {\n /** Let the browser take over showing, hiding and closing this panel. */\n softDismiss: boolean;\n /** Whether the panel is showing. Only used when `softDismiss` is on. */\n open: boolean;\n}\n\n/**\n * Lets a menu close itself the way people expect (#1293).\n *\n * Click outside an open menu and it should go away — and that click should\n * do nothing else. So should pressing `Escape`. The browser does most of\n * this on its own for an element marked as a popover, which is what this\n * controller switches on, and it brings two things that are hard to get\n * right by hand: focus returns to the button that opened the menu, and the\n * menu is drawn above the rest of the page whatever its container does with\n * `overflow`, `transform` or `z-index`.\n *\n * The one thing the browser will not do is swallow that outside click: left\n * alone it closes the menu *and* presses whatever was underneath. So the\n * controller gives the menu a see-through cover over the page, kept behind\n * the menu's own content. The menu is drawn above everything else on the\n * page, so its cover is too: clicks and hovers land on the cover instead of\n * the page, and the cover closes the menu.\n *\n * The cover starts below the top bar, so the bar itself stays usable while a\n * menu is open and moving from one menu to the next is a single click. Its\n * top edge is `--topbar-height`, falling back to the top bar's size token; an\n * app without a top bar sets that to `0`. Consumers can also restyle or tint\n * it through `::part(backdrop)`.\n *\n * A component keeps `open` as the property people set. Since the browser can\n * also open and close the menu on its own, the controller writes what the\n * browser did back into `open`, and fires `close` when the menu went away by\n * itself. Skip that and the property drifts out of step with what is on\n * screen, and the next render closes a menu that was just opened.\n *\n * The button that opens the menu usually belongs to whoever is using the\n * component, not to the component itself, so wiring it up is\n * {@link bindPopoverTrigger}'s job.\n */\nexport class PopoverController implements ReactiveController {\n private installed = false;\n private backdrop?: HTMLElement;\n /** Noted at a close that `open` did not ask for, so it can be reported. */\n private dismissed = false;\n /**\n * True from `beforetoggle` to `toggle`, while the browser is mid-way through\n * opening or closing. `sync()` stands down for that stretch: it would see\n * `open` already updated but the menu not yet moved, and try to move it\n * itself — nested inside the move the browser is making.\n */\n private toggling = false;\n\n constructor(private readonly host: SoftDismissHost) {\n host.addController(this);\n }\n\n hostConnected(): void {\n this.host.addEventListener('beforetoggle', this.onBeforeToggle);\n this.host.addEventListener('toggle', this.onToggle);\n if (this.host.hasUpdated) {\n this.sync();\n }\n }\n\n hostUpdated(): void {\n this.sync();\n }\n\n hostDisconnected(): void {\n this.host.removeEventListener('beforetoggle', this.onBeforeToggle);\n this.host.removeEventListener('toggle', this.onToggle);\n this.toggling = false;\n }\n\n /**\n * The menu is about to open or close for a reason other than `open` being\n * set — a button wired straight to it, `Escape`, a click on the cover, a\n * direct `showPopover()`. `open` is brought into line here, at once.\n *\n * The browser offers two events for this and only `beforetoggle` arrives\n * in time. It fires during the call that opens or closes the menu, while\n * `toggle` waits its turn in the queue. A re-render can get in before that\n * turn, read an `open` that still says the old thing, and undo what just\n * happened — close a menu that was just opened, or reopen one that was\n * just closed.\n */\n private readonly onBeforeToggle = (event: Event): void => {\n if (!this.host.softDismiss) return;\n this.toggling = true;\n // `toggle` clears this. Should it never come — someone cancelled the\n // opening — the flag must not stay up, or `open` could never drive the\n // menu again. A timer runs after the browser has finished either way.\n setTimeout(() => {\n this.toggling = false;\n }, 0);\n if ((event as ToggleEvent).newState === 'open') {\n this.ensureCover();\n this.host.open = true;\n return;\n }\n // `open` is already false when this controller asked for the close;\n // still true means somebody else did, and the consumer should hear.\n this.dismissed = this.host.open;\n this.host.open = false;\n };\n\n /**\n * The menu has closed. Report it only when `open` did not ask for it.\n *\n * By now `open` is `false` either way — `beforetoggle` saw to that — so\n * the note it left in `dismissed` is what tells the two apart.\n *\n * The `softDismiss` check keeps this out of the way of components that run\n * a popover themselves. `obc-menu-button` does that with\n * `obc-context-menu-input`, and those closes are its business.\n */\n private readonly onToggle = (event: Event): void => {\n if (!this.host.softDismiss) return;\n this.toggling = false;\n if ((event as ToggleEvent).newState !== 'closed') return;\n if (!this.dismissed) return;\n this.dismissed = false;\n /**\n * Fired when the popover closed on its own — a click outside, `Escape`,\n * or another popover opening.\n * @event close\n * @type {CustomEvent<void>}\n */\n this.host.dispatchEvent(new CustomEvent('close'));\n };\n\n private sync(): void {\n const host = this.host;\n\n if (!host.softDismiss) {\n if (this.installed) {\n // Dropping the attribute puts the component back to an ordinary\n // element, which is what it was before opting in.\n host.removeAttribute('popover');\n this.installed = false;\n this.backdrop?.remove();\n this.backdrop = undefined;\n }\n return;\n }\n\n if (!this.installed) {\n host.setAttribute('popover', 'auto');\n this.installed = true;\n this.ensureCover();\n }\n\n // Showing a popover that is not on the page throws.\n if (!host.isConnected) return;\n if (this.toggling) return;\n\n const isOpen = host.matches(':popover-open');\n if (host.open && !isOpen) {\n host.showPopover();\n } else if (!host.open && isOpen) {\n host.hidePopover();\n }\n }\n\n /**\n * The see-through cover that swallows clicks while the menu is open.\n *\n * It is an ordinary child of the menu, not a popover of its own: the\n * browser refuses to show one popover while another is on its way up, so\n * the cover cannot be a popover shown as the menu opens. It does not need\n * to be. The menu is drawn above the whole page, so a child of the menu\n * that reaches over the page is drawn above the page as well, and a\n * negative `z-index` keeps it behind the menu's own content. It shows and\n * hides with the menu and never has to be told.\n *\n * Being inside the menu also means the browser treats a click on it as a\n * click *inside* the menu and leaves the menu open — so the cover closes\n * the menu itself.\n */\n private ensureCover(): void {\n const root = this.host.shadowRoot;\n if (!root || this.backdrop) return;\n const cover = document.createElement('div');\n cover.setAttribute('part', 'backdrop');\n // The last fallback keeps the whole page covered where no palette is\n // loaded; an `auto` top would leave the cover wherever it happened to\n // land.\n cover.style.cssText =\n 'position:fixed;' +\n 'top:var(--topbar-height,var(--app-components-topbar-touch-target-size,0px));' +\n 'right:0;bottom:0;left:0;z-index:-1;margin:0;padding:0;border:0;' +\n 'background:transparent';\n cover.addEventListener('click', () => this.host.hidePopover());\n root.append(cover);\n this.backdrop = cover;\n }\n}\n\n/**\n * Makes a button open and close a menu. Returns a function that unhooks it.\n *\n * Most such buttons sit in the top bar, which the cover leaves reachable, and\n * that is where people get caught out. Clicking the button a second time\n * looks like it should close the menu, but the browser has already closed it\n * as the mouse went down, before the click arrives — so a handler that reads\n * the live state opens it right back up and the menu looks stuck.\n * Remembering the state as the mouse goes down is what makes the second click\n * work. Keyboard presses never trigger that early close, so they read the\n * live state; `MouseEvent.detail` is `0` only for the click that `Enter` and\n * `Space` produce, which is how the two are told apart.\n *\n * `open` is not touched here: the controller mirrors what the browser does,\n * in both directions, the moment it happens.\n *\n * HTML can pair a button with a popover on its own, but only inside the same\n * component. Reach for this when the button and the menu live apart.\n */\nexport function bindPopoverTrigger(\n trigger: HTMLElement,\n panel: SoftDismissHost\n): () => void {\n let openBeforeAutoClose = false;\n\n const onPointerDown = (): void => {\n openBeforeAutoClose = panel.matches(':popover-open');\n };\n\n const onClick = (event: MouseEvent): void => {\n const wasOpen =\n event.detail > 0 ? openBeforeAutoClose : panel.matches(':popover-open');\n if (wasOpen) {\n panel.hidePopover();\n } else {\n panel.showPopover();\n }\n };\n\n trigger.addEventListener('pointerdown', onPointerDown);\n trigger.addEventListener('click', onClick);\n\n return () => {\n trigger.removeEventListener('pointerdown', onPointerDown);\n trigger.removeEventListener('click', onClick);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,IAAa,oBAAb,MAA6D;CAa3D,YAAY,MAAwC;EAAvB,KAAA,OAAA;EAZT,KAAA,YAAA;EAGA,KAAA,YAAA;EAOD,KAAA,WAAA;EAoCgB,KAAA,kBAAA,UAAuB;GACxD,IAAI,CAAC,KAAK,KAAK,aAAa;GAC5B,KAAK,WAAW;GAIhB,iBAAiB;IACf,KAAK,WAAW;GAClB,GAAG,CAAC;GACJ,IAAK,MAAsB,aAAa,QAAQ;IAC9C,KAAK,YAAY;IACjB,KAAK,KAAK,OAAO;IACjB;GACF;GAGA,KAAK,YAAY,KAAK,KAAK;GAC3B,KAAK,KAAK,OAAO;EACnB;EAY6B,KAAA,YAAA,UAAuB;GAClD,IAAI,CAAC,KAAK,KAAK,aAAa;GAC5B,KAAK,WAAW;GAChB,IAAK,MAAsB,aAAa,UAAU;GAClD,IAAI,CAAC,KAAK,WAAW;GACrB,KAAK,YAAY;;;;;;;GAOjB,KAAK,KAAK,cAAc,IAAI,YAAY,OAAO,CAAC;EAClD;EA5EE,KAAK,cAAc,IAAI;CACzB;CAEA,gBAAsB;EACpB,KAAK,KAAK,iBAAiB,gBAAgB,KAAK,cAAc;EAC9D,KAAK,KAAK,iBAAiB,UAAU,KAAK,QAAQ;EAClD,IAAI,KAAK,KAAK,YACZ,KAAK,KAAK;CAEd;CAEA,cAAoB;EAClB,KAAK,KAAK;CACZ;CAEA,mBAAyB;EACvB,KAAK,KAAK,oBAAoB,gBAAgB,KAAK,cAAc;EACjE,KAAK,KAAK,oBAAoB,UAAU,KAAK,QAAQ;EACrD,KAAK,WAAW;CAClB;CA2DA,OAAqB;EACnB,MAAM,OAAO,KAAK;EAElB,IAAI,CAAC,KAAK,aAAa;GACrB,IAAI,KAAK,WAAW;IAGlB,KAAK,gBAAgB,SAAS;IAC9B,KAAK,YAAY;IACjB,KAAK,UAAU,OAAO;IACtB,KAAK,WAAW,KAAA;GAClB;GACA;EACF;EAEA,IAAI,CAAC,KAAK,WAAW;GACnB,KAAK,aAAa,WAAW,MAAM;GACnC,KAAK,YAAY;GACjB,KAAK,YAAY;EACnB;EAGA,IAAI,CAAC,KAAK,aAAa;EACvB,IAAI,KAAK,UAAU;EAEnB,MAAM,SAAS,KAAK,QAAQ,eAAe;EAC3C,IAAI,KAAK,QAAQ,CAAC,QAChB,KAAK,YAAY;OACZ,IAAI,CAAC,KAAK,QAAQ,QACvB,KAAK,YAAY;CAErB;;;;;;;;;;;;;;;;CAiBA,cAA4B;EAC1B,MAAM,OAAO,KAAK,KAAK;EACvB,IAAI,CAAC,QAAQ,KAAK,UAAU;EAC5B,MAAM,QAAQ,SAAS,cAAc,KAAK;EAC1C,MAAM,aAAa,QAAQ,UAAU;EAIrC,MAAM,MAAM,UACV;EAIF,MAAM,iBAAiB,eAAe,KAAK,KAAK,YAAY,CAAC;EAC7D,KAAK,OAAO,KAAK;EACjB,KAAK,WAAW;CAClB;AACF;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,mBACd,SACA,OACY;CACZ,IAAI,sBAAsB;CAE1B,MAAM,sBAA4B;EAChC,sBAAsB,MAAM,QAAQ,eAAe;CACrD;CAEA,MAAM,WAAW,UAA4B;EAG3C,IADE,MAAM,SAAS,IAAI,sBAAsB,MAAM,QAAQ,eAAe,GAEtE,MAAM,YAAY;OAElB,MAAM,YAAY;CAEtB;CAEA,QAAQ,iBAAiB,eAAe,aAAa;CACrD,QAAQ,iBAAiB,SAAS,OAAO;CAEzC,aAAa;EACX,QAAQ,oBAAoB,eAAe,aAAa;EACxD,QAAQ,oBAAoB,SAAS,OAAO;CAC9C;AACF"}
|
|
1
|
+
{"version":3,"file":"popover-controller.js","names":[],"sources":["../../src/internal/popover-controller.ts"],"sourcesContent":["import type {LitElement, ReactiveController} from 'lit';\n\n/**\n * What {@link PopoverController} needs a component to have.\n *\n * `softDismiss` has to be something a component opts into. The browser hides\n * a popover until it is opened, so switching this on for everyone would make\n * every menu that a consumer already shows and positions disappear.\n */\nexport interface SoftDismissHost extends LitElement {\n /** Let the browser take over showing, hiding and closing this panel. */\n softDismiss: boolean;\n /** Whether the panel is showing. Only used when `softDismiss` is on. */\n open: boolean;\n}\n\n/**\n * Lets a menu close itself the way people expect (#1293).\n *\n * Click outside an open menu and it should go away — and that click should\n * do nothing else. So should pressing `Escape`. The browser does most of\n * this on its own for an element marked as a popover, which is what this\n * controller switches on, and it brings two things that are hard to get\n * right by hand: focus returns to the button that opened the menu, and the\n * menu is drawn above the rest of the page whatever its container does with\n * `overflow`, `transform` or `z-index`.\n *\n * The one thing the browser will not do is swallow that outside click: left\n * alone it closes the menu *and* presses whatever was underneath. So the\n * controller gives the menu a see-through cover over the page, kept behind\n * the menu's own content. The menu is drawn above everything else on the\n * page, so its cover is too: clicks and hovers land on the cover instead of\n * the page, and the cover closes the menu.\n *\n * The cover starts below the top bar, so the bar itself stays usable while a\n * menu is open and moving from one menu to the next is a single click. Its\n * top edge is `--topbar-height`, falling back to the top bar's size token; an\n * app without a top bar sets that to `0`. Consumers can also restyle or tint\n * it through `::part(backdrop)`.\n *\n * A component keeps `open` as the property people set. Since the browser can\n * also open and close the menu on its own, the controller writes what the\n * browser did back into `open`, and fires `close` when the menu went away by\n * itself. Skip that and the property drifts out of step with what is on\n * screen, and the next render closes a menu that was just opened.\n *\n * The button that opens the menu usually belongs to whoever is using the\n * component, not to the component itself, so wiring it up is\n * {@link bindPopoverTrigger}'s job.\n */\nexport class PopoverController implements ReactiveController {\n private installed = false;\n private backdrop?: HTMLElement;\n /** Noted at a close that `open` did not ask for, so it can be reported. */\n private dismissed = false;\n /**\n * True from `beforetoggle` to `toggle`, while the browser is mid-way through\n * opening or closing. `sync()` stands down for that stretch: it would see\n * `open` already updated but the menu not yet moved, and try to move it\n * itself — nested inside the move the browser is making.\n */\n private toggling = false;\n\n constructor(private readonly host: SoftDismissHost) {\n host.addController(this);\n }\n\n hostConnected(): void {\n this.host.addEventListener('beforetoggle', this.onBeforeToggle);\n this.host.addEventListener('toggle', this.onToggle);\n if (this.host.hasUpdated) {\n this.sync();\n }\n }\n\n hostUpdated(): void {\n this.sync();\n }\n\n hostDisconnected(): void {\n this.host.removeEventListener('beforetoggle', this.onBeforeToggle);\n this.host.removeEventListener('toggle', this.onToggle);\n this.toggling = false;\n }\n\n /**\n * The menu is about to open or close for a reason other than `open` being\n * set — a button wired straight to it, `Escape`, a click on the cover, a\n * direct `showPopover()`. `open` is brought into line here, at once.\n *\n * The browser offers two events for this and only `beforetoggle` arrives\n * in time. It fires during the call that opens or closes the menu, while\n * `toggle` waits its turn in the queue. A re-render can get in before that\n * turn, read an `open` that still says the old thing, and undo what just\n * happened — close a menu that was just opened, or reopen one that was\n * just closed.\n */\n private readonly onBeforeToggle = (event: Event): void => {\n if (!this.host.softDismiss) return;\n this.toggling = true;\n // `toggle` clears this. Should it never come — someone cancelled the\n // opening — the flag must not stay up, or `open` could never drive the\n // menu again. A timer runs after the browser has finished either way.\n setTimeout(() => {\n this.toggling = false;\n }, 0);\n if ((event as ToggleEvent).newState === 'open') {\n this.ensureCover();\n this.host.open = true;\n return;\n }\n // `open` is already false when this controller asked for the close;\n // still true means somebody else did, and the consumer should hear.\n this.dismissed = this.host.open;\n this.host.open = false;\n };\n\n /**\n * The menu has closed. Report it only when `open` did not ask for it.\n *\n * By now `open` is `false` either way — `beforetoggle` saw to that — so\n * the note it left in `dismissed` is what tells the two apart.\n *\n * The `softDismiss` check keeps this out of the way of components that run\n * a popover themselves. `obc-menu-button` does that with\n * `obc-context-menu-input`, and those closes are its business.\n */\n private readonly onToggle = (event: Event): void => {\n if (!this.host.softDismiss) return;\n this.toggling = false;\n if ((event as ToggleEvent).newState !== 'closed') return;\n if (!this.dismissed) return;\n this.dismissed = false;\n /**\n * Fired when the popover closed on its own — a click outside, `Escape`,\n * or another popover opening.\n * @event close\n * @type {CustomEvent<void>}\n */\n this.host.dispatchEvent(new CustomEvent('close'));\n };\n\n private sync(): void {\n const host = this.host;\n\n if (!host.softDismiss) {\n if (this.installed) {\n // Dropping the attribute puts the component back to an ordinary\n // element, which is what it was before opting in.\n host.removeAttribute('popover');\n this.installed = false;\n this.backdrop?.remove();\n this.backdrop = undefined;\n }\n return;\n }\n\n if (!this.installed) {\n host.setAttribute('popover', 'auto');\n this.installed = true;\n this.ensureCover();\n }\n\n // Showing a popover that is not on the page throws.\n if (!host.isConnected) return;\n if (this.toggling) return;\n\n const isOpen = host.matches(':popover-open');\n if (host.open && !isOpen) {\n host.showPopover();\n } else if (!host.open && isOpen) {\n host.hidePopover();\n }\n }\n\n /**\n * The see-through cover that swallows clicks while the menu is open.\n *\n * It is an ordinary child of the menu, not a popover of its own: the\n * browser refuses to show one popover while another is on its way up, so\n * the cover cannot be a popover shown as the menu opens. It does not need\n * to be. The menu is drawn above the whole page, so a child of the menu\n * that reaches over the page is drawn above the page as well, and a\n * negative `z-index` keeps it behind the menu's own content. It shows and\n * hides with the menu and never has to be told.\n *\n * Being inside the menu also means the browser treats a click on it as a\n * click *inside* the menu and leaves the menu open — so the cover closes\n * the menu itself.\n */\n private ensureCover(): void {\n const root = this.host.shadowRoot;\n if (!root || this.backdrop) return;\n const cover = document.createElement('div');\n cover.setAttribute('part', 'backdrop');\n // The last fallback keeps the whole page covered where no palette is\n // loaded; an `auto` top would leave the cover wherever it happened to\n // land.\n cover.style.cssText =\n 'position:fixed;' +\n 'top:var(--topbar-height,var(--app-components-topbar-touch-target-size,0px));' +\n 'right:0;bottom:0;left:0;z-index:-1;margin:0;padding:0;border:0;' +\n 'background:transparent';\n cover.addEventListener('click', () => this.host.hidePopover());\n root.append(cover);\n this.backdrop = cover;\n }\n}\n\n/**\n * Makes a button open and close a menu. Returns a function that unhooks it.\n *\n * Most such buttons sit in the top bar, which the cover leaves reachable, and\n * that is where people get caught out. Clicking the button a second time\n * looks like it should close the menu, but the browser has already closed it\n * as the mouse went down, before the click arrives — so a handler that reads\n * the live state opens it right back up and the menu looks stuck.\n * Remembering the state as the mouse goes down is what makes the second click\n * work. Keyboard presses never trigger that early close, so they read the\n * live state; `MouseEvent.detail` is `0` only for the click that `Enter` and\n * `Space` produce, which is how the two are told apart.\n *\n * `open` is not touched here: the controller mirrors what the browser does,\n * in both directions, the moment it happens.\n *\n * HTML can pair a button with a popover on its own, but only inside the same\n * component. Reach for this when the button and the menu live apart.\n *\n * A bar that reports its buttons as events, `obc-top-bar` or\n * `obc-integration-bar`, needs none of this: flip a flag of your own from the\n * event, bind it to `open` and reset it on `close`.\n */\nexport function bindPopoverTrigger(\n trigger: HTMLElement,\n panel: SoftDismissHost\n): () => void {\n let openBeforeAutoClose = false;\n\n const onPointerDown = (): void => {\n openBeforeAutoClose = panel.matches(':popover-open');\n };\n\n const onClick = (event: MouseEvent): void => {\n const wasOpen =\n event.detail > 0 ? openBeforeAutoClose : panel.matches(':popover-open');\n if (wasOpen) {\n panel.hidePopover();\n } else {\n panel.showPopover();\n }\n };\n\n trigger.addEventListener('pointerdown', onPointerDown);\n trigger.addEventListener('click', onClick);\n\n return () => {\n trigger.removeEventListener('pointerdown', onPointerDown);\n trigger.removeEventListener('click', onClick);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,IAAa,oBAAb,MAA6D;CAa3D,YAAY,MAAwC;EAAvB,KAAA,OAAA;EAZT,KAAA,YAAA;EAGA,KAAA,YAAA;EAOD,KAAA,WAAA;EAoCgB,KAAA,kBAAA,UAAuB;GACxD,IAAI,CAAC,KAAK,KAAK,aAAa;GAC5B,KAAK,WAAW;GAIhB,iBAAiB;IACf,KAAK,WAAW;GAClB,GAAG,CAAC;GACJ,IAAK,MAAsB,aAAa,QAAQ;IAC9C,KAAK,YAAY;IACjB,KAAK,KAAK,OAAO;IACjB;GACF;GAGA,KAAK,YAAY,KAAK,KAAK;GAC3B,KAAK,KAAK,OAAO;EACnB;EAY6B,KAAA,YAAA,UAAuB;GAClD,IAAI,CAAC,KAAK,KAAK,aAAa;GAC5B,KAAK,WAAW;GAChB,IAAK,MAAsB,aAAa,UAAU;GAClD,IAAI,CAAC,KAAK,WAAW;GACrB,KAAK,YAAY;;;;;;;GAOjB,KAAK,KAAK,cAAc,IAAI,YAAY,OAAO,CAAC;EAClD;EA5EE,KAAK,cAAc,IAAI;CACzB;CAEA,gBAAsB;EACpB,KAAK,KAAK,iBAAiB,gBAAgB,KAAK,cAAc;EAC9D,KAAK,KAAK,iBAAiB,UAAU,KAAK,QAAQ;EAClD,IAAI,KAAK,KAAK,YACZ,KAAK,KAAK;CAEd;CAEA,cAAoB;EAClB,KAAK,KAAK;CACZ;CAEA,mBAAyB;EACvB,KAAK,KAAK,oBAAoB,gBAAgB,KAAK,cAAc;EACjE,KAAK,KAAK,oBAAoB,UAAU,KAAK,QAAQ;EACrD,KAAK,WAAW;CAClB;CA2DA,OAAqB;EACnB,MAAM,OAAO,KAAK;EAElB,IAAI,CAAC,KAAK,aAAa;GACrB,IAAI,KAAK,WAAW;IAGlB,KAAK,gBAAgB,SAAS;IAC9B,KAAK,YAAY;IACjB,KAAK,UAAU,OAAO;IACtB,KAAK,WAAW,KAAA;GAClB;GACA;EACF;EAEA,IAAI,CAAC,KAAK,WAAW;GACnB,KAAK,aAAa,WAAW,MAAM;GACnC,KAAK,YAAY;GACjB,KAAK,YAAY;EACnB;EAGA,IAAI,CAAC,KAAK,aAAa;EACvB,IAAI,KAAK,UAAU;EAEnB,MAAM,SAAS,KAAK,QAAQ,eAAe;EAC3C,IAAI,KAAK,QAAQ,CAAC,QAChB,KAAK,YAAY;OACZ,IAAI,CAAC,KAAK,QAAQ,QACvB,KAAK,YAAY;CAErB;;;;;;;;;;;;;;;;CAiBA,cAA4B;EAC1B,MAAM,OAAO,KAAK,KAAK;EACvB,IAAI,CAAC,QAAQ,KAAK,UAAU;EAC5B,MAAM,QAAQ,SAAS,cAAc,KAAK;EAC1C,MAAM,aAAa,QAAQ,UAAU;EAIrC,MAAM,MAAM,UACV;EAIF,MAAM,iBAAiB,eAAe,KAAK,KAAK,YAAY,CAAC;EAC7D,KAAK,OAAO,KAAK;EACjB,KAAK,WAAW;CAClB;AACF;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,mBACd,SACA,OACY;CACZ,IAAI,sBAAsB;CAE1B,MAAM,sBAA4B;EAChC,sBAAsB,MAAM,QAAQ,eAAe;CACrD;CAEA,MAAM,WAAW,UAA4B;EAG3C,IADE,MAAM,SAAS,IAAI,sBAAsB,MAAM,QAAQ,eAAe,GAEtE,MAAM,YAAY;OAElB,MAAM,YAAY;CAEtB;CAEA,QAAQ,iBAAiB,eAAe,aAAa;CACrD,QAAQ,iBAAiB,SAAS,OAAO;CAEzC,aAAa;EACX,QAAQ,oBAAoB,eAAe,aAAa;EACxD,QAAQ,oBAAoB,SAAS,OAAO;CAC9C;AACF"}
|