Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@
ferrostarCore.profile = "bicycle";

ferrostarMap.map = mapInstance;
ferrostarMap.system = "imperial";
ferrostarMap.maxDecimalPlaces = 2;

// Create a search control.
const searchBox = new MapLibreSearchControl({
Expand Down
10 changes: 5 additions & 5 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"lint:fix": "npm run lint -- --fix"
},
"dependencies": {
"@maptimy/platform-formatters": "^0.6.0",
"@maptimy/platform-formatters": "^0.6.1",
"@stadiamaps/ferrostar": "file:../common/ferrostar/pkg",
"lit": "^3.2.1",
"maplibre-gl": "^4.5.0 || ^5"
Expand Down
80 changes: 59 additions & 21 deletions web/src/ferrostar-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,27 @@ import { TripState } from "@stadiamaps/ferrostar";
import "./instructions-view";
import "./trip-progress-view";
import { StateProvider as StateProvider } from "./types";
import { DistanceSystem } from "@maptimy/platform-formatters";

const allowedSystems: Array<DistanceSystem> = [
"metric",
"imperial",
"imperialWithYards",
];

const distanceSystemConverter = {
fromAttribute(value: string | null): DistanceSystem | null {
if (!value) return null;

if (allowedSystems.includes(value as DistanceSystem)) {
return value as DistanceSystem;
}
throw new Error(`Invalid distance system: ${value}`);
},
toAttribute(value: DistanceSystem): string {
return value;
},
};

/**
* A MapLibre-based map component.
Expand Down Expand Up @@ -68,6 +89,18 @@ export class FerrostarMap extends LitElement {
@property({ type: Boolean })
addGeolocateControl: boolean = true;

@property({ converter: distanceSystemConverter })
system?: DistanceSystem;

/**
* Specifies the maximum number of digits allowed after the decimal point
* when formatting distance. This helps control the precision of fractional values.
*
* Example: For a value of 2, the number 3.1415 would be rounded as 3.14.
*/
@property({ type: Number })
maxDecimalPlaces?: number;

/**
* A callback function that is invoked when navigation is stopped.
* Optional: This function can be provided by the StateProvider.
Expand Down Expand Up @@ -390,28 +423,33 @@ export class FerrostarMap extends LitElement {
</style>
<div id="container">
<div id="map">
<slot></slot>
<!-- Fix names/ids; currently this is a breaking change -->
<div id="overlay">
${this.showNavigationUI
? html`
<instructions-view
.tripState=${this.tripState}
.system=${this.system}
.maxDecimalPlaces="${this.maxDecimalPlaces}"
></instructions-view>
<div id="bottom-component">
<trip-progress-view
.tripState=${this.tripState}
.system=${this.system}
.maxDecimalPlaces="${this.maxDecimalPlaces}"
></trip-progress-view>
<button
id="stop-button"
@click=${this.handleStopNavigation}
?hidden=${!this.tripState}
>
<img src=${CloseSvg} alt="Stop navigation" class="icon" />
</button>
</div>
`
: ""}
</div>
</div>

${this.showNavigationUI
? html`
<instructions-view
.tripState=${this.tripState}
></instructions-view>
<div id="bottom-component">
<trip-progress-view
.tripState=${this.tripState}
></trip-progress-view>
<button
id="stop-button"
@click=${this.handleStopNavigation}
?hidden=${!this.tripState}
>
<img src=${CloseSvg} alt="Stop navigation" class="icon" />
</button>
</div>
`
: ""}
</div>
`;
}
Expand Down
23 changes: 23 additions & 0 deletions web/src/formatting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
DistanceSystem,
LocalizedDistanceFormatter,
} from "@maptimy/platform-formatters";

const DistanceFormatter = LocalizedDistanceFormatter();

export function formatDistance(
distanceMeters: number,
system: DistanceSystem = "metric",
desiredMaxDecimalPlaces: number = 2,
): string {
const THRESHOLDS: Record<DistanceSystem, number> = {
metric: 1000,
imperial: 1609.34, // 1 mile
imperialWithYards: 1609.34, // 1 mile
};

const exceedsThreshold = distanceMeters > THRESHOLDS[system];
const decimalPlaces = exceedsThreshold ? desiredMaxDecimalPlaces : 0;

return DistanceFormatter.format(distanceMeters, system, decimalPlaces);
}
15 changes: 11 additions & 4 deletions web/src/instructions-view.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { LitElement, css, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { LocalizedDistanceFormatter } from "@maptimy/platform-formatters";
import { DistanceSystem } from "@maptimy/platform-formatters";
import "./maneuver-image";

const DistanceFormatter = LocalizedDistanceFormatter();
import { formatDistance } from "./formatting";

@customElement("instructions-view")
export class InstructionsView extends LitElement {
@property()
tripState: any = null;

@property()
system: DistanceSystem = "metric";

@property()
maxDecimalPlaces = 2;

static styles = [
css`
.instructions-view-card {
Expand Down Expand Up @@ -63,8 +68,10 @@ export class InstructionsView extends LitElement {
${this.tripState.Navigating.visualInstruction.primaryContent.text}
</p>
<p class="instruction-text">
${DistanceFormatter.format(
${formatDistance(
this.tripState.Navigating.progress.distanceToNextManeuver,
this.system,
this.maxDecimalPlaces,
)}
</p>
</div>
Expand Down
20 changes: 17 additions & 3 deletions web/src/trip-progress-view.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
import {
LocalizedDurationFormatter,
LocalizedDistanceFormatter,
DistanceSystem,
} from "@maptimy/platform-formatters";
import { LitElement, css, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { formatDistance } from "./formatting";

const DurationFormatter = LocalizedDurationFormatter();
const DistanceFormatter = LocalizedDistanceFormatter();

@customElement("trip-progress-view")
export class TripProgressView extends LitElement {
@property()
tripState: any = null;

@property()
system: DistanceSystem = "metric";

/**
* Specifies the maximum number of digits allowed after the decimal point
* when formatting distance. This helps control the precision of fractional values.
*
* Example: For a value of 2, the number 3.1415 would be rounded as 3.14.
*/
@property()
maxDecimalPlaces = 2;

static styles = [
css`
.progress-view-card {
Expand Down Expand Up @@ -65,8 +77,10 @@ export class TripProgressView extends LitElement {
)}
</p>
<p class="arrival-text">
${DistanceFormatter.format(
${formatDistance(
this.tripState.Navigating.progress.distanceRemaining,
this.system,
this.maxDecimalPlaces,
)}
</p>
</div>
Expand Down