Add progressive web app companion for cross-platform access

Vite + TypeScript PWA that mirrors the Android app's core features:
- Pre-processed shelter data (build-time UTM33N→WGS84 conversion)
- Leaflet map with shelter markers, user location, and offline tiles
- Canvas compass arrow (ported from DirectionArrowView.kt)
- IndexedDB shelter cache with 7-day staleness check
- Service worker with CacheFirst tiles and precached app shell
- i18n for en, nb, nn (ported from Android strings.xml)
- iOS/Android compass handling with low-pass filter
- Respects user map interaction (no auto-snap on pan/zoom)
- Build revision cache-breaker for reliable SW updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-03-08 17:41:38 +01:00
commit e8428de775
12051 changed files with 1799735 additions and 0 deletions

91
pwa/node_modules/leaflet/src/dom/DomEvent.DoubleTap.js generated vendored Normal file
View file

@ -0,0 +1,91 @@
import * as DomEvent from './DomEvent';
/*
* Extends the event handling code with double tap support for mobile browsers.
*
* Note: currently most browsers fire native dblclick, with only a few exceptions
* (see https://github.com/Leaflet/Leaflet/issues/7012#issuecomment-595087386)
*/
function makeDblclick(event) {
// in modern browsers `type` cannot be just overridden:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only
var newEvent = {},
prop, i;
for (i in event) {
prop = event[i];
newEvent[i] = prop && prop.bind ? prop.bind(event) : prop;
}
event = newEvent;
newEvent.type = 'dblclick';
newEvent.detail = 2;
newEvent.isTrusted = false;
newEvent._simulated = true; // for debug purposes
return newEvent;
}
var delay = 200;
export function addDoubleTapListener(obj, handler) {
// Most browsers handle double tap natively
obj.addEventListener('dblclick', handler);
// On some platforms the browser doesn't fire native dblclicks for touch events.
// It seems that in all such cases `detail` property of `click` event is always `1`.
// So here we rely on that fact to avoid excessive 'dblclick' simulation when not needed.
var last = 0,
detail;
function simDblclick(e) {
if (e.detail !== 1) {
detail = e.detail; // keep in sync to avoid false dblclick in some cases
return;
}
if (e.pointerType === 'mouse' ||
(e.sourceCapabilities && !e.sourceCapabilities.firesTouchEvents)) {
return;
}
// When clicking on an <input>, the browser generates a click on its
// <label> (and vice versa) triggering two clicks in quick succession.
// This ignores clicks on elements which are a label with a 'for'
// attribute (or children of such a label), but not children of
// a <input>.
var path = DomEvent.getPropagationPath(e);
if (path.some(function (el) {
return el instanceof HTMLLabelElement && el.attributes.for;
}) &&
!path.some(function (el) {
return (
el instanceof HTMLInputElement ||
el instanceof HTMLSelectElement
);
})
) {
return;
}
var now = Date.now();
if (now - last <= delay) {
detail++;
if (detail === 2) {
handler(makeDblclick(e));
}
} else {
detail = 1;
}
last = now;
}
obj.addEventListener('click', simDblclick);
return {
dblclick: handler,
simDblclick: simDblclick
};
}
export function removeDoubleTapListener(obj, handlers) {
obj.removeEventListener('dblclick', handlers.dblclick);
obj.removeEventListener('click', handlers.simDblclick);
}

97
pwa/node_modules/leaflet/src/dom/DomEvent.Pointer.js generated vendored Normal file
View file

