ts-maps 0.3.2 → 0.3.4
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/dist/core-map/control/FullscreenControl.d.ts +39 -0
- package/dist/core-map/control/GeocoderControl.d.ts +61 -0
- package/dist/core-map/control/LocateControl.d.ts +5 -2
- package/dist/core-map/control/NavigationControl.d.ts +39 -0
- package/dist/core-map/control/index.d.ts +6 -0
- package/dist/core-map/game/TerritoryLog.d.ts +66 -0
- package/dist/core-map/game/TerritoryStore.d.ts +59 -0
- package/dist/core-map/game/index.d.ts +11 -0
- package/dist/core-map/game/loop.d.ts +61 -0
- package/dist/core-map/geo/area.d.ts +52 -0
- package/dist/core-map/geo/index.d.ts +30 -0
- package/dist/core-map/geo/index.js +826 -1
- package/dist/core-map/geo/polygonClip.d.ts +75 -0
- package/dist/core-map/geo/validate.d.ts +54 -0
- package/dist/core-map/index.d.ts +7 -2
- package/dist/core-map/layer/GeoJSONTileSource.d.ts +50 -0
- package/dist/core-map/layer/RunTrailLayer.d.ts +35 -0
- package/dist/core-map/layer/TerritoryLayer.d.ts +62 -0
- package/dist/core-map/layer/index.d.ts +6 -0
- package/dist/core-map/layer/tile/RasterDEMLayer.d.ts +4 -0
- package/dist/core-map/layer/tile/VectorTileMapLayer.d.ts +59 -11
- package/dist/core-map/layer/tile/urlTemplate.d.ts +1 -2
- package/dist/core-map/map/Map.d.ts +32 -1
- package/dist/core-map/mvt/DecodedTile.d.ts +20 -0
- package/dist/core-map/mvt/FlatTile.d.ts +25 -0
- package/dist/core-map/mvt/VectorTileFeature.d.ts +8 -0
- package/dist/core-map/style-spec/expressions/formatted.d.ts +36 -0
- package/dist/core-map/style-spec/expressions/operators/binding.d.ts +1 -0
- package/dist/core-map/style-spec/expressions/operators/geometry.d.ts +19 -0
- package/dist/core-map/style-spec/expressions/types.d.ts +3 -0
- package/dist/core-map/style-spec/index.js +459 -42
- package/dist/core-map/style-spec/schema.d.ts +43 -3
- package/dist/core-map/style-spec/types.d.ts +47 -7
- package/dist/core-map/styles/basemap.d.ts +41 -0
- package/dist/core-map/styles/index.d.ts +5 -0
- package/dist/core-map/styles/palette.d.ts +31 -0
- package/dist/core-map/symbols/CollisionIndex.d.ts +22 -5
- package/dist/core-map/symbols/GlyphAtlas.d.ts +6 -1
- package/dist/core-map/symbols/GlyphProvider.d.ts +21 -0
- package/dist/core-map/symbols/GlyphRenderer.d.ts +48 -0
- package/dist/core-map/symbols/IconAtlas.d.ts +10 -1
- package/dist/core-map/symbols/SymbolOverlay.d.ts +47 -0
- package/dist/core-map/symbols/index.d.ts +4 -0
- package/dist/core-map/symbols/index.js +1071 -67
- package/dist/core-map/symbols/loadGlyphs.d.ts +53 -0
- package/dist/core-map/symbols/loadSprite.d.ts +57 -0
- package/dist/core-map/symbols/placement.d.ts +67 -0
- package/dist/core-map/symbols/sdf.d.ts +37 -0
- package/dist/core-map/symbols/sections.d.ts +32 -0
- package/dist/core-map/workers/WorkerPool.d.ts +40 -0
- package/dist/core-map/workers/decodeMvtFlat.d.ts +52 -0
- package/dist/index.js +11548 -5996
- package/package.json +1 -1
- package/src/core-map/ts-maps.css +392 -99
package/src/core-map/ts-maps.css
CHANGED
|
@@ -116,6 +116,10 @@
|
|
|
116
116
|
z-index: 200;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
.tsmap-symbol-pane {
|
|
120
|
+
z-index: 350;
|
|
121
|
+
}
|
|
122
|
+
|
|
119
123
|
.tsmap-overlay-pane {
|
|
120
124
|
z-index: 400;
|
|
121
125
|
}
|
|
@@ -293,25 +297,79 @@ svg.tsmap-image-layer.tsmap-interactive path {
|
|
|
293
297
|
|
|
294
298
|
/* visual tweaks */
|
|
295
299
|
|
|
300
|
+
/*
|
|
301
|
+
* Theme tokens.
|
|
302
|
+
*
|
|
303
|
+
* Every colour the chrome draws with resolves through one of these, so a dark
|
|
304
|
+
* map is a single class flip rather than a parallel stylesheet. They live on
|
|
305
|
+
* the container and not on :root deliberately: two maps on one page can then
|
|
306
|
+
* carry different themes, and a host page's own custom properties can't
|
|
307
|
+
* collide with them.
|
|
308
|
+
*
|
|
309
|
+
* The switch is `.tsmap-dark`, set by the map's `theme` option (see
|
|
310
|
+
* Map.setTheme). It is a class and not a bare `prefers-color-scheme` query
|
|
311
|
+
* because the map's theme should follow the basemap being displayed, which is
|
|
312
|
+
* an application decision — a dark style on a machine set to light mode still
|
|
313
|
+
* needs dark chrome. `theme: 'auto'` is what re-attaches it to the OS setting.
|
|
314
|
+
*/
|
|
296
315
|
.tsmap-container {
|
|
316
|
+
--tsmap-accent: #1a73e8;
|
|
317
|
+
--tsmap-surface: #fff;
|
|
318
|
+
--tsmap-surface-hover: #f1f3f4;
|
|
319
|
+
--tsmap-fg: #3c4043;
|
|
320
|
+
--tsmap-fg-muted: #5f6368;
|
|
321
|
+
--tsmap-fg-disabled: #bdc1c6;
|
|
322
|
+
--tsmap-divider: rgb(0 0 0 / 12%);
|
|
323
|
+
--tsmap-scrim: rgb(255 255 255 / 80%);
|
|
324
|
+
--tsmap-hairline: #ddd;
|
|
325
|
+
--tsmap-scale-line: #777;
|
|
326
|
+
--tsmap-shadow:
|
|
327
|
+
0 1px 2px rgb(60 64 67 / 30%),
|
|
328
|
+
0 2px 6px 2px rgb(60 64 67 / 15%);
|
|
329
|
+
--tsmap-shadow-lg:
|
|
330
|
+
0 2px 6px rgb(60 64 67 / 28%),
|
|
331
|
+
0 6px 18px 4px rgb(60 64 67 / 15%);
|
|
332
|
+
|
|
297
333
|
/* Matched to the land colour of a light basemap, so tiles fade in against
|
|
298
|
-
|
|
299
|
-
|
|
334
|
+
their own background instead of flashing a dark band on every pan. */
|
|
335
|
+
--tsmap-tile-bg: #e8eaed;
|
|
336
|
+
|
|
337
|
+
background: var(--tsmap-tile-bg);
|
|
300
338
|
outline-offset: 1px;
|
|
301
339
|
|
|
302
340
|
a {
|
|
303
|
-
color:
|
|
341
|
+
color: var(--tsmap-accent);
|
|
304
342
|
}
|
|
305
343
|
}
|
|
306
344
|
|
|
345
|
+
.tsmap-container.tsmap-dark {
|
|
346
|
+
--tsmap-accent: #8ab4f8;
|
|
347
|
+
--tsmap-surface: #292a2d;
|
|
348
|
+
--tsmap-surface-hover: #35363a;
|
|
349
|
+
--tsmap-fg: #e8eaed;
|
|
350
|
+
--tsmap-fg-muted: #9aa0a6;
|
|
351
|
+
--tsmap-fg-disabled: #5f6368;
|
|
352
|
+
--tsmap-divider: rgb(255 255 255 / 14%);
|
|
353
|
+
--tsmap-scrim: rgb(32 33 36 / 80%);
|
|
354
|
+
--tsmap-hairline: #3c4043;
|
|
355
|
+
--tsmap-scale-line: #9aa0a6;
|
|
356
|
+
--tsmap-shadow:
|
|
357
|
+
0 1px 2px rgb(0 0 0 / 50%),
|
|
358
|
+
0 2px 6px 2px rgb(0 0 0 / 30%);
|
|
359
|
+
--tsmap-shadow-lg:
|
|
360
|
+
0 2px 6px rgb(0 0 0 / 45%),
|
|
361
|
+
0 6px 18px 4px rgb(0 0 0 / 30%);
|
|
362
|
+
--tsmap-tile-bg: #16171a;
|
|
363
|
+
}
|
|
364
|
+
|
|
307
365
|
/* prevent showing outline-box on Chromium when clicking on a vector with a tooltip */
|
|
308
366
|
path.tsmap-interactive:focus:not(:focus-visible) {
|
|
309
367
|
outline: 0;
|
|
310
368
|
}
|
|
311
369
|
|
|
312
370
|
.tsmap-zoom-box {
|
|
313
|
-
border: 2px dotted
|
|
314
|
-
background:
|
|
371
|
+
border: 2px dotted var(--tsmap-accent);
|
|
372
|
+
background: var(--tsmap-scrim);
|
|
315
373
|
}
|
|
316
374
|
|
|
317
375
|
/* general typography */
|
|
@@ -346,38 +404,35 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
346
404
|
* focus ring, which the old chrome suppressed entirely.
|
|
347
405
|
*/
|
|
348
406
|
.tsmap-bar {
|
|
349
|
-
box-shadow:
|
|
350
|
-
0 1px 2px rgba(60, 64, 67, 0.3),
|
|
351
|
-
0 2px 6px 2px rgba(60, 64, 67, 0.15);
|
|
407
|
+
box-shadow: var(--tsmap-shadow);
|
|
352
408
|
border-radius: 8px;
|
|
353
409
|
overflow: hidden;
|
|
354
410
|
|
|
355
411
|
a {
|
|
356
412
|
position: relative;
|
|
357
|
-
background-color:
|
|
413
|
+
background-color: var(--tsmap-surface);
|
|
358
414
|
width: 40px;
|
|
359
415
|
height: 40px;
|
|
360
416
|
line-height: 40px;
|
|
361
417
|
display: block;
|
|
362
418
|
text-align: center;
|
|
363
419
|
text-decoration: none;
|
|
364
|
-
color: black;
|
|
365
420
|
background-position: 50% 50%;
|
|
366
421
|
background-repeat: no-repeat;
|
|
367
422
|
display: block;
|
|
368
|
-
color:
|
|
423
|
+
color: var(--tsmap-fg);
|
|
369
424
|
transition: background-color 120ms ease;
|
|
370
425
|
|
|
371
426
|
&:hover {
|
|
372
|
-
background-color:
|
|
427
|
+
background-color: var(--tsmap-surface-hover);
|
|
373
428
|
}
|
|
374
429
|
|
|
375
430
|
/* Visible only for keyboard users: a ring on every mouse click is noise,
|
|
376
|
-
|
|
431
|
+
and no ring at all makes the control unusable without a pointer. */
|
|
377
432
|
&:focus-visible {
|
|
378
|
-
outline: 2px solid
|
|
433
|
+
outline: 2px solid var(--tsmap-accent);
|
|
379
434
|
outline-offset: -2px;
|
|
380
|
-
background-color:
|
|
435
|
+
background-color: var(--tsmap-surface-hover);
|
|
381
436
|
}
|
|
382
437
|
|
|
383
438
|
/*
|
|
@@ -396,7 +451,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
396
451
|
bottom: 0;
|
|
397
452
|
left: 8px;
|
|
398
453
|
height: 1px;
|
|
399
|
-
background:
|
|
454
|
+
background: var(--tsmap-divider);
|
|
400
455
|
}
|
|
401
456
|
|
|
402
457
|
&:first-child {
|
|
@@ -411,30 +466,8 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
411
466
|
|
|
412
467
|
&.tsmap-disabled {
|
|
413
468
|
cursor: default;
|
|
414
|
-
background-color:
|
|
415
|
-
color:
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
/* Dark basemaps get dark chrome; white cards on a dark map glare. */
|
|
421
|
-
@media (prefers-color-scheme: dark) {
|
|
422
|
-
.tsmap-dark .tsmap-bar a:not(:last-child)::after {
|
|
423
|
-
background: rgba(255, 255, 255, 0.14);
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
.tsmap-dark .tsmap-bar a {
|
|
427
|
-
background-color: #292a2d;
|
|
428
|
-
color: #e8eaed;
|
|
429
|
-
|
|
430
|
-
&:hover,
|
|
431
|
-
&:focus-visible {
|
|
432
|
-
background-color: #35363a;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
&.tsmap-disabled {
|
|
436
|
-
background-color: #292a2d;
|
|
437
|
-
color: #5f6368;
|
|
469
|
+
background-color: var(--tsmap-surface);
|
|
470
|
+
color: var(--tsmap-fg-disabled);
|
|
438
471
|
}
|
|
439
472
|
}
|
|
440
473
|
}
|
|
@@ -460,11 +493,11 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
460
493
|
/* zoom control */
|
|
461
494
|
|
|
462
495
|
/* Scoped under .tsmap-bar so it outranks the `.tsmap-bar a` colour above —
|
|
463
|
-
|
|
464
|
-
|
|
496
|
+
the zoom glyphs sit a shade lighter than label ink, as they do on every
|
|
497
|
+
map that draws them as characters rather than icons. */
|
|
465
498
|
.tsmap-bar a.tsmap-control-zoom-in,
|
|
466
499
|
.tsmap-bar a.tsmap-control-zoom-out {
|
|
467
|
-
color:
|
|
500
|
+
color: var(--tsmap-fg-muted);
|
|
468
501
|
|
|
469
502
|
font:
|
|
470
503
|
400 21px / 40px -apple-system,
|
|
@@ -478,10 +511,8 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
478
511
|
/* layers control */
|
|
479
512
|
|
|
480
513
|
.tsmap-control-layers {
|
|
481
|
-
box-shadow:
|
|
482
|
-
|
|
483
|
-
0 2px 6px 2px rgba(60, 64, 67, 0.15);
|
|
484
|
-
background: #fff;
|
|
514
|
+
box-shadow: var(--tsmap-shadow);
|
|
515
|
+
background: var(--tsmap-surface);
|
|
485
516
|
border-radius: 8px;
|
|
486
517
|
|
|
487
518
|
.tsmap-control-layers-list {
|
|
@@ -500,6 +531,12 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
500
531
|
width: 44px;
|
|
501
532
|
height: 44px;
|
|
502
533
|
}
|
|
534
|
+
|
|
535
|
+
/* The stacked-sheets glyph is drawn with light fills, which disappear into a
|
|
536
|
+
dark card. Same shape, inverted ink. */
|
|
537
|
+
.tsmap-dark & {
|
|
538
|
+
background-image: url('data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2736%27 height=%2736%27 viewBox=%270 0 36 36%27%3E%3Crect x=%274%27 y=%274%27 width=%2714%27 height=%2714%27 fill=%27%23202124%27 stroke=%27%23bdc1c6%27 stroke-width=%271.5%27/%3E%3Crect x=%2710%27 y=%2710%27 width=%2714%27 height=%2714%27 fill=%27%232f3134%27 stroke=%27%23bdc1c6%27 stroke-width=%271.5%27/%3E%3Crect x=%2716%27 y=%2716%27 width=%2714%27 height=%2714%27 fill=%27%233f4144%27 stroke=%27%23bdc1c6%27 stroke-width=%271.5%27/%3E%3C/svg%3E');
|
|
539
|
+
}
|
|
503
540
|
}
|
|
504
541
|
|
|
505
542
|
.tsmap-control-layers-expanded {
|
|
@@ -521,8 +558,8 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
521
558
|
|
|
522
559
|
.tsmap-control-layers-expanded {
|
|
523
560
|
padding: 6px 10px 6px 6px;
|
|
524
|
-
color:
|
|
525
|
-
background:
|
|
561
|
+
color: var(--tsmap-fg);
|
|
562
|
+
background: var(--tsmap-surface);
|
|
526
563
|
}
|
|
527
564
|
|
|
528
565
|
.tsmap-control-layers-scrollbar {
|
|
@@ -545,7 +582,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
545
582
|
|
|
546
583
|
.tsmap-control-layers-separator {
|
|
547
584
|
height: 0;
|
|
548
|
-
border-top: 1px solid
|
|
585
|
+
border-top: 1px solid var(--tsmap-hairline);
|
|
549
586
|
margin: 5px -10px 5px -6px;
|
|
550
587
|
}
|
|
551
588
|
|
|
@@ -557,15 +594,14 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
557
594
|
/* attribution and scale controls */
|
|
558
595
|
|
|
559
596
|
.tsmap-container .tsmap-control-attribution {
|
|
560
|
-
background:
|
|
561
|
-
background: rgba(255, 255, 255, 0.8);
|
|
597
|
+
background: var(--tsmap-scrim);
|
|
562
598
|
margin: 0;
|
|
563
599
|
}
|
|
564
600
|
|
|
565
601
|
.tsmap-control-attribution,
|
|
566
602
|
.tsmap-control-scale-line {
|
|
567
603
|
padding: 0 5px;
|
|
568
|
-
color:
|
|
604
|
+
color: var(--tsmap-fg);
|
|
569
605
|
line-height: 1.4;
|
|
570
606
|
}
|
|
571
607
|
|
|
@@ -595,22 +631,21 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
595
631
|
}
|
|
596
632
|
|
|
597
633
|
.tsmap-control-scale-line {
|
|
598
|
-
border: 2px solid
|
|
634
|
+
border: 2px solid var(--tsmap-scale-line);
|
|
599
635
|
border-top: none;
|
|
600
636
|
line-height: 1.1;
|
|
601
637
|
padding: 2px 5px 1px;
|
|
602
638
|
white-space: nowrap;
|
|
603
639
|
box-sizing: border-box;
|
|
604
|
-
background:
|
|
605
|
-
text-shadow: 1px 1px #fff;
|
|
640
|
+
background: var(--tsmap-scrim);
|
|
606
641
|
|
|
607
642
|
&:not(:first-child) {
|
|
608
|
-
border-top: 2px solid
|
|
643
|
+
border-top: 2px solid var(--tsmap-scale-line);
|
|
609
644
|
border-bottom: none;
|
|
610
645
|
margin-top: -2px;
|
|
611
646
|
|
|
612
647
|
&:not(:last-child) {
|
|
613
|
-
border-bottom: 2px solid
|
|
648
|
+
border-bottom: 2px solid var(--tsmap-scale-line);
|
|
614
649
|
}
|
|
615
650
|
}
|
|
616
651
|
}
|
|
@@ -683,11 +718,9 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
683
718
|
|
|
684
719
|
.tsmap-popup-content-wrapper,
|
|
685
720
|
.tsmap-popup-tip {
|
|
686
|
-
background:
|
|
687
|
-
color:
|
|
688
|
-
box-shadow:
|
|
689
|
-
0 2px 6px rgba(60, 64, 67, 0.28),
|
|
690
|
-
0 6px 18px 4px rgba(60, 64, 67, 0.15);
|
|
721
|
+
background: var(--tsmap-surface);
|
|
722
|
+
color: var(--tsmap-fg);
|
|
723
|
+
box-shadow: var(--tsmap-shadow-lg);
|
|
691
724
|
}
|
|
692
725
|
|
|
693
726
|
.tsmap-container a.tsmap-popup-close-button {
|
|
@@ -699,13 +732,13 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
699
732
|
width: 24px;
|
|
700
733
|
height: 24px;
|
|
701
734
|
font: 16px/24px Tahoma, Verdana, sans-serif;
|
|
702
|
-
color:
|
|
735
|
+
color: var(--tsmap-fg-muted);
|
|
703
736
|
text-decoration: none;
|
|
704
737
|
background: transparent;
|
|
705
738
|
|
|
706
739
|
&:hover,
|
|
707
740
|
&:focus {
|
|
708
|
-
color:
|
|
741
|
+
color: var(--tsmap-fg);
|
|
709
742
|
}
|
|
710
743
|
}
|
|
711
744
|
|
|
@@ -716,8 +749,8 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
716
749
|
/* div icon */
|
|
717
750
|
|
|
718
751
|
.tsmap-div-icon {
|
|
719
|
-
background:
|
|
720
|
-
border: 1px solid
|
|
752
|
+
background: var(--tsmap-surface);
|
|
753
|
+
border: 1px solid var(--tsmap-fg-muted);
|
|
721
754
|
}
|
|
722
755
|
|
|
723
756
|
/* Tooltip */
|
|
@@ -725,14 +758,14 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
725
758
|
.tsmap-tooltip {
|
|
726
759
|
position: absolute;
|
|
727
760
|
padding: 6px;
|
|
728
|
-
background-color:
|
|
729
|
-
border: 1px solid
|
|
761
|
+
background-color: var(--tsmap-surface);
|
|
762
|
+
border: 1px solid var(--tsmap-surface);
|
|
730
763
|
border-radius: 3px;
|
|
731
|
-
color:
|
|
764
|
+
color: var(--tsmap-fg);
|
|
732
765
|
white-space: nowrap;
|
|
733
766
|
user-select: none;
|
|
734
767
|
pointer-events: none;
|
|
735
|
-
box-shadow: 0 1px 3px
|
|
768
|
+
box-shadow: 0 1px 3px rgb(0 0 0 / 40%);
|
|
736
769
|
|
|
737
770
|
&.tsmap-interactive {
|
|
738
771
|
cursor: pointer;
|
|
@@ -762,7 +795,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
762
795
|
top: 0;
|
|
763
796
|
margin-top: -12px;
|
|
764
797
|
margin-left: -6px;
|
|
765
|
-
border-bottom-color:
|
|
798
|
+
border-bottom-color: var(--tsmap-surface);
|
|
766
799
|
}
|
|
767
800
|
}
|
|
768
801
|
|
|
@@ -774,7 +807,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
774
807
|
margin-left: -6px;
|
|
775
808
|
bottom: 0;
|
|
776
809
|
margin-bottom: -12px;
|
|
777
|
-
border-top-color:
|
|
810
|
+
border-top-color: var(--tsmap-surface);
|
|
778
811
|
}
|
|
779
812
|
}
|
|
780
813
|
|
|
@@ -786,7 +819,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
786
819
|
margin-top: -6px;
|
|
787
820
|
right: 0;
|
|
788
821
|
margin-right: -12px;
|
|
789
|
-
border-left-color:
|
|
822
|
+
border-left-color: var(--tsmap-surface);
|
|
790
823
|
}
|
|
791
824
|
}
|
|
792
825
|
|
|
@@ -798,7 +831,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
798
831
|
margin-top: -6px;
|
|
799
832
|
left: 0;
|
|
800
833
|
margin-left: -12px;
|
|
801
|
-
border-right-color:
|
|
834
|
+
border-right-color: var(--tsmap-surface);
|
|
802
835
|
}
|
|
803
836
|
}
|
|
804
837
|
|
|
@@ -813,11 +846,11 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
813
846
|
}
|
|
814
847
|
|
|
815
848
|
/* locate control
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
849
|
+
==========================================================================
|
|
850
|
+
The crosshair button. Drawn in CSS rather than shipped as an icon file so it
|
|
851
|
+
inherits colour from the button's state and stays crisp at any pixel ratio —
|
|
852
|
+
the control has four states and a bitmap would need four assets.
|
|
853
|
+
========================================================================== */
|
|
821
854
|
|
|
822
855
|
.tsmap-control-locate a {
|
|
823
856
|
display: flex;
|
|
@@ -830,7 +863,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
830
863
|
position: relative;
|
|
831
864
|
width: 18px;
|
|
832
865
|
height: 18px;
|
|
833
|
-
color:
|
|
866
|
+
color: var(--tsmap-fg-muted);
|
|
834
867
|
|
|
835
868
|
/* The ring. */
|
|
836
869
|
&::before {
|
|
@@ -856,15 +889,15 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
856
889
|
}
|
|
857
890
|
|
|
858
891
|
/* Following the device: the crosshair fills in, the way a "you are here"
|
|
859
|
-
|
|
892
|
+
control does everywhere else. */
|
|
860
893
|
a.tsmap-control-locate-active .tsmap-locate-icon {
|
|
861
|
-
color:
|
|
894
|
+
color: var(--tsmap-accent);
|
|
862
895
|
}
|
|
863
896
|
|
|
864
897
|
/* Acquiring a first fix. The pulse is the only thing telling the user that a
|
|
865
|
-
|
|
898
|
+
press did anything at all — a GPS fix can take several seconds. */
|
|
866
899
|
a.tsmap-control-locate-locating .tsmap-locate-icon {
|
|
867
|
-
color:
|
|
900
|
+
color: var(--tsmap-accent);
|
|
868
901
|
animation: tsmap-locate-pulse 1s ease-in-out infinite;
|
|
869
902
|
}
|
|
870
903
|
|
|
@@ -875,8 +908,8 @@ a.tsmap-control-locate-locating .tsmap-locate-icon {
|
|
|
875
908
|
}
|
|
876
909
|
|
|
877
910
|
/* Denied or unavailable. Struck through rather than merely greyed: grey reads
|
|
878
|
-
|
|
879
|
-
|
|
911
|
+
as "disabled, try later" when the real state is "this will not work until
|
|
912
|
+
you change a browser setting". */
|
|
880
913
|
/*
|
|
881
914
|
* The state class lands on the <a> itself (see LocateControl._setState), so
|
|
882
915
|
* these select the anchor rather than a parent. Written as `.tsmap-control-
|
|
@@ -884,7 +917,7 @@ a.tsmap-control-locate-locating .tsmap-locate-icon {
|
|
|
884
917
|
* nothing and left a denied control looking merely idle.
|
|
885
918
|
*/
|
|
886
919
|
a.tsmap-control-locate-denied .tsmap-locate-icon {
|
|
887
|
-
color:
|
|
920
|
+
color: var(--tsmap-fg-disabled);
|
|
888
921
|
}
|
|
889
922
|
|
|
890
923
|
a.tsmap-control-locate-denied::after {
|
|
@@ -896,34 +929,294 @@ a.tsmap-control-locate-denied::after {
|
|
|
896
929
|
height: 2px;
|
|
897
930
|
border-radius: 1px;
|
|
898
931
|
/* Cut out from the strike so it reads as a line crossing the glyph rather
|
|
899
|
-
|
|
900
|
-
background:
|
|
901
|
-
box-shadow: 0 -2px 0
|
|
932
|
+
than a line drawn on top of it. */
|
|
933
|
+
background: var(--tsmap-fg-muted);
|
|
934
|
+
box-shadow: 0 -2px 0 var(--tsmap-surface);
|
|
902
935
|
transform: translate(-50%, -50%) rotate(-45deg);
|
|
903
936
|
}
|
|
904
937
|
|
|
905
938
|
/* The accuracy halo around the reported position. */
|
|
906
939
|
.tsmap-locate-accuracy {
|
|
907
|
-
fill:
|
|
940
|
+
fill: var(--tsmap-accent);
|
|
908
941
|
fill-opacity: 0.12;
|
|
909
|
-
stroke:
|
|
942
|
+
stroke: var(--tsmap-accent);
|
|
910
943
|
stroke-opacity: 0.35;
|
|
911
944
|
stroke-width: 1;
|
|
912
945
|
}
|
|
913
946
|
|
|
947
|
+
/* The "you are here" dot. A fixed screen size at every zoom — the accuracy
|
|
948
|
+
halo is the thing that carries scale — with a white ring so it stays legible
|
|
949
|
+
over both a near-black basemap and a pale one. */
|
|
950
|
+
.tsmap-locate-dot {
|
|
951
|
+
background: var(--tsmap-accent);
|
|
952
|
+
border: 2px solid #fff;
|
|
953
|
+
border-radius: 50%;
|
|
954
|
+
box-shadow: 0 1px 4px rgb(0 0 0 / 40%);
|
|
955
|
+
box-sizing: border-box;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/* The halo breathing outwards. Drawn on a child rather than ::after because
|
|
959
|
+
the icon element itself is positioned by the marker layer, and a transform
|
|
960
|
+
on it would fight the marker's own translate. */
|
|
961
|
+
.tsmap-locate-dot-pulse {
|
|
962
|
+
position: absolute;
|
|
963
|
+
inset: -2px;
|
|
964
|
+
border-radius: 50%;
|
|
965
|
+
background: var(--tsmap-accent);
|
|
966
|
+
opacity: 0.4;
|
|
967
|
+
animation: tsmap-locate-dot-pulse 2s ease-out infinite;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
@keyframes tsmap-locate-dot-pulse {
|
|
971
|
+
0% {
|
|
972
|
+
transform: scale(1);
|
|
973
|
+
opacity: 0.4;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
100% {
|
|
977
|
+
transform: scale(3);
|
|
978
|
+
opacity: 0;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
914
982
|
@media (prefers-reduced-motion: reduce) {
|
|
915
983
|
a.tsmap-control-locate-locating .tsmap-locate-icon {
|
|
916
984
|
animation: none;
|
|
917
985
|
}
|
|
986
|
+
|
|
987
|
+
.tsmap-locate-dot-pulse {
|
|
988
|
+
animation: none;
|
|
989
|
+
}
|
|
918
990
|
}
|
|
919
991
|
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
992
|
+
|
|
993
|
+
/* geocoder control
|
|
994
|
+
==========================================================================
|
|
995
|
+
The search box. Sized to sit comfortably on a phone, where it is usually the
|
|
996
|
+
widest piece of chrome on the map.
|
|
997
|
+
========================================================================== */
|
|
998
|
+
|
|
999
|
+
.tsmap-control-geocoder {
|
|
1000
|
+
overflow: visible;
|
|
1001
|
+
min-width: 44px;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
.tsmap-control-geocoder-form {
|
|
1005
|
+
display: none;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
.tsmap-control-geocoder-expanded .tsmap-control-geocoder-form {
|
|
1009
|
+
display: block;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
.tsmap-control-geocoder-input {
|
|
1013
|
+
width: 240px;
|
|
1014
|
+
max-width: 60vw;
|
|
1015
|
+
height: 40px;
|
|
1016
|
+
padding: 0 12px;
|
|
1017
|
+
border: 0;
|
|
1018
|
+
border-radius: 8px;
|
|
1019
|
+
background: var(--tsmap-surface);
|
|
1020
|
+
color: var(--tsmap-fg);
|
|
1021
|
+
font: inherit;
|
|
1022
|
+
box-sizing: border-box;
|
|
1023
|
+
|
|
1024
|
+
&::placeholder {
|
|
1025
|
+
color: var(--tsmap-fg-muted);
|
|
923
1026
|
}
|
|
924
1027
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
1028
|
+
&:focus-visible {
|
|
1029
|
+
outline: 2px solid var(--tsmap-accent);
|
|
1030
|
+
outline-offset: -2px;
|
|
928
1031
|
}
|
|
929
1032
|
}
|
|
1033
|
+
|
|
1034
|
+
/* The magnifier, shown only in collapsed mode. */
|
|
1035
|
+
.tsmap-geocoder-icon {
|
|
1036
|
+
display: inline-block;
|
|
1037
|
+
width: 15px;
|
|
1038
|
+
height: 15px;
|
|
1039
|
+
border: 2px solid currentcolor;
|
|
1040
|
+
border-radius: 50%;
|
|
1041
|
+
position: relative;
|
|
1042
|
+
vertical-align: middle;
|
|
1043
|
+
|
|
1044
|
+
&::after {
|
|
1045
|
+
content: '';
|
|
1046
|
+
position: absolute;
|
|
1047
|
+
right: -5px;
|
|
1048
|
+
bottom: -4px;
|
|
1049
|
+
width: 2px;
|
|
1050
|
+
height: 7px;
|
|
1051
|
+
border-radius: 1px;
|
|
1052
|
+
background: currentcolor;
|
|
1053
|
+
transform: rotate(-45deg);
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
.tsmap-control-geocoder-expanded .tsmap-control-geocoder-toggle {
|
|
1058
|
+
display: none;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
/* A spinner would be more literal, but the input is already the thing the eye
|
|
1062
|
+
is on — dimming its text says "working" without adding a moving part. */
|
|
1063
|
+
.tsmap-control-geocoder-busy .tsmap-control-geocoder-input {
|
|
1064
|
+
color: var(--tsmap-fg-muted);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
.tsmap-control-geocoder-list {
|
|
1068
|
+
display: none;
|
|
1069
|
+
list-style: none;
|
|
1070
|
+
margin: 6px 0 0;
|
|
1071
|
+
padding: 4px 0;
|
|
1072
|
+
border-radius: 8px;
|
|
1073
|
+
background: var(--tsmap-surface);
|
|
1074
|
+
box-shadow: var(--tsmap-shadow);
|
|
1075
|
+
max-height: 40vh;
|
|
1076
|
+
overflow-y: auto;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
.tsmap-control-geocoder-open .tsmap-control-geocoder-list {
|
|
1080
|
+
display: block;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
.tsmap-control-geocoder-item {
|
|
1084
|
+
padding: 8px 12px;
|
|
1085
|
+
color: var(--tsmap-fg);
|
|
1086
|
+
cursor: pointer;
|
|
1087
|
+
white-space: nowrap;
|
|
1088
|
+
overflow: hidden;
|
|
1089
|
+
text-overflow: ellipsis;
|
|
1090
|
+
|
|
1091
|
+
&:hover,
|
|
1092
|
+
&.tsmap-control-geocoder-item-active {
|
|
1093
|
+
background: var(--tsmap-surface-hover);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
.tsmap-control-geocoder-marker {
|
|
1098
|
+
background: var(--tsmap-accent);
|
|
1099
|
+
border: 2px solid #fff;
|
|
1100
|
+
border-radius: 50%;
|
|
1101
|
+
box-shadow: 0 1px 4px rgb(0 0 0 / 40%);
|
|
1102
|
+
box-sizing: border-box;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
/* navigation control
|
|
1106
|
+
==========================================================================
|
|
1107
|
+
Zoom pair plus a compass. The needle is drawn in CSS for the same reason the
|
|
1108
|
+
locate crosshair is: it has to recolour with the theme and stay sharp while
|
|
1109
|
+
being rotated by a transform.
|
|
1110
|
+
========================================================================== */
|
|
1111
|
+
|
|
1112
|
+
.tsmap-control-navigation a.tsmap-control-navigation-zoom-in,
|
|
1113
|
+
.tsmap-control-navigation a.tsmap-control-navigation-zoom-out {
|
|
1114
|
+
color: var(--tsmap-fg-muted);
|
|
1115
|
+
font:
|
|
1116
|
+
400 21px / 40px -apple-system,
|
|
1117
|
+
BlinkMacSystemFont,
|
|
1118
|
+
'Segoe UI',
|
|
1119
|
+
Roboto,
|
|
1120
|
+
sans-serif;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
.tsmap-control-navigation a.tsmap-control-navigation-compass {
|
|
1124
|
+
display: flex;
|
|
1125
|
+
align-items: center;
|
|
1126
|
+
justify-content: center;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
.tsmap-compass-needle {
|
|
1130
|
+
width: 4px;
|
|
1131
|
+
height: 22px;
|
|
1132
|
+
position: relative;
|
|
1133
|
+
transition: transform 120ms ease-out;
|
|
1134
|
+
|
|
1135
|
+
/* North half carries the colour; the south half is muted, which is how a
|
|
1136
|
+
compass reads as a compass rather than a pin. */
|
|
1137
|
+
&::before,
|
|
1138
|
+
&::after {
|
|
1139
|
+
content: '';
|
|
1140
|
+
position: absolute;
|
|
1141
|
+
left: 0;
|
|
1142
|
+
width: 0;
|
|
1143
|
+
height: 0;
|
|
1144
|
+
border-left: 2px solid transparent;
|
|
1145
|
+
border-right: 2px solid transparent;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
&::before {
|
|
1149
|
+
top: 0;
|
|
1150
|
+
border-bottom: 11px solid #ea4335;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
&::after {
|
|
1154
|
+
bottom: 0;
|
|
1155
|
+
border-top: 11px solid var(--tsmap-fg-disabled);
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1160
|
+
.tsmap-compass-needle {
|
|
1161
|
+
transition: none;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
/* fullscreen control
|
|
1166
|
+
========================================================================== */
|
|
1167
|
+
|
|
1168
|
+
.tsmap-fullscreen-icon {
|
|
1169
|
+
display: block;
|
|
1170
|
+
width: 16px;
|
|
1171
|
+
height: 16px;
|
|
1172
|
+
position: relative;
|
|
1173
|
+
|
|
1174
|
+
/* Four corner brackets, drawn as two boxes clipped by their own borders. */
|
|
1175
|
+
&::before,
|
|
1176
|
+
&::after {
|
|
1177
|
+
content: '';
|
|
1178
|
+
position: absolute;
|
|
1179
|
+
width: 5px;
|
|
1180
|
+
height: 5px;
|
|
1181
|
+
border: 2px solid currentcolor;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
&::before {
|
|
1185
|
+
top: 0;
|
|
1186
|
+
left: 0;
|
|
1187
|
+
border-right: 0;
|
|
1188
|
+
border-bottom: 0;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
&::after {
|
|
1192
|
+
right: 0;
|
|
1193
|
+
bottom: 0;
|
|
1194
|
+
border-top: 0;
|
|
1195
|
+
border-left: 0;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
.tsmap-control-fullscreen-active .tsmap-fullscreen-icon {
|
|
1200
|
+
&::before {
|
|
1201
|
+
border-right: 0;
|
|
1202
|
+
border-bottom: 0;
|
|
1203
|
+
transform: rotate(180deg);
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
&::after {
|
|
1207
|
+
transform: rotate(180deg);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
/*
|
|
1212
|
+
* Fallback for browsers and embeds where the Fullscreen API is unavailable —
|
|
1213
|
+
* an iframe without `allowfullscreen`, or iPhone Safari, which has never
|
|
1214
|
+
* implemented it. Browser chrome stays visible, but the map fills the viewport.
|
|
1215
|
+
*/
|
|
1216
|
+
.tsmap-pseudo-fullscreen {
|
|
1217
|
+
position: fixed !important;
|
|
1218
|
+
inset: 0 !important;
|
|
1219
|
+
width: 100% !important;
|
|
1220
|
+
height: 100% !important;
|
|
1221
|
+
z-index: 99999;
|
|
1222
|
+
}
|