| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| const VIEW_MODES = [ |
| { key: 'fit-width', label: 'Fit Width', icon: 'fa-arrows-left-right' }, |
| { key: 'fit-height', label: 'Fit Height', icon: 'fa-arrows-up-down' }, |
| { key: 'one-to-one', label: '1:1', icon: 'fa-vector-square' }, |
| ]; |
|
|
| class ViewModeControls extends HTMLElement { |
| #mode = 'fit-width'; |
|
|
| connectedCallback() { |
| this.#render(); |
| this.addEventListener('click', this.#onClick); |
| } |
|
|
| get mode() { return this.#mode; } |
| set mode(value) { |
| if (!VIEW_MODES.find(m => m.key === value)) return; |
| if (this.#mode === value) return; |
| this.#mode = value; |
| this.#render(); |
| } |
|
|
| #onClick = (e) => { |
| const btn = e.target.closest('button[data-mode]'); |
| if (!btn) return; |
| e.stopPropagation(); |
| if (btn.dataset.mode === this.#mode) return; |
| this.#mode = btn.dataset.mode; |
| this.#render(); |
| this.dispatchEvent(new CustomEvent('mode-change', { detail: { mode: this.#mode } })); |
| }; |
|
|
| #render() { |
| const buttons = VIEW_MODES.map(m => ` |
| <button type="button" class="secondary outline" data-mode="${m.key}" |
| aria-pressed="${m.key === this.#mode}" |
| title="${m.label}" aria-label="${m.label}"> |
| <i class="fas ${m.icon}"></i> |
| </button> |
| `).join(''); |
| this.innerHTML = ` |
| <style> |
| view-mode-controls { |
| display: inline-flex; |
| vertical-align: middle; |
| } |
| view-mode-controls .vm-row { |
| display: inline-flex; |
| gap: 0; |
| } |
| view-mode-controls .vm-row > button { |
| border-radius: 0; |
| } |
| view-mode-controls .vm-row > button:first-child { |
| border-top-left-radius: var(--pico-border-radius); |
| border-bottom-left-radius: var(--pico-border-radius); |
| } |
| view-mode-controls .vm-row > button:last-child { |
| border-top-right-radius: var(--pico-border-radius); |
| border-bottom-right-radius: var(--pico-border-radius); |
| } |
| view-mode-controls .vm-row > button:not(:first-child) { |
| margin-left: -1px; |
| } |
| view-mode-controls button .fas { |
| margin-right: 0 !important; |
| } |
| /* Pressed state: disable the host toolbar's mix-blend-mode trick and |
| paint a solid filled background so the active mode is unambiguous |
| against the surrounding outline buttons. */ |
| view-mode-controls button[aria-pressed="true"] { |
| mix-blend-mode: normal !important; |
| background: rgba(255, 255, 255, 0.22) !important; |
| opacity: 1 !important; |
| border-color: #fff !important; |
| color: #fff !important; |
| z-index: 1; |
| } |
| </style> |
| <div class="vm-row" role="radiogroup" aria-label="View mode"> |
| ${buttons} |
| </div> |
| `; |
| } |
| } |
|
|
| customElements.define('view-mode-controls', ViewModeControls); |
|
|