@ -0,0 +1,97 @@
import * as DomEvent from './DomEvent';
import Browser from '../core/Browser';
import {falseFn} from '../core/Util';
/*
* Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.
*/
var POINTER_DOWN = Browser.msPointer ? 'MSPointerDown' : 'pointerdown';
var POINTER_MOVE = Browser.msPointer ? 'MSPointerMove' : 'pointermove';
var POINTER_UP = Browser.msPointer ? 'MSPointerUp' : 'pointerup';
var POINTER_CANCEL = Browser.msPointer ? 'MSPointerCancel' : 'pointercancel';
var pEvent = {
touchstart : POINTER_DOWN,
touchmove : POINTER_MOVE,
touchend : POINTER_UP,
touchcancel : POINTER_CANCEL
};
var handle = {
touchstart : _onPointerStart,
touchmove : _handlePointer,
touchend : _handlePointer,
touchcancel : _handlePointer
};
var _pointers = {};
var _pointerDocListener = false;
// Provides a touch events wrapper for (ms)pointer events.
// ref https://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890
export function addPointerListener(obj, type, handler) {
if (type === 'touchstart') {
_addPointerDocListener();
}
if (!handle[type]) {
console.warn('wrong event specified:', type);
return falseFn;
}
handler = handle[type].bind(this, handler);
obj.addEventListener(pEvent[type], handler, false);
return handler;
}
export function removePointerListener(obj, type, handler) {
if (!pEvent[type]) {
console.warn('wrong event specified:', type);
return;
}
obj.removeEventListener(pEvent[type], handler, false);
}
function _globalPointerDown(e) {
_pointers[e.pointerId] = e;
}
function _globalPointerMove(e) {
if (_pointers[e.pointerId]) {
_pointers[e.pointerId] = e;
}
}
function _globalPointerUp(e) {
delete _pointers[e.pointerId];
}
function _addPointerDocListener() {
// need to keep track of what pointers and how many are active to provide e.touches emulation
if (!_pointerDocListener) {
// we listen document as any drags that end by moving the touch off the screen get fired there
document.addEventListener(POINTER_DOWN, _globalPointerDown, true);
document.addEventListener(POINTER_MOVE, _globalPointerMove, true);
document.addEventListener(POINTER_UP, _globalPointerUp, true);
document.addEventListener(POINTER_CANCEL, _globalPointerUp, true);
_pointerDocListener = true;
}
}
function _handlePointer(handler, e) {
if (e.pointerType === (e.MSPOINTER_TYPE_MOUSE || 'mouse')) { return; }
e.touches = [];
for (var i in _pointers) {
e.touches.push(_pointers[i]);
}
e.changedTouches = [e];
handler(e);
}
function _onPointerStart(handler, e) {
// IE10 specific: MsTouch needs preventDefault. See #2000
if (e.MSPOINTER_TYPE_TOUCH && e.pointerType === e.MSPOINTER_TYPE_TOUCH) {
DomEvent.preventDefault(e);
}
_handlePointer(handler, e);
}

315
pwa/node_modules/leaflet/src/dom/DomEvent.js generated vendored Normal file
View file

