ts-maps 0.3.1 → 0.3.3
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 +56 -0
- package/dist/core-map/control/NavigationControl.d.ts +39 -0
- package/dist/core-map/control/index.d.ts +8 -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 +856 -31
- package/dist/core-map/geo/polygonClip.d.ts +75 -0
- package/dist/core-map/geo/validate.d.ts +54 -0
- package/dist/core-map/geometry/index.js +28 -28
- package/dist/core-map/index.d.ts +8 -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/services/index.js +48 -48
- package/dist/core-map/storage/index.js +5 -5
- 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 +460 -60
- 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 +1072 -68
- 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 +11783 -6100
- package/package.json +2 -2
- package/src/core-map/ts-maps.css +576 -79
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,28 +297,91 @@ 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 {
|
|
297
|
-
|
|
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
|
+
|
|
333
|
+
/* Matched to the land colour of a light basemap, so tiles fade in against
|
|
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);
|
|
298
338
|
outline-offset: 1px;
|
|
299
339
|
|
|
300
340
|
a {
|
|
301
|
-
color:
|
|
341
|
+
color: var(--tsmap-accent);
|
|
302
342
|
}
|
|
303
343
|
}
|
|
304
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
|
+
|
|
305
365
|
/* prevent showing outline-box on Chromium when clicking on a vector with a tooltip */
|
|
306
366
|
path.tsmap-interactive:focus:not(:focus-visible) {
|
|
307
367
|
outline: 0;
|
|
308
368
|
}
|
|
309
369
|
|
|
310
370
|
.tsmap-zoom-box {
|
|
311
|
-
border: 2px dotted
|
|
312
|
-
background:
|
|
371
|
+
border: 2px dotted var(--tsmap-accent);
|
|
372
|
+
background: var(--tsmap-scrim);
|
|
313
373
|
}
|
|
314
374
|
|
|
315
375
|
/* general typography */
|
|
316
376
|
.tsmap-container {
|
|
317
|
-
font-family:
|
|
377
|
+
font-family:
|
|
378
|
+
-apple-system,
|
|
379
|
+
BlinkMacSystemFont,
|
|
380
|
+
'Segoe UI',
|
|
381
|
+
Roboto,
|
|
382
|
+
'Helvetica Neue',
|
|
383
|
+
Arial,
|
|
384
|
+
sans-serif;
|
|
318
385
|
font-size: 12px;
|
|
319
386
|
font-size: 0.75rem;
|
|
320
387
|
line-height: 1.5;
|
|
@@ -322,43 +389,85 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
322
389
|
|
|
323
390
|
/* general toolbar styles */
|
|
324
391
|
|
|
392
|
+
/*
|
|
393
|
+
* Map chrome, styled the way a modern map is expected to look.
|
|
394
|
+
*
|
|
395
|
+
* What this replaces was inherited from Leaflet's 2011 defaults: 26px targets
|
|
396
|
+
* (well under the 44px every touch guideline asks for), a 4px radius, and
|
|
397
|
+
* `0 1px 5px rgba(0,0,0,0.65)` — a shadow at 65% black, which over a light
|
|
398
|
+
* basemap reads as a smudge rather than elevation.
|
|
399
|
+
*
|
|
400
|
+
* The values here follow the conventions every major map now shares: a white
|
|
401
|
+
* card, an 8px radius, a soft two-part shadow (a tight contact edge plus a
|
|
402
|
+
* wide ambient falloff), hairline dividers instead of solid #ccc borders, and
|
|
403
|
+
* the system UI font rather than Lucida Console. Controls also gain a real
|
|
404
|
+
* focus ring, which the old chrome suppressed entirely.
|
|
405
|
+
*/
|
|
325
406
|
.tsmap-bar {
|
|
326
|
-
box-shadow:
|
|
327
|
-
border-radius:
|
|
407
|
+
box-shadow: var(--tsmap-shadow);
|
|
408
|
+
border-radius: 8px;
|
|
409
|
+
overflow: hidden;
|
|
328
410
|
|
|
329
411
|
a {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
width:
|
|
333
|
-
height:
|
|
334
|
-
line-height:
|
|
412
|
+
position: relative;
|
|
413
|
+
background-color: var(--tsmap-surface);
|
|
414
|
+
width: 40px;
|
|
415
|
+
height: 40px;
|
|
416
|
+
line-height: 40px;
|
|
335
417
|
display: block;
|
|
336
418
|
text-align: center;
|
|
337
419
|
text-decoration: none;
|
|
338
|
-
color: black;
|
|
339
420
|
background-position: 50% 50%;
|
|
340
421
|
background-repeat: no-repeat;
|
|
341
422
|
display: block;
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
423
|
+
color: var(--tsmap-fg);
|
|
424
|
+
transition: background-color 120ms ease;
|
|
425
|
+
|
|
426
|
+
&:hover {
|
|
427
|
+
background-color: var(--tsmap-surface-hover);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/* Visible only for keyboard users: a ring on every mouse click is noise,
|
|
431
|
+
and no ring at all makes the control unusable without a pointer. */
|
|
432
|
+
&:focus-visible {
|
|
433
|
+
outline: 2px solid var(--tsmap-accent);
|
|
434
|
+
outline-offset: -2px;
|
|
435
|
+
background-color: var(--tsmap-surface-hover);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/*
|
|
439
|
+
* Inset seam between stacked buttons.
|
|
440
|
+
*
|
|
441
|
+
* A full-width `border-bottom` runs edge to edge and visually cuts the
|
|
442
|
+
* card in two, so a zoom control reads as two stacked cards rather than
|
|
443
|
+
* one control with a divider. Every modern map insets this line; drawing
|
|
444
|
+
* it as a pseudo-element is also what lets the last child simply not have
|
|
445
|
+
* one, without a border reset.
|
|
446
|
+
*/
|
|
447
|
+
&:not(:last-child)::after {
|
|
448
|
+
content: '';
|
|
449
|
+
position: absolute;
|
|
450
|
+
right: 8px;
|
|
451
|
+
bottom: 0;
|
|
452
|
+
left: 8px;
|
|
453
|
+
height: 1px;
|
|
454
|
+
background: var(--tsmap-divider);
|
|
345
455
|
}
|
|
346
456
|
|
|
347
457
|
&:first-child {
|
|
348
|
-
border-top-left-radius:
|
|
349
|
-
border-top-right-radius:
|
|
458
|
+
border-top-left-radius: 8px;
|
|
459
|
+
border-top-right-radius: 8px;
|
|
350
460
|
}
|
|
351
461
|
|
|
352
462
|
&:last-child {
|
|
353
|
-
border-bottom-left-radius:
|
|
354
|
-
border-bottom-right-radius:
|
|
355
|
-
border-bottom: none;
|
|
463
|
+
border-bottom-left-radius: 8px;
|
|
464
|
+
border-bottom-right-radius: 8px;
|
|
356
465
|
}
|
|
357
466
|
|
|
358
467
|
&.tsmap-disabled {
|
|
359
468
|
cursor: default;
|
|
360
|
-
background-color:
|
|
361
|
-
color:
|
|
469
|
+
background-color: var(--tsmap-surface);
|
|
470
|
+
color: var(--tsmap-fg-disabled);
|
|
362
471
|
}
|
|
363
472
|
}
|
|
364
473
|
}
|
|
@@ -369,39 +478,42 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
369
478
|
display: block;
|
|
370
479
|
}
|
|
371
480
|
|
|
481
|
+
/*
|
|
482
|
+
* Touch used to shrink these to 30px with a 2px radius, which is smaller than
|
|
483
|
+
* the pointer size and the wrong way round — a finger needs a bigger target
|
|
484
|
+
* than a cursor, not a smaller one. 40px already clears the 44px guideline
|
|
485
|
+
* once the control's own padding is counted, so both inputs share it.
|
|
486
|
+
*/
|
|
372
487
|
.tsmap-touch .tsmap-bar a {
|
|
373
|
-
width:
|
|
374
|
-
height:
|
|
375
|
-
line-height:
|
|
376
|
-
|
|
377
|
-
&:first-child {
|
|
378
|
-
border-top-left-radius: 2px;
|
|
379
|
-
border-top-right-radius: 2px;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
&:last-child {
|
|
383
|
-
border-bottom-left-radius: 2px;
|
|
384
|
-
border-bottom-right-radius: 2px;
|
|
385
|
-
}
|
|
488
|
+
width: 40px;
|
|
489
|
+
height: 40px;
|
|
490
|
+
line-height: 40px;
|
|
386
491
|
}
|
|
387
492
|
|
|
388
493
|
/* zoom control */
|
|
389
494
|
|
|
390
|
-
.tsmap-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
495
|
+
/* Scoped under .tsmap-bar so it outranks the `.tsmap-bar a` colour above —
|
|
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. */
|
|
498
|
+
.tsmap-bar a.tsmap-control-zoom-in,
|
|
499
|
+
.tsmap-bar a.tsmap-control-zoom-out {
|
|
500
|
+
color: var(--tsmap-fg-muted);
|
|
501
|
+
|
|
502
|
+
font:
|
|
503
|
+
400 21px / 40px -apple-system,
|
|
504
|
+
BlinkMacSystemFont,
|
|
505
|
+
'Segoe UI',
|
|
506
|
+
Roboto,
|
|
507
|
+
sans-serif;
|
|
508
|
+
text-indent: 0;
|
|
397
509
|
}
|
|
398
510
|
|
|
399
511
|
/* layers control */
|
|
400
512
|
|
|
401
513
|
.tsmap-control-layers {
|
|
402
|
-
box-shadow:
|
|
403
|
-
background:
|
|
404
|
-
border-radius:
|
|
514
|
+
box-shadow: var(--tsmap-shadow);
|
|
515
|
+
background: var(--tsmap-surface);
|
|
516
|
+
border-radius: 8px;
|
|
405
517
|
|
|
406
518
|
.tsmap-control-layers-list {
|
|
407
519
|
display: none;
|
|
@@ -419,6 +531,12 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
419
531
|
width: 44px;
|
|
420
532
|
height: 44px;
|
|
421
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
|
+
}
|
|
422
540
|
}
|
|
423
541
|
|
|
424
542
|
.tsmap-control-layers-expanded {
|
|
@@ -440,8 +558,8 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
440
558
|
|
|
441
559
|
.tsmap-control-layers-expanded {
|
|
442
560
|
padding: 6px 10px 6px 6px;
|
|
443
|
-
color:
|
|
444
|
-
background:
|
|
561
|
+
color: var(--tsmap-fg);
|
|
562
|
+
background: var(--tsmap-surface);
|
|
445
563
|
}
|
|
446
564
|
|
|
447
565
|
.tsmap-control-layers-scrollbar {
|
|
@@ -464,7 +582,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
464
582
|
|
|
465
583
|
.tsmap-control-layers-separator {
|
|
466
584
|
height: 0;
|
|
467
|
-
border-top: 1px solid
|
|
585
|
+
border-top: 1px solid var(--tsmap-hairline);
|
|
468
586
|
margin: 5px -10px 5px -6px;
|
|
469
587
|
}
|
|
470
588
|
|
|
@@ -476,15 +594,14 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
476
594
|
/* attribution and scale controls */
|
|
477
595
|
|
|
478
596
|
.tsmap-container .tsmap-control-attribution {
|
|
479
|
-
background:
|
|
480
|
-
background: rgba(255, 255, 255, 0.8);
|
|
597
|
+
background: var(--tsmap-scrim);
|
|
481
598
|
margin: 0;
|
|
482
599
|
}
|
|
483
600
|
|
|
484
601
|
.tsmap-control-attribution,
|
|
485
602
|
.tsmap-control-scale-line {
|
|
486
603
|
padding: 0 5px;
|
|
487
|
-
color:
|
|
604
|
+
color: var(--tsmap-fg);
|
|
488
605
|
line-height: 1.4;
|
|
489
606
|
}
|
|
490
607
|
|
|
@@ -514,36 +631,40 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
514
631
|
}
|
|
515
632
|
|
|
516
633
|
.tsmap-control-scale-line {
|
|
517
|
-
border: 2px solid
|
|
634
|
+
border: 2px solid var(--tsmap-scale-line);
|
|
518
635
|
border-top: none;
|
|
519
636
|
line-height: 1.1;
|
|
520
637
|
padding: 2px 5px 1px;
|
|
521
638
|
white-space: nowrap;
|
|
522
639
|
box-sizing: border-box;
|
|
523
|
-
background:
|
|
524
|
-
text-shadow: 1px 1px #fff;
|
|
640
|
+
background: var(--tsmap-scrim);
|
|
525
641
|
|
|
526
642
|
&:not(:first-child) {
|
|
527
|
-
border-top: 2px solid
|
|
643
|
+
border-top: 2px solid var(--tsmap-scale-line);
|
|
528
644
|
border-bottom: none;
|
|
529
645
|
margin-top: -2px;
|
|
530
646
|
|
|
531
647
|
&:not(:last-child) {
|
|
532
|
-
border-bottom: 2px solid
|
|
648
|
+
border-bottom: 2px solid var(--tsmap-scale-line);
|
|
533
649
|
}
|
|
534
650
|
}
|
|
535
651
|
}
|
|
536
652
|
|
|
653
|
+
/*
|
|
654
|
+
* Touch controls are the same controls.
|
|
655
|
+
*
|
|
656
|
+
* This block used to swap the elevated card for a flat one with a hard
|
|
657
|
+
* `2px solid rgba(0,0,0,0.2)` border — the Leaflet touch treatment, and the
|
|
658
|
+
* reason the chrome looked a decade old on exactly the devices most people
|
|
659
|
+
* open a map on. A shadow is not a pointer affordance; it is how a floating
|
|
660
|
+
* control reads as floating, on any input. Phones render it fine.
|
|
661
|
+
*
|
|
662
|
+
* The touch class still exists and still drives hit-target sizing above; it
|
|
663
|
+
* just no longer restyles the surface.
|
|
664
|
+
*/
|
|
537
665
|
.tsmap-touch {
|
|
538
|
-
.tsmap-control-attribution,
|
|
539
666
|
.tsmap-control-layers,
|
|
540
667
|
.tsmap-bar {
|
|
541
|
-
box-shadow: none;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
.tsmap-control-layers,
|
|
545
|
-
.tsmap-bar {
|
|
546
|
-
border: 2px solid rgba(0, 0, 0, 0.2);
|
|
547
668
|
background-clip: padding-box;
|
|
548
669
|
}
|
|
549
670
|
}
|
|
@@ -597,9 +718,9 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
597
718
|
|
|
598
719
|
.tsmap-popup-content-wrapper,
|
|
599
720
|
.tsmap-popup-tip {
|
|
600
|
-
background:
|
|
601
|
-
color:
|
|
602
|
-
box-shadow:
|
|
721
|
+
background: var(--tsmap-surface);
|
|
722
|
+
color: var(--tsmap-fg);
|
|
723
|
+
box-shadow: var(--tsmap-shadow-lg);
|
|
603
724
|
}
|
|
604
725
|
|
|
605
726
|
.tsmap-container a.tsmap-popup-close-button {
|
|
@@ -611,13 +732,13 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
611
732
|
width: 24px;
|
|
612
733
|
height: 24px;
|
|
613
734
|
font: 16px/24px Tahoma, Verdana, sans-serif;
|
|
614
|
-
color:
|
|
735
|
+
color: var(--tsmap-fg-muted);
|
|
615
736
|
text-decoration: none;
|
|
616
737
|
background: transparent;
|
|
617
738
|
|
|
618
739
|
&:hover,
|
|
619
740
|
&:focus {
|
|
620
|
-
color:
|
|
741
|
+
color: var(--tsmap-fg);
|
|
621
742
|
}
|
|
622
743
|
}
|
|
623
744
|
|
|
@@ -628,8 +749,8 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
628
749
|
/* div icon */
|
|
629
750
|
|
|
630
751
|
.tsmap-div-icon {
|
|
631
|
-
background:
|
|
632
|
-
border: 1px solid
|
|
752
|
+
background: var(--tsmap-surface);
|
|
753
|
+
border: 1px solid var(--tsmap-fg-muted);
|
|
633
754
|
}
|
|
634
755
|
|
|
635
756
|
/* Tooltip */
|
|
@@ -637,14 +758,14 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
637
758
|
.tsmap-tooltip {
|
|
638
759
|
position: absolute;
|
|
639
760
|
padding: 6px;
|
|
640
|
-
background-color:
|
|
641
|
-
border: 1px solid
|
|
761
|
+
background-color: var(--tsmap-surface);
|
|
762
|
+
border: 1px solid var(--tsmap-surface);
|
|
642
763
|
border-radius: 3px;
|
|
643
|
-
color:
|
|
764
|
+
color: var(--tsmap-fg);
|
|
644
765
|
white-space: nowrap;
|
|
645
766
|
user-select: none;
|
|
646
767
|
pointer-events: none;
|
|
647
|
-
box-shadow: 0 1px 3px
|
|
768
|
+
box-shadow: 0 1px 3px rgb(0 0 0 / 40%);
|
|
648
769
|
|
|
649
770
|
&.tsmap-interactive {
|
|
650
771
|
cursor: pointer;
|
|
@@ -674,7 +795,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
674
795
|
top: 0;
|
|
675
796
|
margin-top: -12px;
|
|
676
797
|
margin-left: -6px;
|
|
677
|
-
border-bottom-color:
|
|
798
|
+
border-bottom-color: var(--tsmap-surface);
|
|
678
799
|
}
|
|
679
800
|
}
|
|
680
801
|
|
|
@@ -686,7 +807,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
686
807
|
margin-left: -6px;
|
|
687
808
|
bottom: 0;
|
|
688
809
|
margin-bottom: -12px;
|
|
689
|
-
border-top-color:
|
|
810
|
+
border-top-color: var(--tsmap-surface);
|
|
690
811
|
}
|
|
691
812
|
}
|
|
692
813
|
|
|
@@ -698,7 +819,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
698
819
|
margin-top: -6px;
|
|
699
820
|
right: 0;
|
|
700
821
|
margin-right: -12px;
|
|
701
|
-
border-left-color:
|
|
822
|
+
border-left-color: var(--tsmap-surface);
|
|
702
823
|
}
|
|
703
824
|
}
|
|
704
825
|
|
|
@@ -710,7 +831,7 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
710
831
|
margin-top: -6px;
|
|
711
832
|
left: 0;
|
|
712
833
|
margin-left: -12px;
|
|
713
|
-
border-right-color:
|
|
834
|
+
border-right-color: var(--tsmap-surface);
|
|
714
835
|
}
|
|
715
836
|
}
|
|
716
837
|
|
|
@@ -723,3 +844,379 @@ path.tsmap-interactive:focus:not(:focus-visible) {
|
|
|
723
844
|
print-color-adjust: exact;
|
|
724
845
|
}
|
|
725
846
|
}
|
|
847
|
+
|
|
848
|
+
/* locate control
|
|
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
|
+
========================================================================== */
|
|
854
|
+
|
|
855
|
+
.tsmap-control-locate a {
|
|
856
|
+
display: flex;
|
|
857
|
+
align-items: center;
|
|
858
|
+
justify-content: center;
|
|
859
|
+
position: relative;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
.tsmap-locate-icon {
|
|
863
|
+
position: relative;
|
|
864
|
+
width: 18px;
|
|
865
|
+
height: 18px;
|
|
866
|
+
color: var(--tsmap-fg-muted);
|
|
867
|
+
|
|
868
|
+
/* The ring. */
|
|
869
|
+
&::before {
|
|
870
|
+
content: '';
|
|
871
|
+
position: absolute;
|
|
872
|
+
inset: 3px;
|
|
873
|
+
border: 2px solid currentcolor;
|
|
874
|
+
border-radius: 50%;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
/* The centre dot, and the four ticks via a cross gradient. */
|
|
878
|
+
&::after {
|
|
879
|
+
content: '';
|
|
880
|
+
position: absolute;
|
|
881
|
+
inset: 0;
|
|
882
|
+
background:
|
|
883
|
+
linear-gradient(currentcolor, currentcolor) 50% 0 / 2px 4px no-repeat,
|
|
884
|
+
linear-gradient(currentcolor, currentcolor) 50% 100% / 2px 4px no-repeat,
|
|
885
|
+
linear-gradient(currentcolor, currentcolor) 0 50% / 4px 2px no-repeat,
|
|
886
|
+
linear-gradient(currentcolor, currentcolor) 100% 50% / 4px 2px no-repeat,
|
|
887
|
+
radial-gradient(circle at 50% 50%, currentcolor 0 2px, transparent 2px);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
/* Following the device: the crosshair fills in, the way a "you are here"
|
|
892
|
+
control does everywhere else. */
|
|
893
|
+
a.tsmap-control-locate-active .tsmap-locate-icon {
|
|
894
|
+
color: var(--tsmap-accent);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/* Acquiring a first fix. The pulse is the only thing telling the user that a
|
|
898
|
+
press did anything at all — a GPS fix can take several seconds. */
|
|
899
|
+
a.tsmap-control-locate-locating .tsmap-locate-icon {
|
|
900
|
+
color: var(--tsmap-accent);
|
|
901
|
+
animation: tsmap-locate-pulse 1s ease-in-out infinite;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
@keyframes tsmap-locate-pulse {
|
|
905
|
+
50% {
|
|
906
|
+
opacity: 0.35;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/* Denied or unavailable. Struck through rather than merely greyed: grey reads
|
|
911
|
+
as "disabled, try later" when the real state is "this will not work until
|
|
912
|
+
you change a browser setting". */
|
|
913
|
+
/*
|
|
914
|
+
* The state class lands on the <a> itself (see LocateControl._setState), so
|
|
915
|
+
* these select the anchor rather than a parent. Written as `.tsmap-control-
|
|
916
|
+
* locate-denied .tsmap-locate-icon` first time round, which silently matched
|
|
917
|
+
* nothing and left a denied control looking merely idle.
|
|
918
|
+
*/
|
|
919
|
+
a.tsmap-control-locate-denied .tsmap-locate-icon {
|
|
920
|
+
color: var(--tsmap-fg-disabled);
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
a.tsmap-control-locate-denied::after {
|
|
924
|
+
content: '';
|
|
925
|
+
position: absolute;
|
|
926
|
+
top: 50%;
|
|
927
|
+
left: 50%;
|
|
928
|
+
width: 22px;
|
|
929
|
+
height: 2px;
|
|
930
|
+
border-radius: 1px;
|
|
931
|
+
/* Cut out from the strike so it reads as a line crossing the glyph rather
|
|
932
|
+
than a line drawn on top of it. */
|
|
933
|
+
background: var(--tsmap-fg-muted);
|
|
934
|
+
box-shadow: 0 -2px 0 var(--tsmap-surface);
|
|
935
|
+
transform: translate(-50%, -50%) rotate(-45deg);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/* The accuracy halo around the reported position. */
|
|
939
|
+
.tsmap-locate-accuracy {
|
|
940
|
+
fill: var(--tsmap-accent);
|
|
941
|
+
fill-opacity: 0.12;
|
|
942
|
+
stroke: var(--tsmap-accent);
|
|
943
|
+
stroke-opacity: 0.35;
|
|
944
|
+
stroke-width: 1;
|
|
945
|
+
}
|
|
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
|
+
|
|
982
|
+
@media (prefers-reduced-motion: reduce) {
|
|
983
|
+
a.tsmap-control-locate-locating .tsmap-locate-icon {
|
|
984
|
+
animation: none;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
.tsmap-locate-dot-pulse {
|
|
988
|
+
animation: none;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
|
|
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);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
&:focus-visible {
|
|
1029
|
+
outline: 2px solid var(--tsmap-accent);
|
|
1030
|
+
outline-offset: -2px;
|
|
1031
|
+
}
|
|
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
|
+
}
|