UNPKG

@ugrc/layer-selector

Version:

This is a react component for adding a quick base map selector with a happy path for using [UGRC's Discover Service](https://gis.utah.gov/discover).

406 lines (405 loc) 13.4 kB
import { jsxs as k, jsx as u, Fragment as F } from "react/jsx-runtime"; import W from "@arcgis/core/Basemap.js"; import j from "@arcgis/core/layers/FeatureLayer.js"; import S from "@arcgis/core/layers/support/LOD.js"; import N from "@arcgis/core/layers/support/TileInfo.js"; import z from "@arcgis/core/layers/TileLayer.js"; import T from "@arcgis/core/layers/WebTileLayer.js"; import C from "clsx"; import t from "prop-types"; import { useState as w, useRef as _, useEffect as L } from "react"; const $ = (e, o, l) => { const f = o.lods, g = f.slice(0, 20), h = f.slice(0, 18), s = f.slice(0, 19); e.Imagery.tileInfo = new l(o), e.Hybrid.tileInfo = new l(o); let d = Object.assign({}, o); return d.lods = s, e["Color IR"].tileInfo = new l(d), d = Object.assign({}, o), d.lods = h, e.Topo.tileInfo = new l(d), d = Object.assign({}, o), d.lods = g, e.Lite.tileInfo = new l(d), e.Overlay.tileInfo = new l(d), e; }, A = (e) => { const l = 40075016685568e-6, f = 39.37, g = l / 256, h = 96, s = 20, d = 2, v = []; for (let p = 0; p <= s; p++) { const a = g / Math.pow(d, p), y = a * h * f; v.push( new e({ level: p, scale: y, resolution: a }) ); } return { dpi: h, size: 256, origin: { x: -20037508342787e-6, y: 20037508342787e-6 }, spatialReference: { wkid: 3857 }, lods: v }; }, M = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='26'%20height='26'%20viewBox='0%200%2026%2026'%3e%3cg%20fill='none'%20stroke='%23555'%20stroke-width='3'%20stroke-miterlimit='9'%3e%3cpath%20transform='matrix(.95342%20.30165%20-.95342%20.30165%200%20-1026)'%20d='M1715%201701h10v10h-10zM1734%201709v11.2h-11.2M1744%201719v11.2h-11.2'/%3e%3c/g%3e%3c/svg%3e", U = { FeatureLayer: j, WebTileLayer: T, TileLayer: z }, E = (e) => { const [o, l] = w(e.expanded), f = C("layer-selector__toggle", { "layer-selector--hidden": o }), g = C({ "layer-selector--hidden": !o }); return /* @__PURE__ */ k( "div", { className: "layer-selector esri-component esri-widget", onMouseOver: () => l(!0), onMouseOut: () => l(!1), "aria-haspopup": "true", children: [ /* @__PURE__ */ u("input", { type: "image", className: f, src: M, alt: "layers" }), /* @__PURE__ */ u("form", { className: g, children: e.children }) ] } ); }; E.propTypes = { children: t.object, expanded: t.bool }; const q = (e) => { const o = { type: e.layerType === "baselayer" ? "radio" : "checkbox", name: e.layerType, value: e.id }; return /* @__PURE__ */ u("div", { className: "layer-selector-item radio checkbox", children: /* @__PURE__ */ k("label", { className: "layer-selector--item", children: [ /* @__PURE__ */ u( "input", { ...o, checked: e.selected, onChange: (l) => e.onChange(l, e) } ), /* @__PURE__ */ u("span", { className: "layer-selector-item--text", children: o.value }) ] }) }); }, R = "https://mapserv.utah.gov/cdn/attribution/imagery.json", P = (e, o, l, f, g) => { const h = []; return o.forEach((s) => { if (typeof s == "string" || s instanceof String || s.token || typeof s.token == "string" || s.token instanceof String) { const v = s.token || s; if (!f) return console.warn( "layer-selector::You chose to use a layer token `" + v + "` without setting your `quadWord` from Discover. The requests for tiles will fail to authenticate. Pass `quadWord` into the constructor of this widget." ), !1; var d = g[v]; if (!d) return console.warn( "layer-selector::The layer token `" + v + "` was not found. Please use one of the supported tokens (" + Object.keys(g).join(", ") + ") or pass in the information on how to create your custom layer (`{Factory, url, id}`)." ), !1; const p = [d.linked, s.linked].reduce((a, y, r) => (y && (a = a.concat(y)), r === 1 && a.length === 0 ? null : a), []); h.push({ Factory: l, urlTemplate: d.urlPattern, linked: p, id: v, selected: !!s.selected, copyright: d.copyright, layerType: e // TODO: not supported in 4.x WebTileLayer copyright // hasAttributionData: layer.hasAttributionData, // attributionDataUrl: layer.attributionDataUrl }); } else { if (Object.prototype.hasOwnProperty.call(s, "layerType") || (s.layerType = e), s.selected || (s.selected = !1), typeof s.Factory == "string" && (s.Factory = U[s.Factory], !s.Factory)) throw new Error(`Unknown layer factory: ${s.Factory}`); h.push(s); } }), h; }, D = ({ condition: e, wrapper: o, children: l }) => e ? o(l) : l, H = { makeExpandable: !0, position: "top-right", showOpacitySlider: !1 }, G = (e) => { e = { ...H, ...e }; const [o, l] = w({ baseLayers: [], overlays: [] }), [f, g] = w([]), [h, s] = w({}), d = _(); function v(a) { const y = parseFloat(a.target.value) / 100; if (e.showOpacitySlider) for (const r in h) { const n = h[r]; if (n.layer) { const i = (n.layer.originalOpacity ?? 1) - (1 - y); n.layer.opacity = i < 0 ? 0 : i; } } } L(() => { const a = { ...h }; o.baseLayers.concat(o.overlays).forEach((r) => { var i; let n = null; switch (r.layerType) { case "baselayer": (i = e.view.map.basemap) != null && i.baseLayers || (e.view.map.basemap = { baseLayers: [], id: "layer-selector", title: "layer-selector" }), n = e.view.map.basemap.baseLayers; break; case "overlay": n = e.view.map.layers; break; default: throw new Error(`unknown layerType: ${r.layerType}`); } if (r.selected === !1) { var c = a[r.id] || {}; c.layer || (c.layer = n.getItemAt( n.indexOf(r.layer) )), c.layer && n.remove(c.layer); return; } Object.keys(a).indexOf(r.id) < 0 && (a[r.id] = { layerType: r.layerType }), a[r.id].layer || (a[r.id].layer = new r.Factory({ originalOpacity: r.opacity, ...r })), r.selected === !0 ? n.includes(a[r.id].layer) || n.add(a[r.id].layer) : n.remove(a[r.id].layer), a[r.id].layer.when("loaded", () => { const b = a[r.id].layer.tileInfo.lods[e.view.zoom].scale; e.view.zoom > -1 && e.view.scale !== b && (e.view.zoom = e.view.zoom); }), s(a); }); }, [o]), L(() => { if (!e.baseLayers || e.baseLayers.length < 1) { console.warn( "layer-selector::`baseLayers` is null or empty. Make sure you have spelled it correctly and are passing it into the constructor of this widget." ); return; } }, [e.baseLayers]), L(() => { var x; const a = { Imagery: { urlPattern: `https://discover.agrc.utah.gov/login/path/${e.quadWord}/tiles/utah/{level}/{col}/{row}`, hasAttributionData: !0, copyright: "Hexagon", attributionDataUrl: R }, Topo: { urlPattern: `https://discover.agrc.utah.gov/login/path/${e.quadWord}/tiles/topo_basemap/{level}/{col}/{row}`, copyright: "UGRC" }, Terrain: { urlPattern: `https://discover.agrc.utah.gov/login/path/${e.quadWord}/tiles/terrain_basemap/{level}/{col}/{row}`, copyright: "UGRC" }, Lite: { urlPattern: `https://discover.agrc.utah.gov/login/path/${e.quadWord}/tiles/lite_basemap/{level}/{col}/{row}`, copyright: "UGRC" }, "Color IR": { urlPattern: `https://discover.agrc.utah.gov/login/path/${e.quadWord}/tiles/naip_2021_nrg/{level}/{col}/{row}`, copyright: "UGRC" }, Hybrid: { urlPattern: `https://discover.agrc.utah.gov/login/path/${e.quadWord}/tiles/utah/{level}/{col}/{row}`, linked: ["Overlay"], copyright: "Hexagon, UGRC", hasAttributionData: !0, attributionDataUrl: R }, Overlay: { urlPattern: `https://discover.agrc.utah.gov/login/path/${e.quadWord}/tiles/overlay_basemap/{level}/{col}/{row}` // no attribution for overlay layers since it just duplicates the base map attribution }, "Address Points": { urlPattern: `https://discover.agrc.utah.gov/login/path/${e.quadWord}/tiles/address_points_basemap/{level}/{col}/{row}` } }; try { e.view.map.basemap = new W(); } catch { console.warn( "layer-selector::You must pass a view with a map to the constructor of this widget." ); } const y = A(S), r = $( a, y, N ), n = P( "baselayer", e.baseLayers, T, e.quadWord, r ) || []; let c = e.overlays || [], i = null, b = !1, O = []; n.forEach((m) => { m.selected === !0 && (i = m), (m.id || m.token) === "Hybrid" && (b = !0), m.linked && (O = O.concat(m.linked)); }), g(O), !i && n.length > 0 && (n[0].selected = !0, i = n[0]), b && c[0] !== "Overlay" && ((x = c[0]) == null ? void 0 : x.id) !== "Overlay" && c.splice(0, 0, "Overlay"), c = P( "overlay", c, T, e.quadWord, r ) || [], i != null && i.linked && i.linked.length > 0 && c.forEach((m) => { i.linked.includes(m.id) && (m.selected = !0); }), l({ baseLayers: n, overlays: c }), e.view.ui.add(d.current, e.position); }, [ e.baseLayers, e.overlays, e.position, e.quadWord, e.view.map, e.view.ui ]); const p = (a, y) => { console.log("LayerSelector.onItemChanged", y); const r = o.overlays, n = o.baseLayers; if (y.layerType === "baselayer") { n.forEach((i) => { i.selected = i.id === y.id ? a.target.checked : !1; }); const c = n.filter((i) => i.selected)[0]; r.forEach((i) => { f.includes(i.id) && (i.selected = !1); }), c.linked && c.linked.length > 0 && r.forEach((i) => (c.linked.includes(i.id) && (i.selected = !0), i)); } else y.layerType === "overlay" && r.forEach((c) => { c.id === y.id && (c.selected = a.target.checked); }); l({ overlays: r, baseLayers: n }); }; return /* @__PURE__ */ u("div", { ref: d, children: /* @__PURE__ */ u( D, { condition: e.makeExpandable, wrapper: (a) => /* @__PURE__ */ u(E, { children: a }), children: /* @__PURE__ */ k("div", { className: "layer-selector--layers", children: [ o.baseLayers.map((a, y) => /* @__PURE__ */ u( q, { id: a.name || a.id || "unknown", layerType: "baselayer", selected: a.selected, onChange: p }, y )), o.overlays.length ? /* @__PURE__ */ u("hr", { className: "layer-selector-separator" }) : null, o.overlays.map((a) => /* @__PURE__ */ u( q, { id: a.name || a.id || "unknown", layerType: "overlay", selected: a.selected, onChange: p }, a.id || a )), e.showOpacitySlider ? /* @__PURE__ */ k(F, { children: [ /* @__PURE__ */ u("hr", { className: "layer-selector-separator" }), /* @__PURE__ */ u( "input", { type: "range", min: "0", max: "100", step: "1", defaultValue: "100", onChange: v } ) ] }) : null ] }) } ) }); }; G.propTypes = { view: t.object.isRequired, quadWord: t.string, baseLayers: t.arrayOf( t.oneOfType([ t.oneOf([ "Hybrid", "Lite", "Terrain", "Topo", "Color IR", "Address Points", "Overlay", "Imagery" ]), t.shape({ Factory: t.oneOfType([t.func, t.string]).isRequired, urlTemplate: t.string, url: t.string, id: t.string.isRequired, tileInfo: t.object, linked: t.arrayOf(t.string) }), t.shape({ token: t.oneOf([ "Hybrid", "Lite", "Terrain", "Topo", "Color IR", "Address Points", "Overlay" ]).isRequired, selected: t.bool, linked: t.arrayOf(t.string) }) ]) ).isRequired, overlays: t.arrayOf( t.oneOfType([ t.oneOf(["Address Points", "Overlay"]), t.shape({ Factory: t.oneOfType([t.func, t.string]).isRequired, urlTemplate: t.string, url: t.string, id: t.string.isRequired, tileInfo: t.object, linked: t.arrayOf(t.string) }) ]) ), position: t.oneOf([ "bottom-leading", "bottom-left", "bottom-right", "bottom-trailing", "top-leading", "top-left", "top-right", "top-trailing" ]), makeExpandable: t.bool, layerType: t.string, id: t.string, showOpacitySlider: t.bool }; q.propTypes = { onChange: t.func.isRequired, selected: t.bool.isRequired, layerType: t.oneOf(["baselayer", "overlay"]).isRequired, id: t.string.isRequired }; export { E as ExpandableContainer, q as LayerSelectorItem, G as default }; //# sourceMappingURL=index.es.js.map