diff --git a/src/addGraphicsToLayer.ts b/src/addGraphicsToLayer.ts index 2d0002b3..e486cb2f 100644 --- a/src/addGraphicsToLayer.ts +++ b/src/addGraphicsToLayer.ts @@ -59,3 +59,11 @@ export async function addGraphicsToLayer( return getAddedGraphics(editsResult); } + +if (import.meta.hot) { + import.meta.hot.accept((newModule) => { + if (newModule) { + console.log("hot module replacement", newModule); + } + }); +} diff --git a/src/addWsdotLogo.ts b/src/addWsdotLogo.ts new file mode 100644 index 00000000..ad323884 --- /dev/null +++ b/src/addWsdotLogo.ts @@ -0,0 +1,46 @@ +/** + * Imports the raw SVG markup from the WSDOT logo SVG file. + * @returns A Promise that resolves with the WSDOT logo element. + */ +export async function importWsdotLogoSvg(): Promise { + const { default: svg } = await import( + "@wsdot/web-styles/images/wsdot-logo/wsdot-logo-black.svg?raw" + ); + + // Parse the markup into a DOM element. + const dp = new DOMParser(); + const wsdotLogo = dp.parseFromString(svg, "image/svg+xml") + .documentElement as unknown as SVGSVGElement; + + return wsdotLogo; +} + +/** + * Asynchronously adds the WSDOT logo SVG to the HTML document. + * @param parent - The parent element to which the logo will be added. + * It can be either an HTML element or a CSS selector. + * @returns A Promise that resolves with the WSDOT logo element. + * @throws {Error} If the heading element is not found. + */ +export async function addWsdotLogo(parent: string | Element) { + // Import raw SVG markup from SVG file. + const wsdotLogo = await importWsdotLogoSvg(); + + // Add an id attribute. + wsdotLogo.id = "wsdot-logo"; + const wsdotLogoClass = "wsdot-logo"; + wsdotLogo.classList.add(wsdotLogoClass); + + // Add the logo to the heading element. + // Throw an error if the heading element cannot found. + const parentElement = + typeof parent === "string" ? document.querySelector(parent) : parent; + + if (!parentElement) { + throw new Error("Heading element not found"); + } + // Prepend the logo to the heading element. + parentElement.prepend(wsdotLogo); + // Return the logo element. + return wsdotLogo; +} diff --git a/src/createElcErrorAlert.ts b/src/createElcErrorAlert.ts index 9d8e82a3..63b53dc6 100644 --- a/src/createElcErrorAlert.ts +++ b/src/createElcErrorAlert.ts @@ -98,3 +98,12 @@ export function createErrorAlert( /* __PURE__ */ console.groupEnd(); return cAlert; } + +// Setup hot module reloading. +if (import.meta.hot) { + import.meta.hot.accept((newModule) => { + if (newModule) { + console.log("hot module replacement", newModule); + } + }); +} diff --git a/src/elc/errors.ts b/src/elc/errors.ts index d8e2da0e..75a54852 100644 --- a/src/elc/errors.ts +++ b/src/elc/errors.ts @@ -244,3 +244,12 @@ export const isArcGisError = (input: unknown): input is ArcGisError => input != null && typeof input === "object" && ["code", "message", "details"].every((key) => key in input); + +// Setup hot module reloading. +if (import.meta.hot) { + import.meta.hot.accept((newModule) => { + if (newModule) { + console.log("hot module replacement", newModule); + } + }); +} diff --git a/src/elc/json.ts b/src/elc/json.ts index 7687d563..a16cda22 100644 --- a/src/elc/json.ts +++ b/src/elc/json.ts @@ -20,6 +20,7 @@ export function elcReviver( if (isArcGisErrorResponse(value)) { return new ArcGisError(value); } + // Convert empty strings to null. if (value === "") { return null; } @@ -28,3 +29,12 @@ export function elcReviver( } return value; } + +// Setup hot module reloading. +if (import.meta.hot) { + import.meta.hot.accept((newModule) => { + if (newModule) { + console.log("hot module replacement", newModule); + } + }); +} diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 00000000..a619e4cd --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,3 @@ +/// + +// Add Intellisense for typescript in Vite: https://vitejs.dev/guide/api-hmr.html#intellisense-for-typescript diff --git a/src/main.ts b/src/main.ts index 3eaff068..cc34104e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,3 +1,4 @@ +import { addWsdotLogo } from "./addWsdotLogo"; import { createErrorAlert } from "./createElcErrorAlert"; import { emitErrorEvent } from "./errorEvent"; import type MapView from "@arcgis/core/views/MapView"; @@ -8,42 +9,27 @@ import type { FormatError } from "wsdot-route-utils"; import("@wsdot/web-styles/css/wsdot-colors.css"); -/** - * Asynchronously adds the WSDOT logo SVG to the HTML document. - * @returns A Promise that resolves with the WSDOT logo element. - * @throws {Error} If the heading element is not found. - */ -async function addWsdotLogo() { - // Import raw SVG markup from SVG file. - const { default: svg } = await import( - "@wsdot/web-styles/images/wsdot-logo/wsdot-logo-black.svg?raw" - ); - // Parse the markup into a DOM element. - const dp = new DOMParser(); - const wsdotLogo = dp.parseFromString(svg, "image/svg+xml").documentElement; - - // Add an id attribute. - wsdotLogo.id = "wsdot-logo"; - - // Add the logo to the heading element. - // Throw an error if the heading element cannot found. - const headingSelector = "h2"; - const headingElement = document.body.querySelector(headingSelector); - if (!headingElement) { - throw new Error("Heading element not found"); - } - // Prepend the logo to the heading element. - headingElement.prepend(wsdotLogo); - // Return the logo element. - return wsdotLogo; -} +const wsdotLogoParentSelector = "#header-title"; -addWsdotLogo().catch((reason: unknown) => { +const catchErrorAndEmitInDev = (reason: unknown) => { if (import.meta.env.DEV) { emitErrorEvent(reason); } console.error("Failed to add WSDOT logo.", reason); -}); +}; +addWsdotLogo(wsdotLogoParentSelector).catch(catchErrorAndEmitInDev); + +if (import.meta.hot) { + import.meta.hot.accept("./addWsdotLogo", (mod) => { + if (mod) { + console.log("hot module replacement", mod); + } + document.querySelector(".wsdot-logo")?.remove(); + (mod as unknown as typeof import("./addWsdotLogo")) + .addWsdotLogo(wsdotLogoParentSelector) + .catch(catchErrorAndEmitInDev); + }); +} window.addEventListener("elc-error", (event) => { /* __PURE__ */ console.group("elc-error event listener"); diff --git a/src/setupForm.ts b/src/setupForm.ts index 1561547b..4afe7628 100644 --- a/src/setupForm.ts +++ b/src/setupForm.ts @@ -20,6 +20,8 @@ import type MapView from "@arcgis/core/views/MapView"; export async function setupForm(view: MapView, milepostLayer: FeatureLayer) { const form = await createSrmpInputForm(); + // Add an event listener for the custom event "srmp-input" which will add + // the route location that was submitted to the map. form.addEventListener( "srmp-input", (event: RouteInputEvent) => {