|
| 1 | +// debugger |
| 2 | +import { debug } from '../utils/debuglog'; |
| 3 | + |
| 4 | +const debuglog = debug.extend('mini-map'); |
| 5 | + |
1 | 6 | import L from 'leaflet'; |
2 | 7 | import 'leaflet-providers/leaflet-providers.js'; |
3 | 8 | import mapstyle from 'leaflet/dist/leaflet.css'; |
4 | 9 | import { css, CSSResultGroup, html, PropertyValues, TemplateResult, unsafeCSS } from 'lit'; |
5 | 10 | import { customElement, property, state } from 'lit/decorators.js'; |
| 11 | +import { styleMap } from 'lit/directives/style-map.js'; |
6 | 12 |
|
7 | 13 | import { COMPONENT } from '../constants/const'; |
8 | 14 | import { Address, MapData, MiniMapConfig } from '../types/config'; |
9 | 15 | import { SECTION } from '../types/section'; |
| 16 | +import { isSafari } from '../utils'; |
10 | 17 | import { BaseElement } from '../utils/base-element'; |
11 | 18 | import { _getMapAddress } from '../utils/lovelace/create-map-card'; |
12 | 19 | import { showHaMapDialog } from '../utils/lovelace/show-map-dialog'; |
13 | 20 |
|
14 | 21 | export const DEFAULT_HOURS_TO_SHOW = 0; |
15 | 22 | export const DEFAULT_ZOOM = 14; |
16 | 23 |
|
| 24 | +export const CARD_MAP_POSITION = ['default', 'top', 'bottom', 'single'] as const; |
| 25 | +export type CardMapPosition = (typeof CARD_MAP_POSITION)[number]; |
| 26 | + |
| 27 | +const MAP_FILTER: Record<CardMapPosition, string> = { |
| 28 | + default: 'linear-gradient(to bottom, transparent 0%, black 15%, black 90%, transparent 100%)', |
| 29 | + top: 'linear-gradient(to bottom, black 90%, transparent 100%)', |
| 30 | + bottom: 'linear-gradient(to bottom, transparent 0%, black 10%)', |
| 31 | + single: 'linear-gradient(to bottom, transparent 0%, black 0%, black 100%, transparent 100%)', |
| 32 | +}; |
| 33 | + |
| 34 | +const DEBUG_NO_FETCH = process.env.DEBUG === 'true' && true; |
| 35 | +const DEV_ADDRESS = { |
| 36 | + streetName: '123 Example St', |
| 37 | + sublocality: 'Example Suburb', |
| 38 | + city: 'Example City', |
| 39 | +}; |
| 40 | + |
17 | 41 | @customElement(COMPONENT.MINI_MAP) |
18 | 42 | export class MiniMapBox extends BaseElement { |
19 | 43 | constructor() { |
20 | 44 | super(SECTION.MINI_MAP); |
21 | 45 | } |
22 | 46 |
|
23 | | - @property({ attribute: false }) mapConfig!: MiniMapConfig; |
| 47 | + @property({ attribute: false }) public mapConfig!: MiniMapConfig; |
24 | 48 | @property({ attribute: 'is-dark', type: Boolean, reflect: true }) |
25 | 49 | isDark!: boolean; |
| 50 | + @property({ type: String, reflect: true, attribute: 'map-position' }) public mapPosition: CardMapPosition = 'default'; |
26 | 51 | @state() private mapData?: MapData; |
27 | 52 |
|
28 | 53 | @state() private map: L.Map | null = null; |
@@ -144,9 +169,20 @@ export class MiniMapBox extends BaseElement { |
144 | 169 | return true; |
145 | 170 | } |
146 | 171 |
|
| 172 | + protected firstUpdated(): void { |
| 173 | + this.mapPosition = this._computeMapPosition(); |
| 174 | + } |
| 175 | + |
147 | 176 | private async _getAddress(): Promise<void> { |
| 177 | + // Avoid fetching address in debug mode |
| 178 | + if (DEBUG_NO_FETCH) { |
| 179 | + this._addressReady = true; |
| 180 | + this._address = DEV_ADDRESS; |
| 181 | + return; |
| 182 | + } |
| 183 | + |
148 | 184 | const { lat, lon } = this.mapData!; |
149 | | - // console.log('Getting adress...'); |
| 185 | + debuglog('Getting adress...'); |
150 | 186 | const address = await _getMapAddress(this.mapConfig, lat, lon); |
151 | 187 | if (address) { |
152 | 188 | this._address = address; |
@@ -237,9 +273,13 @@ export class MiniMapBox extends BaseElement { |
237 | 273 | } |
238 | 274 |
|
239 | 275 | protected render(): TemplateResult { |
240 | | - const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); |
| 276 | + const mapStyle = { |
| 277 | + '--vic-map-mask-image': MAP_FILTER[this.mapPosition] || MAP_FILTER['default'], |
| 278 | + height: `${this.mapConfig?.map_height || 150}px`, |
| 279 | + }; |
| 280 | + |
241 | 281 | return html` |
242 | | - <div class="map-wrapper" ?safari=${isSafari} style=${`height: ${this.mapConfig?.map_height || 150}px;`}> |
| 282 | + <div class="map-wrapper" ?safari=${isSafari} style=${styleMap(mapStyle)}> |
243 | 283 | <div id="overlay-container"> |
244 | 284 | <div class="reset-button" @click=${this.resetMap} .hidden=${this._locateIconVisible}> |
245 | 285 | <ha-icon icon="mdi:compass"></ha-icon> |
@@ -294,6 +334,24 @@ export class MiniMapBox extends BaseElement { |
294 | 334 | showHaMapDialog(this, params); |
295 | 335 | } |
296 | 336 |
|
| 337 | + private _computeMapPosition = (): CardMapPosition => { |
| 338 | + const mapSec = this.parentNode as HTMLElement | null; |
| 339 | + if (!mapSec) return 'default'; |
| 340 | + const { previousElementSibling, nextElementSibling } = mapSec; |
| 341 | + |
| 342 | + let position: CardMapPosition = 'default'; |
| 343 | + if (!previousElementSibling && !nextElementSibling) { |
| 344 | + position = 'single'; |
| 345 | + } else if (!previousElementSibling && nextElementSibling) { |
| 346 | + position = 'top'; |
| 347 | + } else if (previousElementSibling && !nextElementSibling) { |
| 348 | + position = 'bottom'; |
| 349 | + } else { |
| 350 | + position = 'default'; |
| 351 | + } |
| 352 | + return position; |
| 353 | + }; |
| 354 | + |
297 | 355 | static get styles(): CSSResultGroup { |
298 | 356 | return [ |
299 | 357 | super.styles, |
|
0 commit comments