@ -0,0 +1,315 @@
import {Point} from '../geometry/Point';
import * as Util from '../core/Util';
import Browser from '../core/Browser';
import {addPointerListener, removePointerListener} from './DomEvent.Pointer';
import {addDoubleTapListener, removeDoubleTapListener} from './DomEvent.DoubleTap';
import {getScale} from './DomUtil';
/*
* @namespace DomEvent
* Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally.
*/
// Inspired by John Resig, Dean Edwards and YUI addEvent implementations.
// @function on(el: HTMLElement, types: String, fn: Function, context?: Object): this
// Adds a listener function (`fn`) to a particular DOM event type of the
// element `el`. You can optionally specify the context of the listener
// (object the `this` keyword will point to). You can also pass several
// space-separated types (e.g. `'click dblclick'`).
// @alternative
// @function on(el: HTMLElement, eventMap: Object, context?: Object): this
// Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
export function on(obj, types, fn, context) {
if (types && typeof types === 'object') {
for (var type in types) {
addOne(obj, type, types[type], fn);
}
} else {
types = Util.splitWords(types);
for (var i = 0, len = types.length; i < len; i++) {
addOne(obj, types[i], fn, context);
}
}
return this;
}
var eventsKey = '_leaflet_events';
// @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this
// Removes a previously added listener function.
// Note that if you passed a custom context to on, you must pass the same
// context to `off` in order to remove the listener.
// @alternative
// @function off(el: HTMLElement, eventMap: Object, context?: Object): this
// Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
// @alternative
// @function off(el: HTMLElement, types: String): this
// Removes all previously added listeners of given types.
// @alternative
// @function off(el: HTMLElement): this
// Removes all previously added listeners from given HTMLElement
export function off(obj, types, fn, context) {
if (arguments.length === 1) {
batchRemove(obj);
delete obj[eventsKey];
} else if (types && typeof types === 'object') {
for (var type in types) {
removeOne(obj, type, types[type], fn);
}
} else {
types = Util.splitWords(types);
if (arguments.length === 2) {
batchRemove(obj, function (type) {
return Util.indexOf(types, type) !== -1;
});
} else {
for (var i = 0, len = types.length; i < len; i++) {
removeOne(obj, types[i], fn, context);
}
}
}
return this;
}
function batchRemove(obj, filterFn) {
for (var id in obj[eventsKey]) {
var type = id.split(/\d/)[0];
if (!filterFn || filterFn(type)) {
removeOne(obj, type, null, null, id);
}
}
}
var mouseSubst = {
mouseenter: 'mouseover',
mouseleave: 'mouseout',
wheel: !('onwheel' in window) && 'mousewheel'
};
function addOne(obj, type, fn, context) {
var id = type + Util.stamp(fn) + (context ? '_' + Util.stamp(context) : '');
if (obj[eventsKey] && obj[eventsKey][id]) { return this; }
var handler = function (e) {
return fn.call(context || obj, e || window.event);
};
var originalHandler = handler;
if (!Browser.touchNative && Browser.pointer && type.indexOf('touch') === 0) {
// Needs DomEvent.Pointer.js
handler = addPointerListener(obj, type, handler);
} else if (Browser.touch && (type === 'dblclick')) {
handler = addDoubleTapListener(obj, handler);
} else if ('addEventListener' in obj) {
if (type === 'touchstart' || type === 'touchmove' || type === 'wheel' || type === 'mousewheel') {
obj.addEventListener(mouseSubst[type] || type, handler, Browser.passiveEvents ? {passive: false} : false);
} else if (type === 'mouseenter' || type === 'mouseleave') {
handler = function (e) {
e = e || window.event;
if (isExternalTarget(obj, e)) {
originalHandler(e);
}
};
obj.addEventListener(mouseSubst[type], handler, false);
} else {
obj.addEventListener(type, originalHandler, false);
}
} else {
obj.attachEvent('on' + type, handler);
}
obj[eventsKey] = obj[eventsKey] || {};
obj[eventsKey][id] = handler;
}
function removeOne(obj, type, fn, context, id) {
id = id || type + Util.stamp(fn) + (context ? '_' + Util.stamp(context) : '');
var handler = obj[eventsKey] && obj[eventsKey][id];
if (!handler) { return this; }
if (!Browser.touchNative && Browser.pointer && type.indexOf('touch') === 0) {
removePointerListener(obj, type, handler);
} else if (Browser.touch && (type === 'dblclick')) {
removeDoubleTapListener(obj, handler);
} else if ('removeEventListener' in obj) {
obj.removeEventListener(mouseSubst[type] || type, handler, false);
} else {
obj.detachEvent('on' + type, handler);
}
obj[eventsKey][id] = null;
}
// @function stopPropagation(ev: DOMEvent): this
// Stop the given event from propagation to parent elements. Used inside the listener functions:
// ```js
// L.DomEvent.on(div, 'click', function (ev) {
// L.DomEvent.stopPropagation(ev);
// });
// ```
export function stopPropagation(e) {
if (e.stopPropagation) {
e.stopPropagation();
} else if (e.originalEvent) { // In case of Leaflet event.
e.originalEvent._stopped = true;
} else {
e.cancelBubble = true;
}
return this;
}
// @function disableScrollPropagation(el: HTMLElement): this
// Adds `stopPropagation` to the element's `'wheel'` events (plus browser variants).
export function disableScrollPropagation(el) {
addOne(el, 'wheel', stopPropagation);
return this;
}
// @function disableClickPropagation(el: HTMLElement): this
// Adds `stopPropagation` to the element's `'click'`, `'dblclick'`, `'contextmenu'`,
// `'mousedown'` and `'touchstart'` events (plus browser variants).
export function disableClickPropagation(el) {
on(el, 'mousedown touchstart dblclick contextmenu', stopPropagation);
el['_leaflet_disable_click'] = true;
return this;
}
// @function preventDefault(ev: DOMEvent): this
// Prevents the default action of the DOM Event `ev` from happening (such as
// following a link in the href of the a element, or doing a POST request
// with page reload when a `<form>` is submitted).
// Use it inside listener functions.
export function preventDefault(e) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
return this;
}
// @function stop(ev: DOMEvent): this
// Does `stopPropagation` and `preventDefault` at the same time.
export function stop(e) {
preventDefault(e);
stopPropagation(e);
return this;
}
// @function getPropagationPath(ev: DOMEvent): Array
// Compatibility polyfill for [`Event.composedPath()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath).
// Returns an array containing the `HTMLElement`s that the given DOM event
// should propagate to (if not stopped).
export function getPropagationPath(ev) {
if (ev.composedPath) {
return ev.composedPath();
}
var path = [];
var el = ev.target;
while (el) {
path.push(el);
el = el.parentNode;
}
return path;
}
// @function getMousePosition(ev: DOMEvent, container?: HTMLElement): Point
// Gets normalized mouse position from a DOM event relative to the
// `container` (border excluded) or to the whole page if not specified.
export function getMousePosition(e, container) {
if (!container) {
return new Point(e.clientX, e.clientY);
}
var scale = getScale(container),
offset = scale.boundingClientRect; // left and top values are in page scale (like the event clientX/Y)
return new Point(
// offset.left/top values are in page scale (like clientX/Y),
// whereas clientLeft/Top (border width) values are the original values (before CSS scale applies).
(e.clientX - offset.left) / scale.x - container.clientLeft,
(e.clientY - offset.top) / scale.y - container.clientTop
);
}
// except , Safari and
// We need double the scroll pixels (see #7403 and #4538) for all Browsers
// except OSX (Mac) -> 3x, Chrome running on Linux 1x
var wheelPxFactor =
(Browser.linux && Browser.chrome) ? window.devicePixelRatio :
Browser.mac ? window.devicePixelRatio * 3 :
window.devicePixelRatio > 0 ? 2 * window.devicePixelRatio : 1;
// @function getWheelDelta(ev: DOMEvent): Number
// Gets normalized wheel delta from a wheel DOM event, in vertical
// pixels scrolled (negative if scrolling down).
// Events from pointing devices without precise scrolling are mapped to
// a best guess of 60 pixels.
export function getWheelDelta(e) {
return (Browser.edge) ? e.wheelDeltaY / 2 : // Don't trust window-geometry-based delta
(e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor : // Pixels
(e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 : // Lines
(e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 : // Pages
(e.deltaX || e.deltaZ) ? 0 : // Skip horizontal/depth wheel events
e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : // Legacy IE pixels
(e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 : // Legacy Moz lines
e.detail ? e.detail / -32765 * 60 : // Legacy Moz pages
0;
}
// check if element really left/entered the event target (for mouseenter/mouseleave)
export function isExternalTarget(el, e) {
var related = e.relatedTarget;
if (!related) { return true; }
try {
while (related && (related !== el)) {
related = related.parentNode;
}
} catch (err) {
return false;
}
return (related !== el);
}
// @function addListener(…): this
// Alias to [`L.DomEvent.on`](#domevent-on)
export {on as addListener};
// @function removeListener(…): this
// Alias to [`L.DomEvent.off`](#domevent-off)
export {off as removeListener};

349
pwa/node_modules/leaflet/src/dom/DomUtil.js generated vendored Normal file
View file

@ -0,0 +1,349 @@
import * as DomEvent from './DomEvent';
import * as Util from '../core/Util';
import {Point} from '../geometry/Point';
import Browser from '../core/Browser';
/*
* @namespace DomUtil
*
* Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)
* tree, used by Leaflet internally.
*
* Most functions expecting or returning a `HTMLElement` also work for
* SVG elements. The only difference is that classes refer to CSS classes
* in HTML and SVG classes in SVG.
*/
// @property TRANSFORM: String
// Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit).
export var TRANSFORM = testProp(
['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
// webkitTransition comes first because some browser versions that drop vendor prefix don't do
// the same for the transitionend event, in particular the Android 4.1 stock browser
// @property TRANSITION: String
// Vendor-prefixed transition style name.
export var TRANSITION = testProp(
['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);
// @property TRANSITION_END: String
// Vendor-prefixed transitionend event name.
export var TRANSITION_END =
TRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend';
// @function get(id: String|HTMLElement): HTMLElement
// Returns an element given its DOM id, or returns the element itself
// if it was passed directly.
export function get(id) {
return typeof id === 'string' ? document.getElementById(id) : id;
}
// @function getStyle(el: HTMLElement, styleAttrib: String): String
// Returns the value for a certain style attribute on an element,
// including computed values or values set through CSS.
export function getStyle(el, style) {
var value = el.style[style] || (el.currentStyle && el.currentStyle[style]);
if ((!value || value === 'auto') && document.defaultView) {
var css = document.defaultView.getComputedStyle(el, null);
value = css ? css[style] : null;
}
return value === 'auto' ? null : value;
}
// @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement
// Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element.
export function create(tagName, className, container) {
var el = document.createElement(tagName);
el.className = className || '';
if (container) {
container.appendChild(el);
}
return el;
}
// @function remove(el: HTMLElement)
// Removes `el` from its parent element
export function remove(el) {
var parent = el.parentNode;
if (parent) {
parent.removeChild(el);
}
}
// @function empty(el: HTMLElement)
// Removes all of `el`'s children elements from `el`
export function empty(el) {
while (el.firstChild) {
el.removeChild(el.firstChild);
}
}
// @function toFront(el: HTMLElement)
// Makes `el` the last child of its parent, so it renders in front of the other children.
export function toFront(el) {
var parent = el.parentNode;
if (parent && parent.lastChild !== el) {
parent.appendChild(el);
}
}
// @function toBack(el: HTMLElement)
// Makes `el` the first child of its parent, so it renders behind the other children.
export function toBack(el) {
var parent = el.parentNode;
if (parent && parent.firstChild !== el) {
parent.insertBefore(el, parent.firstChild);
}
}
// @function hasClass(el: HTMLElement, name: String): Boolean
// Returns `true` if the element's class attribute contains `name`.
export function hasClass(el, name) {
if (el.classList !== undefined) {
return el.classList.contains(name);
}
var className = getClass(el);
return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className);
}
// @function addClass(el: HTMLElement, name: String)
// Adds `name` to the element's class attribute.
export function addClass(el, name) {
if (el.classList !== undefined) {
var classes = Util.splitWords(name);
for (var i = 0, len = classes.length; i < len; i++) {
el.classList.add(classes[i]);
}
} else if (!hasClass(el, name)) {
var className = getClass(el);
setClass(el, (className ? className + ' ' : '') + name);
}
}
// @function removeClass(el: HTMLElement, name: String)
// Removes `name` from the element's class attribute.
export function removeClass(el, name) {
if (el.classList !== undefined) {
el.classList.remove(name);
} else {
setClass(el, Util.trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' ')));
}
}
// @function setClass(el: HTMLElement, name: String)
// Sets the element's class.
export function setClass(el, name) {
if (el.className.baseVal === undefined) {
el.className = name;
} else {
// in case of SVG element
el.className.baseVal = name;
}
}
// @function getClass(el: HTMLElement): String
// Returns the element's class.
export function getClass(el) {
// Check if the element is an SVGElementInstance and use the correspondingElement instead
// (Required for linked SVG elements in IE11.)
if (el.correspondingElement) {
el = el.correspondingElement;
}
return el.className.baseVal === undefined ? el.className : el.className.baseVal;
}
// @function setOpacity(el: HTMLElement, opacity: Number)
// Set the opacity of an element (including old IE support).
// `opacity` must be a number from `0` to `1`.
export function setOpacity(el, value) {
if ('opacity' in el.style) {
el.style.opacity = value;
} else if ('filter' in el.style) {
_setOpacityIE(el, value);
}
}
function _setOpacityIE(el, value) {
var filter = false,
filterName = 'DXImageTransform.Microsoft.Alpha';
// filters collection throws an error if we try to retrieve a filter that doesn't exist
try {
filter = el.filters.item(filterName);
} catch (e) {
// don't set opacity to 1 if we haven't already set an opacity,
// it isn't needed and breaks transparent pngs.
if (value === 1) { return; }
}
value = Math.round(value * 100);
if (filter) {
filter.Enabled = (value !== 100);
filter.Opacity = value;
} else {
el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')';
}
}
// @function testProp(props: String[]): String|false
// Goes through the array of style names and returns the first name
// that is a valid style name for an element. If no such name is found,
// it returns false. Useful for vendor-prefixed styles like `transform`.
export function testProp(props) {
var style = document.documentElement.style;
for (var i = 0; i < props.length; i++) {
if (props[i] in style) {
return props[i];
}
}
return false;
}
// @function setTransform(el: HTMLElement, offset: Point, scale?: Number)
// Resets the 3D CSS transform of `el` so it is translated by `offset` pixels
// and optionally scaled by `scale`. Does not have an effect if the
// browser doesn't support 3D CSS transforms.
export function setTransform(el, offset, scale) {
var pos = offset || new Point(0, 0);
el.style[TRANSFORM] =
(Browser.ie3d ?
'translate(' + pos.x + 'px,' + pos.y + 'px)' :
'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') +
(scale ? ' scale(' + scale + ')' : '');
}
// @function setPosition(el: HTMLElement, position: Point)
// Sets the position of `el` to coordinates specified by `position`,
// using CSS translate or top/left positioning depending on the browser
// (used by Leaflet internally to position its layers).
export function setPosition(el, point) {
/*eslint-disable */
el._leaflet_pos = point;
/* eslint-enable */
if (Browser.any3d) {
setTransform(el, point);
} else {
el.style.left = point.x + 'px';
el.style.top = point.y + 'px';
}
}
// @function getPosition(el: HTMLElement): Point
// Returns the coordinates of an element previously positioned with setPosition.
export function getPosition(el) {
// this method is only used for elements previously positioned using setPosition,
// so it's safe to cache the position for performance
return el._leaflet_pos || new Point(0, 0);
}
// @function disableTextSelection()
// Prevents the user from generating `selectstart` DOM events, usually generated
// when the user drags the mouse through a page with text. Used internally
// by Leaflet to override the behaviour of any click-and-drag interaction on
// the map. Affects drag interactions on the whole document.
// @function enableTextSelection()
// Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection).
export var disableTextSelection;
export var enableTextSelection;
var _userSelect;
if ('onselectstart' in document) {
disableTextSelection = function () {
DomEvent.on(window, 'selectstart', DomEvent.preventDefault);
};
enableTextSelection = function () {
DomEvent.off(window, 'selectstart', DomEvent.preventDefault);
};
} else {
var userSelectProperty = testProp(
['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);
disableTextSelection = function () {
if (userSelectProperty) {
var style = document.documentElement.style;
_userSelect = style[userSelectProperty];
style[userSelectProperty] = 'none';
}
};
enableTextSelection = function () {
if (userSelectProperty) {
document.documentElement.style[userSelectProperty] = _userSelect;
_userSelect = undefined;
}
};
}
// @function disableImageDrag()
// As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but
// for `dragstart` DOM events, usually generated when the user drags an image.
export function disableImageDrag() {
DomEvent.on(window, 'dragstart', DomEvent.preventDefault);
}
// @function enableImageDrag()
// Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection).
export function enableImageDrag() {
DomEvent.off(window, 'dragstart', DomEvent.preventDefault);
}
var _outlineElement, _outlineStyle;
// @function preventOutline(el: HTMLElement)
// Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline)
// of the element `el` invisible. Used internally by Leaflet to prevent
// focusable elements from displaying an outline when the user performs a
// drag interaction on them.
export function preventOutline(element) {
while (element.tabIndex === -1) {
element = element.parentNode;
}
if (!element.style) { return; }
restoreOutline();
_outlineElement = element;
_outlineStyle = element.style.outlineStyle;
element.style.outlineStyle = 'none';
DomEvent.on(window, 'keydown', restoreOutline);
}
// @function restoreOutline()
// Cancels the effects of a previous [`L.DomUtil.preventOutline`]().
export function restoreOutline() {
if (!_outlineElement) { return; }
_outlineElement.style.outlineStyle = _outlineStyle;
_outlineElement = undefined;
_outlineStyle = undefined;
DomEvent.off(window, 'keydown', restoreOutline);
}
// @function getSizedParentNode(el: HTMLElement): HTMLElement
// Finds the closest parent node which size (width and height) is not null.
export function getSizedParentNode(element) {
do {
element = element.parentNode;
} while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body);
return element;
}
// @function getScale(el: HTMLElement): Object
// Computes the CSS scale currently applied on the element.
// Returns an object with `x` and `y` members as horizontal and vertical scales respectively,
// and `boundingClientRect` as the result of [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect).
export function getScale(element) {
var rect = element.getBoundingClientRect(); // Read-only in old browsers.
return {
x: rect.width / element.offsetWidth || 1,
y: rect.height / element.offsetHeight || 1,
boundingClientRect: rect
};
}

220
pwa/node_modules/leaflet/src/dom/Draggable.js generated vendored Normal file
View file

@ -0,0 +1,220 @@
import {Evented} from '../core/Events';
import Browser from '../core/Browser';
import * as DomEvent from './DomEvent';
import * as DomUtil from './DomUtil';
import * as Util from '../core/Util';
import {Point} from '../geometry/Point';
/*
* @class Draggable
* @aka L.Draggable
* @inherits Evented
*
* A class for making DOM elements draggable (including touch support).
* Used internally for map and marker dragging. Only works for elements
* that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition).
*
* @example
* ```js
* var draggable = new L.Draggable(elementToDrag);
* draggable.enable();
* ```
*/
var START = Browser.touch ? 'touchstart mousedown' : 'mousedown';
export var Draggable = Evented.extend({
options: {
// @section
// @aka Draggable options
// @option clickTolerance: Number = 3
// The max number of pixels a user can shift the mouse pointer during a click
// for it to be considered a valid click (as opposed to a mouse drag).
clickTolerance: 3
},
// @constructor L.Draggable(el: HTMLElement, dragHandle?: HTMLElement, preventOutline?: Boolean, options?: Draggable options)
// Creates a `Draggable` object for moving `el` when you start dragging the `dragHandle` element (equals `el` itself by default).
initialize: function (element, dragStartTarget, preventOutline, options) {
Util.setOptions(this, options);
this._element = element;
this._dragStartTarget = dragStartTarget || element;
this._preventOutline = preventOutline;
},
// @method enable()
// Enables the dragging ability
enable: function () {
if (this._enabled) { return; }
DomEvent.on(this._dragStartTarget, START, this._onDown, this);
this._enabled = true;
},
// @method disable()
// Disables the dragging ability
disable: function () {
if (!this._enabled) { return; }
// If we're currently dragging this draggable,
// disabling it counts as first ending the drag.
if (Draggable._dragging === this) {
this.finishDrag(true);
}
DomEvent.off(this._dragStartTarget, START, this._onDown, this);
this._enabled = false;
this._moved = false;
},
_onDown: function (e) {
// Ignore the event if disabled; this happens in IE11
// under some circumstances, see #3666.
if (!this._enabled) { return; }
this._moved = false;
if (DomUtil.hasClass(this._element, 'leaflet-zoom-anim')) { return; }
if (e.touches && e.touches.length !== 1) {
// Finish dragging to avoid conflict with touchZoom
if (Draggable._dragging === this) {
this.finishDrag();
}
return;
}
if (Draggable._dragging || e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; }
Draggable._dragging = this; // Prevent dragging multiple objects at once.
if (this._preventOutline) {
DomUtil.preventOutline(this._element);
}
DomUtil.disableImageDrag();
DomUtil.disableTextSelection();
if (this._moving) { return; }
// @event down: Event
// Fired when a drag is about to start.
this.fire('down');
var first = e.touches ? e.touches[0] : e,
sizedParent = DomUtil.getSizedParentNode(this._element);
this._startPoint = new Point(first.clientX, first.clientY);
this._startPos = DomUtil.getPosition(this._element);
// Cache the scale, so that we can continuously compensate for it during drag (_onMove).
this._parentScale = DomUtil.getScale(sizedParent);
var mouseevent = e.type === 'mousedown';
DomEvent.on(document, mouseevent ? 'mousemove' : 'touchmove', this._onMove, this);
DomEvent.on(document, mouseevent ? 'mouseup' : 'touchend touchcancel', this._onUp, this);
},
_onMove: function (e) {
// Ignore the event if disabled; this happens in IE11
// under some circumstances, see #3666.
if (!this._enabled) { return; }
if (e.touches && e.touches.length > 1) {
this._moved = true;
return;
}
var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),
offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint);
if (!offset.x && !offset.y) { return; }
if (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) { return; }
// We assume that the parent container's position, border and scale do not change for the duration of the drag.
// Therefore there is no need to account for the position and border (they are eliminated by the subtraction)
// and we can use the cached value for the scale.
offset.x /= this._parentScale.x;
offset.y /= this._parentScale.y;
DomEvent.preventDefault(e);
if (!this._moved) {
// @event dragstart: Event
// Fired when a drag starts
this.fire('dragstart');
this._moved = true;
DomUtil.addClass(document.body, 'leaflet-dragging');
this._lastTarget = e.target || e.srcElement;
// IE and Edge do not give the <use> element, so fetch it
// if necessary
if (window.SVGElementInstance && this._lastTarget instanceof window.SVGElementInstance) {
this._lastTarget = this._lastTarget.correspondingUseElement;
}
DomUtil.addClass(this._lastTarget, 'leaflet-drag-target');
}
this._newPos = this._startPos.add(offset);
this._moving = true;
this._lastEvent = e;
this._updatePosition();
},
_updatePosition: function () {
var e = {originalEvent: this._lastEvent};
// @event predrag: Event
// Fired continuously during dragging *before* each corresponding
// update of the element's position.
this.fire('predrag', e);
DomUtil.setPosition(this._element, this._newPos);
// @event drag: Event
// Fired continuously during dragging.
this.fire('drag', e);
},
_onUp: function () {
// Ignore the event if disabled; this happens in IE11
// under some circumstances, see #3666.
if (!this._enabled) { return; }
this.finishDrag();
},
finishDrag: function (noInertia) {
DomUtil.removeClass(document.body, 'leaflet-dragging');
if (this._lastTarget) {
DomUtil.removeClass(this._lastTarget, 'leaflet-drag-target');
this._lastTarget = null;
}
DomEvent.off(document, 'mousemove touchmove', this._onMove, this);
DomEvent.off(document, 'mouseup touchend touchcancel', this._onUp, this);
DomUtil.enableImageDrag();
DomUtil.enableTextSelection();
var fireDragend = this._moved && this._moving;
this._moving = false;
Draggable._dragging = false;
if (fireDragend) {
// @event dragend: DragEndEvent
// Fired when the drag ends.
this.fire('dragend', {
noInertia: noInertia,
distance: this._newPos.distanceTo(this._startPos)
});
}
}
});

113
pwa/node_modules/leaflet/src/dom/PosAnimation.js generated vendored Normal file
View file

@ -0,0 +1,113 @@
import * as Util from '../core/Util';
import {Evented} from '../core/Events';
import * as DomUtil from '../dom/DomUtil';
/*
* @class PosAnimation
* @aka L.PosAnimation
* @inherits Evented
* Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.
*
* @example
* ```js
* var myPositionMarker = L.marker([48.864716, 2.294694]).addTo(map);
*
* myPositionMarker.on("click", function() {
* var pos = map.latLngToLayerPoint(myPositionMarker.getLatLng());
* pos.y -= 25;
* var fx = new L.PosAnimation();
*
* fx.once('end',function() {
* pos.y += 25;
* fx.run(myPositionMarker._icon, pos, 0.8);
* });
*
* fx.run(myPositionMarker._icon, pos, 0.3);
* });
*
* ```
*
* @constructor L.PosAnimation()
* Creates a `PosAnimation` object.
*
*/
export var PosAnimation = Evented.extend({
// @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number)
// Run an animation of a given element to a new position, optionally setting
// duration in seconds (`0.25` by default) and easing linearity factor (3rd
// argument of the [cubic bezier curve](https://cubic-bezier.com/#0,0,.5,1),
// `0.5` by default).
run: function (el, newPos, duration, easeLinearity) {
this.stop();
this._el = el;
this._inProgress = true;
this._duration = duration || 0.25;
this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);
this._startPos = DomUtil.getPosition(el);
this._offset = newPos.subtract(this._startPos);
this._startTime = +new Date();
// @event start: Event
// Fired when the animation starts
this.fire('start');
this._animate();
},
// @method stop()
// Stops the animation (if currently running).
stop: function () {
if (!this._inProgress) { return; }
this._step(true);
this._complete();
},
_animate: function () {
// animation loop
this._animId = Util.requestAnimFrame(this._animate, this);
this._step();
},
_step: function (round) {
var elapsed = (+new Date()) - this._startTime,
duration = this._duration * 1000;
if (elapsed < duration) {
this._runFrame(this._easeOut(elapsed / duration), round);
} else {
this._runFrame(1);
this._complete();
}
},
_runFrame: function (progress, round) {
var pos = this._startPos.add(this._offset.multiplyBy(progress));
if (round) {
pos._round();
}
DomUtil.setPosition(this._el, pos);
// @event step: Event
// Fired continuously during the animation.
this.fire('step');
},
_complete: function () {
Util.cancelAnimFrame(this._animId);
this._inProgress = false;
// @event end: Event
// Fired when the animation ends.
this.fire('end');
},
_easeOut: function (t) {
return 1 - Math.pow(1 - t, this._easeOutPower);
}
});

9
pwa/node_modules/leaflet/src/dom/index.js generated vendored Normal file
View file

@ -0,0 +1,9 @@
export {PosAnimation} from './PosAnimation';
import * as DomEvent from './DomEvent';
export {DomEvent};
import * as DomUtil from './DomUtil';
export {DomUtil};
export {Draggable} from './Draggable';