`, so it can be styled via any CSS solution you prefer.\n * @see https://floating-ui.com/docs/FloatingOverlay\n */\nconst FloatingOverlay = /*#__PURE__*/React.forwardRef(function FloatingOverlay(props, ref) {\n const {\n lockScroll = false,\n ...rest\n } = props;\n index(() => {\n if (!lockScroll) return;\n lockCount++;\n if (lockCount === 1) {\n cleanup = enableScrollLock();\n }\n return () => {\n lockCount--;\n if (lockCount === 0) {\n cleanup();\n }\n };\n }, [lockScroll]);\n return /*#__PURE__*/React.createElement(\"div\", _extends({\n ref: ref\n }, rest, {\n style: {\n position: 'fixed',\n overflow: 'auto',\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n ...rest.style\n }\n }));\n});\n\nfunction isButtonTarget(event) {\n return isHTMLElement(event.target) && event.target.tagName === 'BUTTON';\n}\nfunction isSpaceIgnored(element) {\n return isTypeableElement(element);\n}\n/**\n * Opens or closes the floating element when clicking the reference element.\n * @see https://floating-ui.com/docs/useClick\n */\nfunction useClick(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n onOpenChange,\n dataRef,\n elements: {\n domReference\n }\n } = context;\n const {\n enabled = true,\n event: eventOption = 'click',\n toggle = true,\n ignoreMouse = false,\n keyboardHandlers = true,\n stickIfOpen = true\n } = props;\n const pointerTypeRef = React.useRef();\n const didKeyDownRef = React.useRef(false);\n const reference = React.useMemo(() => ({\n onPointerDown(event) {\n pointerTypeRef.current = event.pointerType;\n },\n onMouseDown(event) {\n const pointerType = pointerTypeRef.current;\n\n // Ignore all buttons except for the \"main\" button.\n // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button\n if (event.button !== 0) return;\n if (eventOption === 'click') return;\n if (isMouseLikePointerType(pointerType, true) && ignoreMouse) return;\n if (open && toggle && (dataRef.current.openEvent && stickIfOpen ? dataRef.current.openEvent.type === 'mousedown' : true)) {\n onOpenChange(false, event.nativeEvent, 'click');\n } else {\n // Prevent stealing focus from the floating element\n event.preventDefault();\n onOpenChange(true, event.nativeEvent, 'click');\n }\n },\n onClick(event) {\n const pointerType = pointerTypeRef.current;\n if (eventOption === 'mousedown' && pointerTypeRef.current) {\n pointerTypeRef.current = undefined;\n return;\n }\n if (isMouseLikePointerType(pointerType, true) && ignoreMouse) return;\n if (open && toggle && (dataRef.current.openEvent && stickIfOpen ? dataRef.current.openEvent.type === 'click' : true)) {\n onOpenChange(false, event.nativeEvent, 'click');\n } else {\n onOpenChange(true, event.nativeEvent, 'click');\n }\n },\n onKeyDown(event) {\n pointerTypeRef.current = undefined;\n if (event.defaultPrevented || !keyboardHandlers || isButtonTarget(event)) {\n return;\n }\n if (event.key === ' ' && !isSpaceIgnored(domReference)) {\n // Prevent scrolling\n event.preventDefault();\n didKeyDownRef.current = true;\n }\n if (event.key === 'Enter') {\n if (open && toggle) {\n onOpenChange(false, event.nativeEvent, 'click');\n } else {\n onOpenChange(true, event.nativeEvent, 'click');\n }\n }\n },\n onKeyUp(event) {\n if (event.defaultPrevented || !keyboardHandlers || isButtonTarget(event) || isSpaceIgnored(domReference)) {\n return;\n }\n if (event.key === ' ' && didKeyDownRef.current) {\n didKeyDownRef.current = false;\n if (open && toggle) {\n onOpenChange(false, event.nativeEvent, 'click');\n } else {\n onOpenChange(true, event.nativeEvent, 'click');\n }\n }\n }\n }), [dataRef, domReference, eventOption, ignoreMouse, keyboardHandlers, onOpenChange, open, stickIfOpen, toggle]);\n return React.useMemo(() => enabled ? {\n reference\n } : {}, [enabled, reference]);\n}\n\nfunction createVirtualElement(domElement, data) {\n let offsetX = null;\n let offsetY = null;\n let isAutoUpdateEvent = false;\n return {\n contextElement: domElement || undefined,\n getBoundingClientRect() {\n var _data$dataRef$current;\n const domRect = (domElement == null ? void 0 : domElement.getBoundingClientRect()) || {\n width: 0,\n height: 0,\n x: 0,\n y: 0\n };\n const isXAxis = data.axis === 'x' || data.axis === 'both';\n const isYAxis = data.axis === 'y' || data.axis === 'both';\n const canTrackCursorOnAutoUpdate = ['mouseenter', 'mousemove'].includes(((_data$dataRef$current = data.dataRef.current.openEvent) == null ? void 0 : _data$dataRef$current.type) || '') && data.pointerType !== 'touch';\n let width = domRect.width;\n let height = domRect.height;\n let x = domRect.x;\n let y = domRect.y;\n if (offsetX == null && data.x && isXAxis) {\n offsetX = domRect.x - data.x;\n }\n if (offsetY == null && data.y && isYAxis) {\n offsetY = domRect.y - data.y;\n }\n x -= offsetX || 0;\n y -= offsetY || 0;\n width = 0;\n height = 0;\n if (!isAutoUpdateEvent || canTrackCursorOnAutoUpdate) {\n width = data.axis === 'y' ? domRect.width : 0;\n height = data.axis === 'x' ? domRect.height : 0;\n x = isXAxis && data.x != null ? data.x : x;\n y = isYAxis && data.y != null ? data.y : y;\n } else if (isAutoUpdateEvent && !canTrackCursorOnAutoUpdate) {\n height = data.axis === 'x' ? domRect.height : height;\n width = data.axis === 'y' ? domRect.width : width;\n }\n isAutoUpdateEvent = true;\n return {\n width,\n height,\n x,\n y,\n top: y,\n right: x + width,\n bottom: y + height,\n left: x\n };\n }\n };\n}\nfunction isMouseBasedEvent(event) {\n return event != null && event.clientX != null;\n}\n/**\n * Positions the floating element relative to a client point (in the viewport),\n * such as the mouse position. By default, it follows the mouse cursor.\n * @see https://floating-ui.com/docs/useClientPoint\n */\nfunction useClientPoint(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n dataRef,\n elements: {\n floating,\n domReference\n },\n refs\n } = context;\n const {\n enabled = true,\n axis = 'both',\n x = null,\n y = null\n } = props;\n const initialRef = React.useRef(false);\n const cleanupListenerRef = React.useRef(null);\n const [pointerType, setPointerType] = React.useState();\n const [reactive, setReactive] = React.useState([]);\n const setReference = useEffectEvent((x, y) => {\n if (initialRef.current) return;\n\n // Prevent setting if the open event was not a mouse-like one\n // (e.g. focus to open, then hover over the reference element).\n // Only apply if the event exists.\n if (dataRef.current.openEvent && !isMouseBasedEvent(dataRef.current.openEvent)) {\n return;\n }\n refs.setPositionReference(createVirtualElement(domReference, {\n x,\n y,\n axis,\n dataRef,\n pointerType\n }));\n });\n const handleReferenceEnterOrMove = useEffectEvent(event => {\n if (x != null || y != null) return;\n if (!open) {\n setReference(event.clientX, event.clientY);\n } else if (!cleanupListenerRef.current) {\n // If there's no cleanup, there's no listener, but we want to ensure\n // we add the listener if the cursor landed on the floating element and\n // then back on the reference (i.e. it's interactive).\n setReactive([]);\n }\n });\n\n // If the pointer is a mouse-like pointer, we want to continue following the\n // mouse even if the floating element is transitioning out. On touch\n // devices, this is undesirable because the floating element will move to\n // the dismissal touch point.\n const openCheck = isMouseLikePointerType(pointerType) ? floating : open;\n const addListener = React.useCallback(() => {\n // Explicitly specified `x`/`y` coordinates shouldn't add a listener.\n if (!openCheck || !enabled || x != null || y != null) return;\n const win = getWindow(floating);\n function handleMouseMove(event) {\n const target = getTarget(event);\n if (!contains(floating, target)) {\n setReference(event.clientX, event.clientY);\n } else {\n win.removeEventListener('mousemove', handleMouseMove);\n cleanupListenerRef.current = null;\n }\n }\n if (!dataRef.current.openEvent || isMouseBasedEvent(dataRef.current.openEvent)) {\n win.addEventListener('mousemove', handleMouseMove);\n const cleanup = () => {\n win.removeEventListener('mousemove', handleMouseMove);\n cleanupListenerRef.current = null;\n };\n cleanupListenerRef.current = cleanup;\n return cleanup;\n }\n refs.setPositionReference(domReference);\n }, [openCheck, enabled, x, y, floating, dataRef, refs, domReference, setReference]);\n React.useEffect(() => {\n return addListener();\n }, [addListener, reactive]);\n React.useEffect(() => {\n if (enabled && !floating) {\n initialRef.current = false;\n }\n }, [enabled, floating]);\n React.useEffect(() => {\n if (!enabled && open) {\n initialRef.current = true;\n }\n }, [enabled, open]);\n index(() => {\n if (enabled && (x != null || y != null)) {\n initialRef.current = false;\n setReference(x, y);\n }\n }, [enabled, x, y, setReference]);\n const reference = React.useMemo(() => {\n function setPointerTypeRef(_ref) {\n let {\n pointerType\n } = _ref;\n setPointerType(pointerType);\n }\n return {\n onPointerDown: setPointerTypeRef,\n onPointerEnter: setPointerTypeRef,\n onMouseMove: handleReferenceEnterOrMove,\n onMouseEnter: handleReferenceEnterOrMove\n };\n }, [handleReferenceEnterOrMove]);\n return React.useMemo(() => enabled ? {\n reference\n } : {}, [enabled, reference]);\n}\n\nconst bubbleHandlerKeys = {\n pointerdown: 'onPointerDown',\n mousedown: 'onMouseDown',\n click: 'onClick'\n};\nconst captureHandlerKeys = {\n pointerdown: 'onPointerDownCapture',\n mousedown: 'onMouseDownCapture',\n click: 'onClickCapture'\n};\nconst normalizeProp = normalizable => {\n var _normalizable$escapeK, _normalizable$outside;\n return {\n escapeKey: typeof normalizable === 'boolean' ? normalizable : (_normalizable$escapeK = normalizable == null ? void 0 : normalizable.escapeKey) != null ? _normalizable$escapeK : false,\n outsidePress: typeof normalizable === 'boolean' ? normalizable : (_normalizable$outside = normalizable == null ? void 0 : normalizable.outsidePress) != null ? _normalizable$outside : true\n };\n};\n/**\n * Closes the floating element when a dismissal is requested — by default, when\n * the user presses the `escape` key or outside of the floating element.\n * @see https://floating-ui.com/docs/useDismiss\n */\nfunction useDismiss(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n onOpenChange,\n elements,\n dataRef\n } = context;\n const {\n enabled = true,\n escapeKey = true,\n outsidePress: unstable_outsidePress = true,\n outsidePressEvent = 'pointerdown',\n referencePress = false,\n referencePressEvent = 'pointerdown',\n ancestorScroll = false,\n bubbles,\n capture\n } = props;\n const tree = useFloatingTree();\n const outsidePressFn = useEffectEvent(typeof unstable_outsidePress === 'function' ? unstable_outsidePress : () => false);\n const outsidePress = typeof unstable_outsidePress === 'function' ? outsidePressFn : unstable_outsidePress;\n const insideReactTreeRef = React.useRef(false);\n const endedOrStartedInsideRef = React.useRef(false);\n const {\n escapeKey: escapeKeyBubbles,\n outsidePress: outsidePressBubbles\n } = normalizeProp(bubbles);\n const {\n escapeKey: escapeKeyCapture,\n outsidePress: outsidePressCapture\n } = normalizeProp(capture);\n const isComposingRef = React.useRef(false);\n const closeOnEscapeKeyDown = useEffectEvent(event => {\n var _dataRef$current$floa;\n if (!open || !enabled || !escapeKey || event.key !== 'Escape') {\n return;\n }\n\n // Wait until IME is settled. Pressing `Escape` while composing should\n // close the compose menu, but not the floating element.\n if (isComposingRef.current) {\n return;\n }\n const nodeId = (_dataRef$current$floa = dataRef.current.floatingContext) == null ? void 0 : _dataRef$current$floa.nodeId;\n const children = tree ? getChildren(tree.nodesRef.current, nodeId) : [];\n if (!escapeKeyBubbles) {\n event.stopPropagation();\n if (children.length > 0) {\n let shouldDismiss = true;\n children.forEach(child => {\n var _child$context;\n if ((_child$context = child.context) != null && _child$context.open && !child.context.dataRef.current.__escapeKeyBubbles) {\n shouldDismiss = false;\n return;\n }\n });\n if (!shouldDismiss) {\n return;\n }\n }\n }\n onOpenChange(false, isReactEvent(event) ? event.nativeEvent : event, 'escape-key');\n });\n const closeOnEscapeKeyDownCapture = useEffectEvent(event => {\n var _getTarget2;\n const callback = () => {\n var _getTarget;\n closeOnEscapeKeyDown(event);\n (_getTarget = getTarget(event)) == null || _getTarget.removeEventListener('keydown', callback);\n };\n (_getTarget2 = getTarget(event)) == null || _getTarget2.addEventListener('keydown', callback);\n });\n const closeOnPressOutside = useEffectEvent(event => {\n var _dataRef$current$floa2;\n // Given developers can stop the propagation of the synthetic event,\n // we can only be confident with a positive value.\n const insideReactTree = insideReactTreeRef.current;\n insideReactTreeRef.current = false;\n\n // When click outside is lazy (`click` event), handle dragging.\n // Don't close if:\n // - The click started inside the floating element.\n // - The click ended inside the floating element.\n const endedOrStartedInside = endedOrStartedInsideRef.current;\n endedOrStartedInsideRef.current = false;\n if (outsidePressEvent === 'click' && endedOrStartedInside) {\n return;\n }\n if (insideReactTree) {\n return;\n }\n if (typeof outsidePress === 'function' && !outsidePress(event)) {\n return;\n }\n const target = getTarget(event);\n const inertSelector = \"[\" + createAttribute('inert') + \"]\";\n const markers = getDocument(elements.floating).querySelectorAll(inertSelector);\n let targetRootAncestor = isElement(target) ? target : null;\n while (targetRootAncestor && !isLastTraversableNode(targetRootAncestor)) {\n const nextParent = getParentNode(targetRootAncestor);\n if (isLastTraversableNode(nextParent) || !isElement(nextParent)) {\n break;\n }\n targetRootAncestor = nextParent;\n }\n\n // Check if the click occurred on a third-party element injected after the\n // floating element rendered.\n if (markers.length && isElement(target) && !isRootElement(target) &&\n // Clicked on a direct ancestor (e.g. FloatingOverlay).\n !contains(target, elements.floating) &&\n // If the target root element contains none of the markers, then the\n // element was injected after the floating element rendered.\n Array.from(markers).every(marker => !contains(targetRootAncestor, marker))) {\n return;\n }\n\n // Check if the click occurred on the scrollbar\n if (isHTMLElement(target) && floating) {\n // In Firefox, `target.scrollWidth > target.clientWidth` for inline\n // elements.\n const canScrollX = target.clientWidth > 0 && target.scrollWidth > target.clientWidth;\n const canScrollY = target.clientHeight > 0 && target.scrollHeight > target.clientHeight;\n let xCond = canScrollY && event.offsetX > target.clientWidth;\n\n // In some browsers it is possible to change the (or window)\n // scrollbar to the left side, but is very rare and is difficult to\n // check for. Plus, for modal dialogs with backdrops, it is more\n // important that the backdrop is checked but not so much the window.\n if (canScrollY) {\n const isRTL = getComputedStyle(target).direction === 'rtl';\n if (isRTL) {\n xCond = event.offsetX <= target.offsetWidth - target.clientWidth;\n }\n }\n if (xCond || canScrollX && event.offsetY > target.clientHeight) {\n return;\n }\n }\n const nodeId = (_dataRef$current$floa2 = dataRef.current.floatingContext) == null ? void 0 : _dataRef$current$floa2.nodeId;\n const targetIsInsideChildren = tree && getChildren(tree.nodesRef.current, nodeId).some(node => {\n var _node$context;\n return isEventTargetWithin(event, (_node$context = node.context) == null ? void 0 : _node$context.elements.floating);\n });\n if (isEventTargetWithin(event, elements.floating) || isEventTargetWithin(event, elements.domReference) || targetIsInsideChildren) {\n return;\n }\n const children = tree ? getChildren(tree.nodesRef.current, nodeId) : [];\n if (children.length > 0) {\n let shouldDismiss = true;\n children.forEach(child => {\n var _child$context2;\n if ((_child$context2 = child.context) != null && _child$context2.open && !child.context.dataRef.current.__outsidePressBubbles) {\n shouldDismiss = false;\n return;\n }\n });\n if (!shouldDismiss) {\n return;\n }\n }\n onOpenChange(false, event, 'outside-press');\n });\n const closeOnPressOutsideCapture = useEffectEvent(event => {\n var _getTarget4;\n const callback = () => {\n var _getTarget3;\n closeOnPressOutside(event);\n (_getTarget3 = getTarget(event)) == null || _getTarget3.removeEventListener(outsidePressEvent, callback);\n };\n (_getTarget4 = getTarget(event)) == null || _getTarget4.addEventListener(outsidePressEvent, callback);\n });\n React.useEffect(() => {\n if (!open || !enabled) {\n return;\n }\n dataRef.current.__escapeKeyBubbles = escapeKeyBubbles;\n dataRef.current.__outsidePressBubbles = outsidePressBubbles;\n let compositionTimeout = -1;\n function onScroll(event) {\n onOpenChange(false, event, 'ancestor-scroll');\n }\n function handleCompositionStart() {\n window.clearTimeout(compositionTimeout);\n isComposingRef.current = true;\n }\n function handleCompositionEnd() {\n // Safari fires `compositionend` before `keydown`, so we need to wait\n // until the next tick to set `isComposing` to `false`.\n // https://bugs.webkit.org/show_bug.cgi?id=165004\n compositionTimeout = window.setTimeout(() => {\n isComposingRef.current = false;\n },\n // 0ms or 1ms don't work in Safari. 5ms appears to consistently work.\n // Only apply to WebKit for the test to remain 0ms.\n isWebKit() ? 5 : 0);\n }\n const doc = getDocument(elements.floating);\n if (escapeKey) {\n doc.addEventListener('keydown', escapeKeyCapture ? closeOnEscapeKeyDownCapture : closeOnEscapeKeyDown, escapeKeyCapture);\n doc.addEventListener('compositionstart', handleCompositionStart);\n doc.addEventListener('compositionend', handleCompositionEnd);\n }\n outsidePress && doc.addEventListener(outsidePressEvent, outsidePressCapture ? closeOnPressOutsideCapture : closeOnPressOutside, outsidePressCapture);\n let ancestors = [];\n if (ancestorScroll) {\n if (isElement(elements.domReference)) {\n ancestors = getOverflowAncestors(elements.domReference);\n }\n if (isElement(elements.floating)) {\n ancestors = ancestors.concat(getOverflowAncestors(elements.floating));\n }\n if (!isElement(elements.reference) && elements.reference && elements.reference.contextElement) {\n ancestors = ancestors.concat(getOverflowAncestors(elements.reference.contextElement));\n }\n }\n\n // Ignore the visual viewport for scrolling dismissal (allow pinch-zoom)\n ancestors = ancestors.filter(ancestor => {\n var _doc$defaultView;\n return ancestor !== ((_doc$defaultView = doc.defaultView) == null ? void 0 : _doc$defaultView.visualViewport);\n });\n ancestors.forEach(ancestor => {\n ancestor.addEventListener('scroll', onScroll, {\n passive: true\n });\n });\n return () => {\n if (escapeKey) {\n doc.removeEventListener('keydown', escapeKeyCapture ? closeOnEscapeKeyDownCapture : closeOnEscapeKeyDown, escapeKeyCapture);\n doc.removeEventListener('compositionstart', handleCompositionStart);\n doc.removeEventListener('compositionend', handleCompositionEnd);\n }\n outsidePress && doc.removeEventListener(outsidePressEvent, outsidePressCapture ? closeOnPressOutsideCapture : closeOnPressOutside, outsidePressCapture);\n ancestors.forEach(ancestor => {\n ancestor.removeEventListener('scroll', onScroll);\n });\n window.clearTimeout(compositionTimeout);\n };\n }, [dataRef, elements, escapeKey, outsidePress, outsidePressEvent, open, onOpenChange, ancestorScroll, enabled, escapeKeyBubbles, outsidePressBubbles, closeOnEscapeKeyDown, escapeKeyCapture, closeOnEscapeKeyDownCapture, closeOnPressOutside, outsidePressCapture, closeOnPressOutsideCapture]);\n React.useEffect(() => {\n insideReactTreeRef.current = false;\n }, [outsidePress, outsidePressEvent]);\n const reference = React.useMemo(() => ({\n onKeyDown: closeOnEscapeKeyDown,\n [bubbleHandlerKeys[referencePressEvent]]: event => {\n if (referencePress) {\n onOpenChange(false, event.nativeEvent, 'reference-press');\n }\n }\n }), [closeOnEscapeKeyDown, onOpenChange, referencePress, referencePressEvent]);\n const floating = React.useMemo(() => ({\n onKeyDown: closeOnEscapeKeyDown,\n onMouseDown() {\n endedOrStartedInsideRef.current = true;\n },\n onMouseUp() {\n endedOrStartedInsideRef.current = true;\n },\n [captureHandlerKeys[outsidePressEvent]]: () => {\n insideReactTreeRef.current = true;\n }\n }), [closeOnEscapeKeyDown, outsidePressEvent]);\n return React.useMemo(() => enabled ? {\n reference,\n floating\n } : {}, [enabled, reference, floating]);\n}\n\nfunction useFloatingRootContext(options) {\n const {\n open = false,\n onOpenChange: onOpenChangeProp,\n elements: elementsProp\n } = options;\n const floatingId = useId();\n const dataRef = React.useRef({});\n const [events] = React.useState(() => createPubSub());\n const nested = useFloatingParentNodeId() != null;\n if (process.env.NODE_ENV !== \"production\") {\n const optionDomReference = elementsProp.reference;\n if (optionDomReference && !isElement(optionDomReference)) {\n error('Cannot pass a virtual element to the `elements.reference` option,', 'as it must be a real DOM element. Use `refs.setPositionReference()`', 'instead.');\n }\n }\n const [positionReference, setPositionReference] = React.useState(elementsProp.reference);\n const onOpenChange = useEffectEvent((open, event, reason) => {\n dataRef.current.openEvent = open ? event : undefined;\n events.emit('openchange', {\n open,\n event,\n reason,\n nested\n });\n onOpenChangeProp == null || onOpenChangeProp(open, event, reason);\n });\n const refs = React.useMemo(() => ({\n setPositionReference\n }), []);\n const elements = React.useMemo(() => ({\n reference: positionReference || elementsProp.reference || null,\n floating: elementsProp.floating || null,\n domReference: elementsProp.reference\n }), [positionReference, elementsProp.reference, elementsProp.floating]);\n return React.useMemo(() => ({\n dataRef,\n open,\n onOpenChange,\n elements,\n events,\n floatingId,\n refs\n }), [open, onOpenChange, elements, events, floatingId, refs]);\n}\n\n/**\n * Provides data to position a floating element and context to add interactions.\n * @see https://floating-ui.com/docs/useFloating\n */\nfunction useFloating(options) {\n if (options === void 0) {\n options = {};\n }\n const {\n nodeId\n } = options;\n const internalRootContext = useFloatingRootContext({\n ...options,\n elements: {\n reference: null,\n floating: null,\n ...options.elements\n }\n });\n const rootContext = options.rootContext || internalRootContext;\n const computedElements = rootContext.elements;\n const [_domReference, setDomReference] = React.useState(null);\n const [positionReference, _setPositionReference] = React.useState(null);\n const optionDomReference = computedElements == null ? void 0 : computedElements.domReference;\n const domReference = optionDomReference || _domReference;\n const domReferenceRef = React.useRef(null);\n const tree = useFloatingTree();\n index(() => {\n if (domReference) {\n domReferenceRef.current = domReference;\n }\n }, [domReference]);\n const position = useFloating$1({\n ...options,\n elements: {\n ...computedElements,\n ...(positionReference && {\n reference: positionReference\n })\n }\n });\n const setPositionReference = React.useCallback(node => {\n const computedPositionReference = isElement(node) ? {\n getBoundingClientRect: () => node.getBoundingClientRect(),\n contextElement: node\n } : node;\n // Store the positionReference in state if the DOM reference is specified externally via the\n // `elements.reference` option. This ensures that it won't be overridden on future renders.\n _setPositionReference(computedPositionReference);\n position.refs.setReference(computedPositionReference);\n }, [position.refs]);\n const setReference = React.useCallback(node => {\n if (isElement(node) || node === null) {\n domReferenceRef.current = node;\n setDomReference(node);\n }\n\n // Backwards-compatibility for passing a virtual element to `reference`\n // after it has set the DOM reference.\n if (isElement(position.refs.reference.current) || position.refs.reference.current === null ||\n // Don't allow setting virtual elements using the old technique back to\n // `null` to support `positionReference` + an unstable `reference`\n // callback ref.\n node !== null && !isElement(node)) {\n position.refs.setReference(node);\n }\n }, [position.refs]);\n const refs = React.useMemo(() => ({\n ...position.refs,\n setReference,\n setPositionReference,\n domReference: domReferenceRef\n }), [position.refs, setReference, setPositionReference]);\n const elements = React.useMemo(() => ({\n ...position.elements,\n domReference: domReference\n }), [position.elements, domReference]);\n const context = React.useMemo(() => ({\n ...position,\n ...rootContext,\n refs,\n elements,\n nodeId\n }), [position, refs, elements, nodeId, rootContext]);\n index(() => {\n rootContext.dataRef.current.floatingContext = context;\n const node = tree == null ? void 0 : tree.nodesRef.current.find(node => node.id === nodeId);\n if (node) {\n node.context = context;\n }\n });\n return React.useMemo(() => ({\n ...position,\n context,\n refs,\n elements\n }), [position, refs, elements, context]);\n}\n\n/**\n * Opens the floating element while the reference element has focus, like CSS\n * `:focus`.\n * @see https://floating-ui.com/docs/useFocus\n */\nfunction useFocus(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n onOpenChange,\n events,\n dataRef,\n elements\n } = context;\n const {\n enabled = true,\n visibleOnly = true\n } = props;\n const blockFocusRef = React.useRef(false);\n const timeoutRef = React.useRef();\n const keyboardModalityRef = React.useRef(true);\n React.useEffect(() => {\n if (!enabled) return;\n const win = getWindow(elements.domReference);\n\n // If the reference was focused and the user left the tab/window, and the\n // floating element was not open, the focus should be blocked when they\n // return to the tab/window.\n function onBlur() {\n if (!open && isHTMLElement(elements.domReference) && elements.domReference === activeElement(getDocument(elements.domReference))) {\n blockFocusRef.current = true;\n }\n }\n function onKeyDown() {\n keyboardModalityRef.current = true;\n }\n win.addEventListener('blur', onBlur);\n win.addEventListener('keydown', onKeyDown, true);\n return () => {\n win.removeEventListener('blur', onBlur);\n win.removeEventListener('keydown', onKeyDown, true);\n };\n }, [elements.domReference, open, enabled]);\n React.useEffect(() => {\n if (!enabled) return;\n function onOpenChange(_ref) {\n let {\n reason\n } = _ref;\n if (reason === 'reference-press' || reason === 'escape-key') {\n blockFocusRef.current = true;\n }\n }\n events.on('openchange', onOpenChange);\n return () => {\n events.off('openchange', onOpenChange);\n };\n }, [events, enabled]);\n React.useEffect(() => {\n return () => {\n clearTimeout(timeoutRef.current);\n };\n }, []);\n const reference = React.useMemo(() => ({\n onPointerDown(event) {\n if (isVirtualPointerEvent(event.nativeEvent)) return;\n keyboardModalityRef.current = false;\n },\n onMouseLeave() {\n blockFocusRef.current = false;\n },\n onFocus(event) {\n if (blockFocusRef.current) return;\n const target = getTarget(event.nativeEvent);\n if (visibleOnly && isElement(target)) {\n try {\n // Mac Safari unreliably matches `:focus-visible` on the reference\n // if focus was outside the page initially - use the fallback\n // instead.\n if (isSafari() && isMac()) throw Error();\n if (!target.matches(':focus-visible')) return;\n } catch (e) {\n // Old browsers will throw an error when using `:focus-visible`.\n if (!keyboardModalityRef.current && !isTypeableElement(target)) {\n return;\n }\n }\n }\n onOpenChange(true, event.nativeEvent, 'focus');\n },\n onBlur(event) {\n blockFocusRef.current = false;\n const relatedTarget = event.relatedTarget;\n const nativeEvent = event.nativeEvent;\n\n // Hit the non-modal focus management portal guard. Focus will be\n // moved into the floating element immediately after.\n const movedToFocusGuard = isElement(relatedTarget) && relatedTarget.hasAttribute(createAttribute('focus-guard')) && relatedTarget.getAttribute('data-type') === 'outside';\n\n // Wait for the window blur listener to fire.\n timeoutRef.current = window.setTimeout(() => {\n var _dataRef$current$floa;\n const activeEl = activeElement(elements.domReference ? elements.domReference.ownerDocument : document);\n\n // Focus left the page, keep it open.\n if (!relatedTarget && activeEl === elements.domReference) return;\n\n // When focusing the reference element (e.g. regular click), then\n // clicking into the floating element, prevent it from hiding.\n // Note: it must be focusable, e.g. `tabindex=\"-1\"`.\n // We can not rely on relatedTarget to point to the correct element\n // as it will only point to the shadow host of the newly focused element\n // and not the element that actually has received focus if it is located\n // inside a shadow root.\n if (contains((_dataRef$current$floa = dataRef.current.floatingContext) == null ? void 0 : _dataRef$current$floa.refs.floating.current, activeEl) || contains(elements.domReference, activeEl) || movedToFocusGuard) {\n return;\n }\n onOpenChange(false, nativeEvent, 'focus');\n });\n }\n }), [dataRef, elements.domReference, onOpenChange, visibleOnly]);\n return React.useMemo(() => enabled ? {\n reference\n } : {}, [enabled, reference]);\n}\n\nconst ACTIVE_KEY = 'active';\nconst SELECTED_KEY = 'selected';\nfunction mergeProps(userProps, propsList, elementKey) {\n const map = new Map();\n const isItem = elementKey === 'item';\n let domUserProps = userProps;\n if (isItem && userProps) {\n const {\n [ACTIVE_KEY]: _,\n [SELECTED_KEY]: __,\n ...validProps\n } = userProps;\n domUserProps = validProps;\n }\n return {\n ...(elementKey === 'floating' && {\n tabIndex: -1,\n [FOCUSABLE_ATTRIBUTE]: ''\n }),\n ...domUserProps,\n ...propsList.map(value => {\n const propsOrGetProps = value ? value[elementKey] : null;\n if (typeof propsOrGetProps === 'function') {\n return userProps ? propsOrGetProps(userProps) : null;\n }\n return propsOrGetProps;\n }).concat(userProps).reduce((acc, props) => {\n if (!props) {\n return acc;\n }\n Object.entries(props).forEach(_ref => {\n let [key, value] = _ref;\n if (isItem && [ACTIVE_KEY, SELECTED_KEY].includes(key)) {\n return;\n }\n if (key.indexOf('on') === 0) {\n if (!map.has(key)) {\n map.set(key, []);\n }\n if (typeof value === 'function') {\n var _map$get;\n (_map$get = map.get(key)) == null || _map$get.push(value);\n acc[key] = function () {\n var _map$get2;\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return (_map$get2 = map.get(key)) == null ? void 0 : _map$get2.map(fn => fn(...args)).find(val => val !== undefined);\n };\n }\n } else {\n acc[key] = value;\n }\n });\n return acc;\n }, {})\n };\n}\n/**\n * Merges an array of interaction hooks' props into prop getters, allowing\n * event handler functions to be composed together without overwriting one\n * another.\n * @see https://floating-ui.com/docs/useInteractions\n */\nfunction useInteractions(propsList) {\n if (propsList === void 0) {\n propsList = [];\n }\n const referenceDeps = propsList.map(key => key == null ? void 0 : key.reference);\n const floatingDeps = propsList.map(key => key == null ? void 0 : key.floating);\n const itemDeps = propsList.map(key => key == null ? void 0 : key.item);\n const getReferenceProps = React.useCallback(userProps => mergeProps(userProps, propsList, 'reference'),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n referenceDeps);\n const getFloatingProps = React.useCallback(userProps => mergeProps(userProps, propsList, 'floating'),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n floatingDeps);\n const getItemProps = React.useCallback(userProps => mergeProps(userProps, propsList, 'item'),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n itemDeps);\n return React.useMemo(() => ({\n getReferenceProps,\n getFloatingProps,\n getItemProps\n }), [getReferenceProps, getFloatingProps, getItemProps]);\n}\n\nlet isPreventScrollSupported = false;\nfunction doSwitch(orientation, vertical, horizontal) {\n switch (orientation) {\n case 'vertical':\n return vertical;\n case 'horizontal':\n return horizontal;\n default:\n return vertical || horizontal;\n }\n}\nfunction isMainOrientationKey(key, orientation) {\n const vertical = key === ARROW_UP || key === ARROW_DOWN;\n const horizontal = key === ARROW_LEFT || key === ARROW_RIGHT;\n return doSwitch(orientation, vertical, horizontal);\n}\nfunction isMainOrientationToEndKey(key, orientation, rtl) {\n const vertical = key === ARROW_DOWN;\n const horizontal = rtl ? key === ARROW_LEFT : key === ARROW_RIGHT;\n return doSwitch(orientation, vertical, horizontal) || key === 'Enter' || key === ' ' || key === '';\n}\nfunction isCrossOrientationOpenKey(key, orientation, rtl) {\n const vertical = rtl ? key === ARROW_LEFT : key === ARROW_RIGHT;\n const horizontal = key === ARROW_DOWN;\n return doSwitch(orientation, vertical, horizontal);\n}\nfunction isCrossOrientationCloseKey(key, orientation, rtl) {\n const vertical = rtl ? key === ARROW_RIGHT : key === ARROW_LEFT;\n const horizontal = key === ARROW_UP;\n return doSwitch(orientation, vertical, horizontal);\n}\n/**\n * Adds arrow key-based navigation of a list of items, either using real DOM\n * focus or virtual focus.\n * @see https://floating-ui.com/docs/useListNavigation\n */\nfunction useListNavigation(context, props) {\n const {\n open,\n onOpenChange,\n elements\n } = context;\n const {\n listRef,\n activeIndex,\n onNavigate: unstable_onNavigate = () => {},\n enabled = true,\n selectedIndex = null,\n allowEscape = false,\n loop = false,\n nested = false,\n rtl = false,\n virtual = false,\n focusItemOnOpen = 'auto',\n focusItemOnHover = true,\n openOnArrowKeyDown = true,\n disabledIndices = undefined,\n orientation = 'vertical',\n cols = 1,\n scrollItemIntoView = true,\n virtualItemRef,\n itemSizes,\n dense = false\n } = props;\n if (process.env.NODE_ENV !== \"production\") {\n if (allowEscape) {\n if (!loop) {\n warn('`useListNavigation` looping must be enabled to allow escaping.');\n }\n if (!virtual) {\n warn('`useListNavigation` must be virtual to allow escaping.');\n }\n }\n if (orientation === 'vertical' && cols > 1) {\n warn('In grid list navigation mode (`cols` > 1), the `orientation` should', 'be either \"horizontal\" or \"both\".');\n }\n }\n const floatingFocusElement = getFloatingFocusElement(elements.floating);\n const floatingFocusElementRef = useLatestRef(floatingFocusElement);\n const parentId = useFloatingParentNodeId();\n const tree = useFloatingTree();\n const onNavigate = useEffectEvent(unstable_onNavigate);\n const typeableComboboxReference = isTypeableCombobox(elements.domReference);\n const focusItemOnOpenRef = React.useRef(focusItemOnOpen);\n const indexRef = React.useRef(selectedIndex != null ? selectedIndex : -1);\n const keyRef = React.useRef(null);\n const isPointerModalityRef = React.useRef(true);\n const previousOnNavigateRef = React.useRef(onNavigate);\n const previousMountedRef = React.useRef(!!elements.floating);\n const previousOpenRef = React.useRef(open);\n const forceSyncFocus = React.useRef(false);\n const forceScrollIntoViewRef = React.useRef(false);\n const disabledIndicesRef = useLatestRef(disabledIndices);\n const latestOpenRef = useLatestRef(open);\n const scrollItemIntoViewRef = useLatestRef(scrollItemIntoView);\n const selectedIndexRef = useLatestRef(selectedIndex);\n const [activeId, setActiveId] = React.useState();\n const [virtualId, setVirtualId] = React.useState();\n const focusItem = useEffectEvent(function (listRef, indexRef, forceScrollIntoView) {\n if (forceScrollIntoView === void 0) {\n forceScrollIntoView = false;\n }\n function runFocus(item) {\n if (virtual) {\n setActiveId(item.id);\n tree == null || tree.events.emit('virtualfocus', item);\n if (virtualItemRef) {\n virtualItemRef.current = item;\n }\n } else {\n enqueueFocus(item, {\n preventScroll: true,\n // Mac Safari does not move the virtual cursor unless the focus call\n // is sync. However, for the very first focus call, we need to wait\n // for the position to be ready in order to prevent unwanted\n // scrolling. This means the virtual cursor will not move to the first\n // item when first opening the floating element, but will on\n // subsequent calls. `preventScroll` is supported in modern Safari,\n // so we can use that instead.\n // iOS Safari must be async or the first item will not be focused.\n sync: isMac() && isSafari() ? isPreventScrollSupported || forceSyncFocus.current : false\n });\n }\n }\n const initialItem = listRef.current[indexRef.current];\n if (initialItem) {\n runFocus(initialItem);\n }\n requestAnimationFrame(() => {\n const waitedItem = listRef.current[indexRef.current] || initialItem;\n if (!waitedItem) return;\n if (!initialItem) {\n runFocus(waitedItem);\n }\n const scrollIntoViewOptions = scrollItemIntoViewRef.current;\n const shouldScrollIntoView = scrollIntoViewOptions && item && (forceScrollIntoView || !isPointerModalityRef.current);\n if (shouldScrollIntoView) {\n // JSDOM doesn't support `.scrollIntoView()` but it's widely supported\n // by all browsers.\n waitedItem.scrollIntoView == null || waitedItem.scrollIntoView(typeof scrollIntoViewOptions === 'boolean' ? {\n block: 'nearest',\n inline: 'nearest'\n } : scrollIntoViewOptions);\n }\n });\n });\n index(() => {\n document.createElement('div').focus({\n get preventScroll() {\n isPreventScrollSupported = true;\n return false;\n }\n });\n }, []);\n\n // Sync `selectedIndex` to be the `activeIndex` upon opening the floating\n // element. Also, reset `activeIndex` upon closing the floating element.\n index(() => {\n if (!enabled) return;\n if (open && elements.floating) {\n if (focusItemOnOpenRef.current && selectedIndex != null) {\n // Regardless of the pointer modality, we want to ensure the selected\n // item comes into view when the floating element is opened.\n forceScrollIntoViewRef.current = true;\n indexRef.current = selectedIndex;\n onNavigate(selectedIndex);\n }\n } else if (previousMountedRef.current) {\n // Since the user can specify `onNavigate` conditionally\n // (onNavigate: open ? setActiveIndex : setSelectedIndex),\n // we store and call the previous function.\n indexRef.current = -1;\n previousOnNavigateRef.current(null);\n }\n }, [enabled, open, elements.floating, selectedIndex, onNavigate]);\n\n // Sync `activeIndex` to be the focused item while the floating element is\n // open.\n index(() => {\n if (!enabled) return;\n if (open && elements.floating) {\n if (activeIndex == null) {\n forceSyncFocus.current = false;\n if (selectedIndexRef.current != null) {\n return;\n }\n\n // Reset while the floating element was open (e.g. the list changed).\n if (previousMountedRef.current) {\n indexRef.current = -1;\n focusItem(listRef, indexRef);\n }\n\n // Initial sync.\n if ((!previousOpenRef.current || !previousMountedRef.current) && focusItemOnOpenRef.current && (keyRef.current != null || focusItemOnOpenRef.current === true && keyRef.current == null)) {\n let runs = 0;\n const waitForListPopulated = () => {\n if (listRef.current[0] == null) {\n // Avoid letting the browser paint if possible on the first try,\n // otherwise use rAF. Don't try more than twice, since something\n // is wrong otherwise.\n if (runs < 2) {\n const scheduler = runs ? requestAnimationFrame : queueMicrotask;\n scheduler(waitForListPopulated);\n }\n runs++;\n } else {\n indexRef.current = keyRef.current == null || isMainOrientationToEndKey(keyRef.current, orientation, rtl) || nested ? getMinIndex(listRef, disabledIndicesRef.current) : getMaxIndex(listRef, disabledIndicesRef.current);\n keyRef.current = null;\n onNavigate(indexRef.current);\n }\n };\n waitForListPopulated();\n }\n } else if (!isIndexOutOfBounds(listRef, activeIndex)) {\n indexRef.current = activeIndex;\n focusItem(listRef, indexRef, forceScrollIntoViewRef.current);\n forceScrollIntoViewRef.current = false;\n }\n }\n }, [enabled, open, elements.floating, activeIndex, selectedIndexRef, nested, listRef, orientation, rtl, onNavigate, focusItem, disabledIndicesRef]);\n\n // Ensure the parent floating element has focus when a nested child closes\n // to allow arrow key navigation to work after the pointer leaves the child.\n index(() => {\n var _nodes$find;\n if (!enabled || elements.floating || !tree || virtual || !previousMountedRef.current) {\n return;\n }\n const nodes = tree.nodesRef.current;\n const parent = (_nodes$find = nodes.find(node => node.id === parentId)) == null || (_nodes$find = _nodes$find.context) == null ? void 0 : _nodes$find.elements.floating;\n const activeEl = activeElement(getDocument(elements.floating));\n const treeContainsActiveEl = nodes.some(node => node.context && contains(node.context.elements.floating, activeEl));\n if (parent && !treeContainsActiveEl && isPointerModalityRef.current) {\n parent.focus({\n preventScroll: true\n });\n }\n }, [enabled, elements.floating, tree, parentId, virtual]);\n index(() => {\n if (!enabled) return;\n if (!tree) return;\n if (!virtual) return;\n if (parentId) return;\n function handleVirtualFocus(item) {\n setVirtualId(item.id);\n if (virtualItemRef) {\n virtualItemRef.current = item;\n }\n }\n tree.events.on('virtualfocus', handleVirtualFocus);\n return () => {\n tree.events.off('virtualfocus', handleVirtualFocus);\n };\n }, [enabled, tree, virtual, parentId, virtualItemRef]);\n index(() => {\n previousOnNavigateRef.current = onNavigate;\n previousMountedRef.current = !!elements.floating;\n });\n index(() => {\n if (!open) {\n keyRef.current = null;\n }\n }, [open]);\n index(() => {\n previousOpenRef.current = open;\n }, [open]);\n const hasActiveIndex = activeIndex != null;\n const item = React.useMemo(() => {\n function syncCurrentTarget(currentTarget) {\n if (!open) return;\n const index = listRef.current.indexOf(currentTarget);\n if (index !== -1) {\n onNavigate(index);\n }\n }\n const props = {\n onFocus(_ref) {\n let {\n currentTarget\n } = _ref;\n syncCurrentTarget(currentTarget);\n },\n onClick: _ref2 => {\n let {\n currentTarget\n } = _ref2;\n return currentTarget.focus({\n preventScroll: true\n });\n },\n // Safari\n ...(focusItemOnHover && {\n onMouseMove(_ref3) {\n let {\n currentTarget\n } = _ref3;\n syncCurrentTarget(currentTarget);\n },\n onPointerLeave(_ref4) {\n let {\n pointerType\n } = _ref4;\n if (!isPointerModalityRef.current || pointerType === 'touch') {\n return;\n }\n indexRef.current = -1;\n focusItem(listRef, indexRef);\n onNavigate(null);\n if (!virtual) {\n enqueueFocus(floatingFocusElementRef.current, {\n preventScroll: true\n });\n }\n }\n })\n };\n return props;\n }, [open, floatingFocusElementRef, focusItem, focusItemOnHover, listRef, onNavigate, virtual]);\n const commonOnKeyDown = useEffectEvent(event => {\n isPointerModalityRef.current = false;\n forceSyncFocus.current = true;\n\n // When composing a character, Chrome fires ArrowDown twice. Firefox/Safari\n // don't appear to suffer from this. `event.isComposing` is avoided due to\n // Safari not supporting it properly (although it's not needed in the first\n // place for Safari, just avoiding any possible issues).\n if (event.which === 229) {\n return;\n }\n\n // If the floating element is animating out, ignore navigation. Otherwise,\n // the `activeIndex` gets set to 0 despite not being open so the next time\n // the user ArrowDowns, the first item won't be focused.\n if (!latestOpenRef.current && event.currentTarget === floatingFocusElementRef.current) {\n return;\n }\n if (nested && isCrossOrientationCloseKey(event.key, orientation, rtl)) {\n stopEvent(event);\n onOpenChange(false, event.nativeEvent, 'list-navigation');\n if (isHTMLElement(elements.domReference)) {\n if (virtual) {\n tree == null || tree.events.emit('virtualfocus', elements.domReference);\n } else {\n elements.domReference.focus();\n }\n }\n return;\n }\n const currentIndex = indexRef.current;\n const minIndex = getMinIndex(listRef, disabledIndices);\n const maxIndex = getMaxIndex(listRef, disabledIndices);\n if (!typeableComboboxReference) {\n if (event.key === 'Home') {\n stopEvent(event);\n indexRef.current = minIndex;\n onNavigate(indexRef.current);\n }\n if (event.key === 'End') {\n stopEvent(event);\n indexRef.current = maxIndex;\n onNavigate(indexRef.current);\n }\n }\n\n // Grid navigation.\n if (cols > 1) {\n const sizes = itemSizes || Array.from({\n length: listRef.current.length\n }, () => ({\n width: 1,\n height: 1\n }));\n // To calculate movements on the grid, we use hypothetical cell indices\n // as if every item was 1x1, then convert back to real indices.\n const cellMap = buildCellMap(sizes, cols, dense);\n const minGridIndex = cellMap.findIndex(index => index != null && !isDisabled(listRef.current, index, disabledIndices));\n // last enabled index\n const maxGridIndex = cellMap.reduce((foundIndex, index, cellIndex) => index != null && !isDisabled(listRef.current, index, disabledIndices) ? cellIndex : foundIndex, -1);\n const index = cellMap[getGridNavigatedIndex({\n current: cellMap.map(itemIndex => itemIndex != null ? listRef.current[itemIndex] : null)\n }, {\n event,\n orientation,\n loop,\n rtl,\n cols,\n // treat undefined (empty grid spaces) as disabled indices so we\n // don't end up in them\n disabledIndices: getCellIndices([...(disabledIndices || listRef.current.map((_, index) => isDisabled(listRef.current, index) ? index : undefined)), undefined], cellMap),\n minIndex: minGridIndex,\n maxIndex: maxGridIndex,\n prevIndex: getCellIndexOfCorner(indexRef.current > maxIndex ? minIndex : indexRef.current, sizes, cellMap, cols,\n // use a corner matching the edge closest to the direction\n // we're moving in so we don't end up in the same item. Prefer\n // top/left over bottom/right.\n event.key === ARROW_DOWN ? 'bl' : event.key === (rtl ? ARROW_LEFT : ARROW_RIGHT) ? 'tr' : 'tl'),\n stopEvent: true\n })];\n if (index != null) {\n indexRef.current = index;\n onNavigate(indexRef.current);\n }\n if (orientation === 'both') {\n return;\n }\n }\n if (isMainOrientationKey(event.key, orientation)) {\n stopEvent(event);\n\n // Reset the index if no item is focused.\n if (open && !virtual && activeElement(event.currentTarget.ownerDocument) === event.currentTarget) {\n indexRef.current = isMainOrientationToEndKey(event.key, orientation, rtl) ? minIndex : maxIndex;\n onNavigate(indexRef.current);\n return;\n }\n if (isMainOrientationToEndKey(event.key, orientation, rtl)) {\n if (loop) {\n indexRef.current = currentIndex >= maxIndex ? allowEscape && currentIndex !== listRef.current.length ? -1 : minIndex : findNonDisabledIndex(listRef, {\n startingIndex: currentIndex,\n disabledIndices\n });\n } else {\n indexRef.current = Math.min(maxIndex, findNonDisabledIndex(listRef, {\n startingIndex: currentIndex,\n disabledIndices\n }));\n }\n } else {\n if (loop) {\n indexRef.current = currentIndex <= minIndex ? allowEscape && currentIndex !== -1 ? listRef.current.length : maxIndex : findNonDisabledIndex(listRef, {\n startingIndex: currentIndex,\n decrement: true,\n disabledIndices\n });\n } else {\n indexRef.current = Math.max(minIndex, findNonDisabledIndex(listRef, {\n startingIndex: currentIndex,\n decrement: true,\n disabledIndices\n }));\n }\n }\n if (isIndexOutOfBounds(listRef, indexRef.current)) {\n onNavigate(null);\n } else {\n onNavigate(indexRef.current);\n }\n }\n });\n const ariaActiveDescendantProp = React.useMemo(() => {\n return virtual && open && hasActiveIndex && {\n 'aria-activedescendant': virtualId || activeId\n };\n }, [virtual, open, hasActiveIndex, virtualId, activeId]);\n const floating = React.useMemo(() => {\n return {\n 'aria-orientation': orientation === 'both' ? undefined : orientation,\n ...(!isTypeableCombobox(elements.domReference) && ariaActiveDescendantProp),\n onKeyDown: commonOnKeyDown,\n onPointerMove() {\n isPointerModalityRef.current = true;\n }\n };\n }, [ariaActiveDescendantProp, commonOnKeyDown, elements.domReference, orientation]);\n const reference = React.useMemo(() => {\n function checkVirtualMouse(event) {\n if (focusItemOnOpen === 'auto' && isVirtualClick(event.nativeEvent)) {\n focusItemOnOpenRef.current = true;\n }\n }\n function checkVirtualPointer(event) {\n // `pointerdown` fires first, reset the state then perform the checks.\n focusItemOnOpenRef.current = focusItemOnOpen;\n if (focusItemOnOpen === 'auto' && isVirtualPointerEvent(event.nativeEvent)) {\n focusItemOnOpenRef.current = true;\n }\n }\n return {\n ...ariaActiveDescendantProp,\n onKeyDown(event) {\n isPointerModalityRef.current = false;\n const isArrowKey = event.key.startsWith('Arrow');\n const isHomeOrEndKey = ['Home', 'End'].includes(event.key);\n const isMoveKey = isArrowKey || isHomeOrEndKey;\n const isCrossOpenKey = isCrossOrientationOpenKey(event.key, orientation, rtl);\n const isCrossCloseKey = isCrossOrientationCloseKey(event.key, orientation, rtl);\n const isMainKey = isMainOrientationKey(event.key, orientation);\n const isNavigationKey = (nested ? isCrossOpenKey : isMainKey) || event.key === 'Enter' || event.key.trim() === '';\n if (virtual && open) {\n const rootNode = tree == null ? void 0 : tree.nodesRef.current.find(node => node.parentId == null);\n const deepestNode = tree && rootNode ? getDeepestNode(tree.nodesRef.current, rootNode.id) : null;\n if (isMoveKey && deepestNode && virtualItemRef) {\n const eventObject = new KeyboardEvent('keydown', {\n key: event.key,\n bubbles: true\n });\n if (isCrossOpenKey || isCrossCloseKey) {\n var _deepestNode$context, _deepestNode$context2;\n const isCurrentTarget = ((_deepestNode$context = deepestNode.context) == null ? void 0 : _deepestNode$context.elements.domReference) === event.currentTarget;\n const dispatchItem = isCrossCloseKey && !isCurrentTarget ? (_deepestNode$context2 = deepestNode.context) == null ? void 0 : _deepestNode$context2.elements.domReference : isCrossOpenKey ? listRef.current.find(item => (item == null ? void 0 : item.id) === activeId) : null;\n if (dispatchItem) {\n stopEvent(event);\n dispatchItem.dispatchEvent(eventObject);\n setVirtualId(undefined);\n }\n }\n if ((isMainKey || isHomeOrEndKey) && deepestNode.context) {\n if (deepestNode.context.open && deepestNode.parentId && event.currentTarget !== deepestNode.context.elements.domReference) {\n var _deepestNode$context$;\n stopEvent(event);\n (_deepestNode$context$ = deepestNode.context.elements.domReference) == null || _deepestNode$context$.dispatchEvent(eventObject);\n return;\n }\n }\n }\n return commonOnKeyDown(event);\n }\n\n // If a floating element should not open on arrow key down, avoid\n // setting `activeIndex` while it's closed.\n if (!open && !openOnArrowKeyDown && isArrowKey) {\n return;\n }\n if (isNavigationKey) {\n keyRef.current = nested && isMainKey ? null : event.key;\n }\n if (nested) {\n if (isCrossOpenKey) {\n stopEvent(event);\n if (open) {\n indexRef.current = getMinIndex(listRef, disabledIndicesRef.current);\n onNavigate(indexRef.current);\n } else {\n onOpenChange(true, event.nativeEvent, 'list-navigation');\n }\n }\n return;\n }\n if (isMainKey) {\n if (selectedIndex != null) {\n indexRef.current = selectedIndex;\n }\n stopEvent(event);\n if (!open && openOnArrowKeyDown) {\n onOpenChange(true, event.nativeEvent, 'list-navigation');\n } else {\n commonOnKeyDown(event);\n }\n if (open) {\n onNavigate(indexRef.current);\n }\n }\n },\n onFocus() {\n if (open && !virtual) {\n onNavigate(null);\n }\n },\n onPointerDown: checkVirtualPointer,\n onMouseDown: checkVirtualMouse,\n onClick: checkVirtualMouse\n };\n }, [activeId, ariaActiveDescendantProp, commonOnKeyDown, disabledIndicesRef, focusItemOnOpen, listRef, nested, onNavigate, onOpenChange, open, openOnArrowKeyDown, orientation, rtl, selectedIndex, tree, virtual, virtualItemRef]);\n return React.useMemo(() => enabled ? {\n reference,\n floating,\n item\n } : {}, [enabled, reference, floating, item]);\n}\n\nconst componentRoleToAriaRoleMap = /*#__PURE__*/new Map([['select', 'listbox'], ['combobox', 'listbox'], ['label', false]]);\n\n/**\n * Adds base screen reader props to the reference and floating elements for a\n * given floating element `role`.\n * @see https://floating-ui.com/docs/useRole\n */\nfunction useRole(context, props) {\n var _componentRoleToAriaR;\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n floatingId\n } = context;\n const {\n enabled = true,\n role = 'dialog'\n } = props;\n const ariaRole = (_componentRoleToAriaR = componentRoleToAriaRoleMap.get(role)) != null ? _componentRoleToAriaR : role;\n const referenceId = useId();\n const parentId = useFloatingParentNodeId();\n const isNested = parentId != null;\n const reference = React.useMemo(() => {\n if (ariaRole === 'tooltip' || role === 'label') {\n return {\n [\"aria-\" + (role === 'label' ? 'labelledby' : 'describedby')]: open ? floatingId : undefined\n };\n }\n return {\n 'aria-expanded': open ? 'true' : 'false',\n 'aria-haspopup': ariaRole === 'alertdialog' ? 'dialog' : ariaRole,\n 'aria-controls': open ? floatingId : undefined,\n ...(ariaRole === 'listbox' && {\n role: 'combobox'\n }),\n ...(ariaRole === 'menu' && {\n id: referenceId\n }),\n ...(ariaRole === 'menu' && isNested && {\n role: 'menuitem'\n }),\n ...(role === 'select' && {\n 'aria-autocomplete': 'none'\n }),\n ...(role === 'combobox' && {\n 'aria-autocomplete': 'list'\n })\n };\n }, [ariaRole, floatingId, isNested, open, referenceId, role]);\n const floating = React.useMemo(() => {\n const floatingProps = {\n id: floatingId,\n ...(ariaRole && {\n role: ariaRole\n })\n };\n if (ariaRole === 'tooltip' || role === 'label') {\n return floatingProps;\n }\n return {\n ...floatingProps,\n ...(ariaRole === 'menu' && {\n 'aria-labelledby': referenceId\n })\n };\n }, [ariaRole, floatingId, referenceId, role]);\n const item = React.useCallback(_ref => {\n let {\n active,\n selected\n } = _ref;\n const commonProps = {\n role: 'option',\n ...(active && {\n id: floatingId + \"-option\"\n })\n };\n\n // For `menu`, we are unable to tell if the item is a `menuitemradio`\n // or `menuitemcheckbox`. For backwards-compatibility reasons, also\n // avoid defaulting to `menuitem` as it may overwrite custom role props.\n switch (role) {\n case 'select':\n return {\n ...commonProps,\n 'aria-selected': active && selected\n };\n case 'combobox':\n {\n return {\n ...commonProps,\n ...(active && {\n 'aria-selected': true\n })\n };\n }\n }\n return {};\n }, [floatingId, role]);\n return React.useMemo(() => enabled ? {\n reference,\n floating,\n item\n } : {}, [enabled, reference, floating, item]);\n}\n\n// Converts a JS style key like `backgroundColor` to a CSS transition-property\n// like `background-color`.\nconst camelCaseToKebabCase = str => str.replace(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? '-' : '') + $.toLowerCase());\nfunction execWithArgsOrReturn(valueOrFn, args) {\n return typeof valueOrFn === 'function' ? valueOrFn(args) : valueOrFn;\n}\nfunction useDelayUnmount(open, durationMs) {\n const [isMounted, setIsMounted] = React.useState(open);\n if (open && !isMounted) {\n setIsMounted(true);\n }\n React.useEffect(() => {\n if (!open && isMounted) {\n const timeout = setTimeout(() => setIsMounted(false), durationMs);\n return () => clearTimeout(timeout);\n }\n }, [open, isMounted, durationMs]);\n return isMounted;\n}\n/**\n * Provides a status string to apply CSS transitions to a floating element,\n * correctly handling placement-aware transitions.\n * @see https://floating-ui.com/docs/useTransition#usetransitionstatus\n */\nfunction useTransitionStatus(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n elements: {\n floating\n }\n } = context;\n const {\n duration = 250\n } = props;\n const isNumberDuration = typeof duration === 'number';\n const closeDuration = (isNumberDuration ? duration : duration.close) || 0;\n const [status, setStatus] = React.useState('unmounted');\n const isMounted = useDelayUnmount(open, closeDuration);\n if (!isMounted && status === 'close') {\n setStatus('unmounted');\n }\n index(() => {\n if (!floating) return;\n if (open) {\n setStatus('initial');\n const frame = requestAnimationFrame(() => {\n setStatus('open');\n });\n return () => {\n cancelAnimationFrame(frame);\n };\n }\n setStatus('close');\n }, [open, floating]);\n return {\n isMounted,\n status\n };\n}\n/**\n * Provides styles to apply CSS transitions to a floating element, correctly\n * handling placement-aware transitions. Wrapper around `useTransitionStatus`.\n * @see https://floating-ui.com/docs/useTransition#usetransitionstyles\n */\nfunction useTransitionStyles(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n initial: unstable_initial = {\n opacity: 0\n },\n open: unstable_open,\n close: unstable_close,\n common: unstable_common,\n duration = 250\n } = props;\n const placement = context.placement;\n const side = placement.split('-')[0];\n const fnArgs = React.useMemo(() => ({\n side,\n placement\n }), [side, placement]);\n const isNumberDuration = typeof duration === 'number';\n const openDuration = (isNumberDuration ? duration : duration.open) || 0;\n const closeDuration = (isNumberDuration ? duration : duration.close) || 0;\n const [styles, setStyles] = React.useState(() => ({\n ...execWithArgsOrReturn(unstable_common, fnArgs),\n ...execWithArgsOrReturn(unstable_initial, fnArgs)\n }));\n const {\n isMounted,\n status\n } = useTransitionStatus(context, {\n duration\n });\n const initialRef = useLatestRef(unstable_initial);\n const openRef = useLatestRef(unstable_open);\n const closeRef = useLatestRef(unstable_close);\n const commonRef = useLatestRef(unstable_common);\n index(() => {\n const initialStyles = execWithArgsOrReturn(initialRef.current, fnArgs);\n const closeStyles = execWithArgsOrReturn(closeRef.current, fnArgs);\n const commonStyles = execWithArgsOrReturn(commonRef.current, fnArgs);\n const openStyles = execWithArgsOrReturn(openRef.current, fnArgs) || Object.keys(initialStyles).reduce((acc, key) => {\n acc[key] = '';\n return acc;\n }, {});\n if (status === 'initial') {\n setStyles(styles => ({\n transitionProperty: styles.transitionProperty,\n ...commonStyles,\n ...initialStyles\n }));\n }\n if (status === 'open') {\n setStyles({\n transitionProperty: Object.keys(openStyles).map(camelCaseToKebabCase).join(','),\n transitionDuration: openDuration + \"ms\",\n ...commonStyles,\n ...openStyles\n });\n }\n if (status === 'close') {\n const styles = closeStyles || initialStyles;\n setStyles({\n transitionProperty: Object.keys(styles).map(camelCaseToKebabCase).join(','),\n transitionDuration: closeDuration + \"ms\",\n ...commonStyles,\n ...styles\n });\n }\n }, [closeDuration, closeRef, initialRef, openRef, commonRef, openDuration, status, fnArgs]);\n return {\n isMounted,\n styles\n };\n}\n\n/**\n * Provides a matching callback that can be used to focus an item as the user\n * types, often used in tandem with `useListNavigation()`.\n * @see https://floating-ui.com/docs/useTypeahead\n */\nfunction useTypeahead(context, props) {\n var _ref;\n const {\n open,\n dataRef\n } = context;\n const {\n listRef,\n activeIndex,\n onMatch: unstable_onMatch,\n onTypingChange: unstable_onTypingChange,\n enabled = true,\n findMatch = null,\n resetMs = 750,\n ignoreKeys = [],\n selectedIndex = null\n } = props;\n const timeoutIdRef = React.useRef();\n const stringRef = React.useRef('');\n const prevIndexRef = React.useRef((_ref = selectedIndex != null ? selectedIndex : activeIndex) != null ? _ref : -1);\n const matchIndexRef = React.useRef(null);\n const onMatch = useEffectEvent(unstable_onMatch);\n const onTypingChange = useEffectEvent(unstable_onTypingChange);\n const findMatchRef = useLatestRef(findMatch);\n const ignoreKeysRef = useLatestRef(ignoreKeys);\n index(() => {\n if (open) {\n clearTimeout(timeoutIdRef.current);\n matchIndexRef.current = null;\n stringRef.current = '';\n }\n }, [open]);\n index(() => {\n // Sync arrow key navigation but not typeahead navigation.\n if (open && stringRef.current === '') {\n var _ref2;\n prevIndexRef.current = (_ref2 = selectedIndex != null ? selectedIndex : activeIndex) != null ? _ref2 : -1;\n }\n }, [open, selectedIndex, activeIndex]);\n const setTypingChange = useEffectEvent(value => {\n if (value) {\n if (!dataRef.current.typing) {\n dataRef.current.typing = value;\n onTypingChange(value);\n }\n } else {\n if (dataRef.current.typing) {\n dataRef.current.typing = value;\n onTypingChange(value);\n }\n }\n });\n const onKeyDown = useEffectEvent(event => {\n function getMatchingIndex(list, orderedList, string) {\n const str = findMatchRef.current ? findMatchRef.current(orderedList, string) : orderedList.find(text => (text == null ? void 0 : text.toLocaleLowerCase().indexOf(string.toLocaleLowerCase())) === 0);\n return str ? list.indexOf(str) : -1;\n }\n const listContent = listRef.current;\n if (stringRef.current.length > 0 && stringRef.current[0] !== ' ') {\n if (getMatchingIndex(listContent, listContent, stringRef.current) === -1) {\n setTypingChange(false);\n } else if (event.key === ' ') {\n stopEvent(event);\n }\n }\n if (listContent == null || ignoreKeysRef.current.includes(event.key) ||\n // Character key.\n event.key.length !== 1 ||\n // Modifier key.\n event.ctrlKey || event.metaKey || event.altKey) {\n return;\n }\n if (open && event.key !== ' ') {\n stopEvent(event);\n setTypingChange(true);\n }\n\n // Bail out if the list contains a word like \"llama\" or \"aaron\". TODO:\n // allow it in this case, too.\n const allowRapidSuccessionOfFirstLetter = listContent.every(text => {\n var _text$, _text$2;\n return text ? ((_text$ = text[0]) == null ? void 0 : _text$.toLocaleLowerCase()) !== ((_text$2 = text[1]) == null ? void 0 : _text$2.toLocaleLowerCase()) : true;\n });\n\n // Allows the user to cycle through items that start with the same letter\n // in rapid succession.\n if (allowRapidSuccessionOfFirstLetter && stringRef.current === event.key) {\n stringRef.current = '';\n prevIndexRef.current = matchIndexRef.current;\n }\n stringRef.current += event.key;\n clearTimeout(timeoutIdRef.current);\n timeoutIdRef.current = setTimeout(() => {\n stringRef.current = '';\n prevIndexRef.current = matchIndexRef.current;\n setTypingChange(false);\n }, resetMs);\n const prevIndex = prevIndexRef.current;\n const index = getMatchingIndex(listContent, [...listContent.slice((prevIndex || 0) + 1), ...listContent.slice(0, (prevIndex || 0) + 1)], stringRef.current);\n if (index !== -1) {\n onMatch(index);\n matchIndexRef.current = index;\n } else if (event.key !== ' ') {\n stringRef.current = '';\n setTypingChange(false);\n }\n });\n const reference = React.useMemo(() => ({\n onKeyDown\n }), [onKeyDown]);\n const floating = React.useMemo(() => {\n return {\n onKeyDown,\n onKeyUp(event) {\n if (event.key === ' ') {\n setTypingChange(false);\n }\n }\n };\n }, [onKeyDown, setTypingChange]);\n return React.useMemo(() => enabled ? {\n reference,\n floating\n } : {}, [enabled, reference, floating]);\n}\n\nfunction getArgsWithCustomFloatingHeight(state, height) {\n return {\n ...state,\n rects: {\n ...state.rects,\n floating: {\n ...state.rects.floating,\n height\n }\n }\n };\n}\n/**\n * Positions the floating element such that an inner element inside of it is\n * anchored to the reference element.\n * @see https://floating-ui.com/docs/inner\n */\nconst inner = props => ({\n name: 'inner',\n options: props,\n async fn(state) {\n const {\n listRef,\n overflowRef,\n onFallbackChange,\n offset: innerOffset = 0,\n index = 0,\n minItemsVisible = 4,\n referenceOverflowThreshold = 0,\n scrollRef,\n ...detectOverflowOptions\n } = evaluate(props, state);\n const {\n rects,\n elements: {\n floating\n }\n } = state;\n const item = listRef.current[index];\n const scrollEl = (scrollRef == null ? void 0 : scrollRef.current) || floating;\n\n // Valid combinations:\n // 1. Floating element is the scrollRef and has a border (default)\n // 2. Floating element is not the scrollRef, floating element has a border\n // 3. Floating element is not the scrollRef, scrollRef has a border\n // Floating > {...getFloatingProps()} wrapper > scrollRef > items is not\n // allowed as VoiceOver doesn't work.\n const clientTop = floating.clientTop || scrollEl.clientTop;\n const floatingIsBordered = floating.clientTop !== 0;\n const scrollElIsBordered = scrollEl.clientTop !== 0;\n const floatingIsScrollEl = floating === scrollEl;\n if (process.env.NODE_ENV !== \"production\") {\n if (!state.placement.startsWith('bottom')) {\n warn('`placement` side must be \"bottom\" when using the `inner`', 'middleware.');\n }\n }\n if (!item) {\n return {};\n }\n const nextArgs = {\n ...state,\n ...(await offset(-item.offsetTop - floating.clientTop - rects.reference.height / 2 - item.offsetHeight / 2 - innerOffset).fn(state))\n };\n const overflow = await detectOverflow(getArgsWithCustomFloatingHeight(nextArgs, scrollEl.scrollHeight + clientTop + floating.clientTop), detectOverflowOptions);\n const refOverflow = await detectOverflow(nextArgs, {\n ...detectOverflowOptions,\n elementContext: 'reference'\n });\n const diffY = max(0, overflow.top);\n const nextY = nextArgs.y + diffY;\n const isScrollable = scrollEl.scrollHeight > scrollEl.clientHeight;\n const rounder = isScrollable ? v => v : round;\n const maxHeight = rounder(max(0, scrollEl.scrollHeight + (floatingIsBordered && floatingIsScrollEl || scrollElIsBordered ? clientTop * 2 : 0) - diffY - max(0, overflow.bottom)));\n scrollEl.style.maxHeight = maxHeight + \"px\";\n scrollEl.scrollTop = diffY;\n\n // There is not enough space, fallback to standard anchored positioning\n if (onFallbackChange) {\n const shouldFallback = scrollEl.offsetHeight < item.offsetHeight * min(minItemsVisible, listRef.current.length) - 1 || refOverflow.top >= -referenceOverflowThreshold || refOverflow.bottom >= -referenceOverflowThreshold;\n ReactDOM.flushSync(() => onFallbackChange(shouldFallback));\n }\n if (overflowRef) {\n overflowRef.current = await detectOverflow(getArgsWithCustomFloatingHeight({\n ...nextArgs,\n y: nextY\n }, scrollEl.offsetHeight + clientTop + floating.clientTop), detectOverflowOptions);\n }\n return {\n y: nextY\n };\n }\n});\n/**\n * Changes the `inner` middleware's `offset` upon a `wheel` event to\n * expand the floating element's height, revealing more list items.\n * @see https://floating-ui.com/docs/inner\n */\nfunction useInnerOffset(context, props) {\n const {\n open,\n elements\n } = context;\n const {\n enabled = true,\n overflowRef,\n scrollRef,\n onChange: unstable_onChange\n } = props;\n const onChange = useEffectEvent(unstable_onChange);\n const controlledScrollingRef = React.useRef(false);\n const prevScrollTopRef = React.useRef(null);\n const initialOverflowRef = React.useRef(null);\n React.useEffect(() => {\n if (!enabled) return;\n function onWheel(e) {\n if (e.ctrlKey || !el || overflowRef.current == null) {\n return;\n }\n const dY = e.deltaY;\n const isAtTop = overflowRef.current.top >= -0.5;\n const isAtBottom = overflowRef.current.bottom >= -0.5;\n const remainingScroll = el.scrollHeight - el.clientHeight;\n const sign = dY < 0 ? -1 : 1;\n const method = dY < 0 ? 'max' : 'min';\n if (el.scrollHeight <= el.clientHeight) {\n return;\n }\n if (!isAtTop && dY > 0 || !isAtBottom && dY < 0) {\n e.preventDefault();\n ReactDOM.flushSync(() => {\n onChange(d => d + Math[method](dY, remainingScroll * sign));\n });\n } else if (/firefox/i.test(getUserAgent())) {\n // Needed to propagate scrolling during momentum scrolling phase once\n // it gets limited by the boundary. UX improvement, not critical.\n el.scrollTop += dY;\n }\n }\n const el = (scrollRef == null ? void 0 : scrollRef.current) || elements.floating;\n if (open && el) {\n el.addEventListener('wheel', onWheel);\n\n // Wait for the position to be ready.\n requestAnimationFrame(() => {\n prevScrollTopRef.current = el.scrollTop;\n if (overflowRef.current != null) {\n initialOverflowRef.current = {\n ...overflowRef.current\n };\n }\n });\n return () => {\n prevScrollTopRef.current = null;\n initialOverflowRef.current = null;\n el.removeEventListener('wheel', onWheel);\n };\n }\n }, [enabled, open, elements.floating, overflowRef, scrollRef, onChange]);\n const floating = React.useMemo(() => ({\n onKeyDown() {\n controlledScrollingRef.current = true;\n },\n onWheel() {\n controlledScrollingRef.current = false;\n },\n onPointerMove() {\n controlledScrollingRef.current = false;\n },\n onScroll() {\n const el = (scrollRef == null ? void 0 : scrollRef.current) || elements.floating;\n if (!overflowRef.current || !el || !controlledScrollingRef.current) {\n return;\n }\n if (prevScrollTopRef.current !== null) {\n const scrollDiff = el.scrollTop - prevScrollTopRef.current;\n if (overflowRef.current.bottom < -0.5 && scrollDiff < -1 || overflowRef.current.top < -0.5 && scrollDiff > 1) {\n ReactDOM.flushSync(() => onChange(d => d + scrollDiff));\n }\n }\n\n // [Firefox] Wait for the height change to have been applied.\n requestAnimationFrame(() => {\n prevScrollTopRef.current = el.scrollTop;\n });\n }\n }), [elements.floating, onChange, overflowRef, scrollRef]);\n return React.useMemo(() => enabled ? {\n floating\n } : {}, [enabled, floating]);\n}\n\nfunction isPointInPolygon(point, polygon) {\n const [x, y] = point;\n let isInside = false;\n const length = polygon.length;\n for (let i = 0, j = length - 1; i < length; j = i++) {\n const [xi, yi] = polygon[i] || [0, 0];\n const [xj, yj] = polygon[j] || [0, 0];\n const intersect = yi >= y !== yj >= y && x <= (xj - xi) * (y - yi) / (yj - yi) + xi;\n if (intersect) {\n isInside = !isInside;\n }\n }\n return isInside;\n}\nfunction isInside(point, rect) {\n return point[0] >= rect.x && point[0] <= rect.x + rect.width && point[1] >= rect.y && point[1] <= rect.y + rect.height;\n}\n/**\n * Generates a safe polygon area that the user can traverse without closing the\n * floating element once leaving the reference element.\n * @see https://floating-ui.com/docs/useHover#safepolygon\n */\nfunction safePolygon(options) {\n if (options === void 0) {\n options = {};\n }\n const {\n buffer = 0.5,\n blockPointerEvents = false,\n requireIntent = true\n } = options;\n let timeoutId;\n let hasLanded = false;\n let lastX = null;\n let lastY = null;\n let lastCursorTime = performance.now();\n function getCursorSpeed(x, y) {\n const currentTime = performance.now();\n const elapsedTime = currentTime - lastCursorTime;\n if (lastX === null || lastY === null || elapsedTime === 0) {\n lastX = x;\n lastY = y;\n lastCursorTime = currentTime;\n return null;\n }\n const deltaX = x - lastX;\n const deltaY = y - lastY;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n const speed = distance / elapsedTime; // px / ms\n\n lastX = x;\n lastY = y;\n lastCursorTime = currentTime;\n return speed;\n }\n const fn = _ref => {\n let {\n x,\n y,\n placement,\n elements,\n onClose,\n nodeId,\n tree\n } = _ref;\n return function onMouseMove(event) {\n function close() {\n clearTimeout(timeoutId);\n onClose();\n }\n clearTimeout(timeoutId);\n if (!elements.domReference || !elements.floating || placement == null || x == null || y == null) {\n return;\n }\n const {\n clientX,\n clientY\n } = event;\n const clientPoint = [clientX, clientY];\n const target = getTarget(event);\n const isLeave = event.type === 'mouseleave';\n const isOverFloatingEl = contains(elements.floating, target);\n const isOverReferenceEl = contains(elements.domReference, target);\n const refRect = elements.domReference.getBoundingClientRect();\n const rect = elements.floating.getBoundingClientRect();\n const side = placement.split('-')[0];\n const cursorLeaveFromRight = x > rect.right - rect.width / 2;\n const cursorLeaveFromBottom = y > rect.bottom - rect.height / 2;\n const isOverReferenceRect = isInside(clientPoint, refRect);\n const isFloatingWider = rect.width > refRect.width;\n const isFloatingTaller = rect.height > refRect.height;\n const left = (isFloatingWider ? refRect : rect).left;\n const right = (isFloatingWider ? refRect : rect).right;\n const top = (isFloatingTaller ? refRect : rect).top;\n const bottom = (isFloatingTaller ? refRect : rect).bottom;\n if (isOverFloatingEl) {\n hasLanded = true;\n if (!isLeave) {\n return;\n }\n }\n if (isOverReferenceEl) {\n hasLanded = false;\n }\n if (isOverReferenceEl && !isLeave) {\n hasLanded = true;\n return;\n }\n\n // Prevent overlapping floating element from being stuck in an open-close\n // loop: https://github.com/floating-ui/floating-ui/issues/1910\n if (isLeave && isElement(event.relatedTarget) && contains(elements.floating, event.relatedTarget)) {\n return;\n }\n\n // If any nested child is open, abort.\n if (tree && getChildren(tree.nodesRef.current, nodeId).some(_ref2 => {\n let {\n context\n } = _ref2;\n return context == null ? void 0 : context.open;\n })) {\n return;\n }\n\n // If the pointer is leaving from the opposite side, the \"buffer\" logic\n // creates a point where the floating element remains open, but should be\n // ignored.\n // A constant of 1 handles floating point rounding errors.\n if (side === 'top' && y >= refRect.bottom - 1 || side === 'bottom' && y <= refRect.top + 1 || side === 'left' && x >= refRect.right - 1 || side === 'right' && x <= refRect.left + 1) {\n return close();\n }\n\n // Ignore when the cursor is within the rectangular trough between the\n // two elements. Since the triangle is created from the cursor point,\n // which can start beyond the ref element's edge, traversing back and\n // forth from the ref to the floating element can cause it to close. This\n // ensures it always remains open in that case.\n let rectPoly = [];\n switch (side) {\n case 'top':\n rectPoly = [[left, refRect.top + 1], [left, rect.bottom - 1], [right, rect.bottom - 1], [right, refRect.top + 1]];\n break;\n case 'bottom':\n rectPoly = [[left, rect.top + 1], [left, refRect.bottom - 1], [right, refRect.bottom - 1], [right, rect.top + 1]];\n break;\n case 'left':\n rectPoly = [[rect.right - 1, bottom], [rect.right - 1, top], [refRect.left + 1, top], [refRect.left + 1, bottom]];\n break;\n case 'right':\n rectPoly = [[refRect.right - 1, bottom], [refRect.right - 1, top], [rect.left + 1, top], [rect.left + 1, bottom]];\n break;\n }\n function getPolygon(_ref3) {\n let [x, y] = _ref3;\n switch (side) {\n case 'top':\n {\n const cursorPointOne = [isFloatingWider ? x + buffer / 2 : cursorLeaveFromRight ? x + buffer * 4 : x - buffer * 4, y + buffer + 1];\n const cursorPointTwo = [isFloatingWider ? x - buffer / 2 : cursorLeaveFromRight ? x + buffer * 4 : x - buffer * 4, y + buffer + 1];\n const commonPoints = [[rect.left, cursorLeaveFromRight ? rect.bottom - buffer : isFloatingWider ? rect.bottom - buffer : rect.top], [rect.right, cursorLeaveFromRight ? isFloatingWider ? rect.bottom - buffer : rect.top : rect.bottom - buffer]];\n return [cursorPointOne, cursorPointTwo, ...commonPoints];\n }\n case 'bottom':\n {\n const cursorPointOne = [isFloatingWider ? x + buffer / 2 : cursorLeaveFromRight ? x + buffer * 4 : x - buffer * 4, y - buffer];\n const cursorPointTwo = [isFloatingWider ? x - buffer / 2 : cursorLeaveFromRight ? x + buffer * 4 : x - buffer * 4, y - buffer];\n const commonPoints = [[rect.left, cursorLeaveFromRight ? rect.top + buffer : isFloatingWider ? rect.top + buffer : rect.bottom], [rect.right, cursorLeaveFromRight ? isFloatingWider ? rect.top + buffer : rect.bottom : rect.top + buffer]];\n return [cursorPointOne, cursorPointTwo, ...commonPoints];\n }\n case 'left':\n {\n const cursorPointOne = [x + buffer + 1, isFloatingTaller ? y + buffer / 2 : cursorLeaveFromBottom ? y + buffer * 4 : y - buffer * 4];\n const cursorPointTwo = [x + buffer + 1, isFloatingTaller ? y - buffer / 2 : cursorLeaveFromBottom ? y + buffer * 4 : y - buffer * 4];\n const commonPoints = [[cursorLeaveFromBottom ? rect.right - buffer : isFloatingTaller ? rect.right - buffer : rect.left, rect.top], [cursorLeaveFromBottom ? isFloatingTaller ? rect.right - buffer : rect.left : rect.right - buffer, rect.bottom]];\n return [...commonPoints, cursorPointOne, cursorPointTwo];\n }\n case 'right':\n {\n const cursorPointOne = [x - buffer, isFloatingTaller ? y + buffer / 2 : cursorLeaveFromBottom ? y + buffer * 4 : y - buffer * 4];\n const cursorPointTwo = [x - buffer, isFloatingTaller ? y - buffer / 2 : cursorLeaveFromBottom ? y + buffer * 4 : y - buffer * 4];\n const commonPoints = [[cursorLeaveFromBottom ? rect.left + buffer : isFloatingTaller ? rect.left + buffer : rect.right, rect.top], [cursorLeaveFromBottom ? isFloatingTaller ? rect.left + buffer : rect.right : rect.left + buffer, rect.bottom]];\n return [cursorPointOne, cursorPointTwo, ...commonPoints];\n }\n }\n }\n if (isPointInPolygon([clientX, clientY], rectPoly)) {\n return;\n }\n if (hasLanded && !isOverReferenceRect) {\n return close();\n }\n if (!isLeave && requireIntent) {\n const cursorSpeed = getCursorSpeed(event.clientX, event.clientY);\n const cursorSpeedThreshold = 0.1;\n if (cursorSpeed !== null && cursorSpeed < cursorSpeedThreshold) {\n return close();\n }\n }\n if (!isPointInPolygon([clientX, clientY], getPolygon([x, y]))) {\n close();\n } else if (!hasLanded && requireIntent) {\n timeoutId = window.setTimeout(close, 40);\n }\n };\n };\n fn.__options = {\n blockPointerEvents\n };\n return fn;\n}\n\nexport { Composite, CompositeItem, FloatingArrow, FloatingDelayGroup, FloatingFocusManager, FloatingList, FloatingNode, FloatingOverlay, FloatingPortal, FloatingTree, inner, safePolygon, useClick, useClientPoint, useDelayGroup, useDelayGroupContext, useDismiss, useFloating, useFloatingNodeId, useFloatingParentNodeId, useFloatingPortalNode, useFloatingRootContext, useFloatingTree, useFocus, useHover, useId, useInnerOffset, useInteractions, useListItem, useListNavigation, useMergeRefs, useRole, useTransitionStatus, useTransitionStyles, useTypeahead };\n","/**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\nfunction listCacheClear() {\n this.__data__ = [];\n this.size = 0;\n}\n\nmodule.exports = listCacheClear;\n","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\nmodule.exports = eq;\n","var eq = require('./eq');\n\n/**\n * Gets the index at which the `key` is found in `array` of key-value pairs.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} key The key to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction assocIndexOf(array, key) {\n var length = array.length;\n while (length--) {\n if (eq(array[length][0], key)) {\n return length;\n }\n }\n return -1;\n}\n\nmodule.exports = assocIndexOf;\n","var assocIndexOf = require('./_assocIndexOf');\n\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype;\n\n/** Built-in value references. */\nvar splice = arrayProto.splice;\n\n/**\n * Removes `key` and its value from the list cache.\n *\n * @private\n * @name delete\n * @memberOf ListCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction listCacheDelete(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n return false;\n }\n var lastIndex = data.length - 1;\n if (index == lastIndex) {\n data.pop();\n } else {\n splice.call(data, index, 1);\n }\n --this.size;\n return true;\n}\n\nmodule.exports = listCacheDelete;\n","var assocIndexOf = require('./_assocIndexOf');\n\n/**\n * Gets the list cache value for `key`.\n *\n * @private\n * @name get\n * @memberOf ListCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction listCacheGet(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n return index < 0 ? undefined : data[index][1];\n}\n\nmodule.exports = listCacheGet;\n","var assocIndexOf = require('./_assocIndexOf');\n\n/**\n * Checks if a list cache value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf ListCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction listCacheHas(key) {\n return assocIndexOf(this.__data__, key) > -1;\n}\n\nmodule.exports = listCacheHas;\n","var assocIndexOf = require('./_assocIndexOf');\n\n/**\n * Sets the list cache `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf ListCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the list cache instance.\n */\nfunction listCacheSet(key, value) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n ++this.size;\n data.push([key, value]);\n } else {\n data[index][1] = value;\n }\n return this;\n}\n\nmodule.exports = listCacheSet;\n","var listCacheClear = require('./_listCacheClear'),\n listCacheDelete = require('./_listCacheDelete'),\n listCacheGet = require('./_listCacheGet'),\n listCacheHas = require('./_listCacheHas'),\n listCacheSet = require('./_listCacheSet');\n\n/**\n * Creates an list cache object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction ListCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `ListCache`.\nListCache.prototype.clear = listCacheClear;\nListCache.prototype['delete'] = listCacheDelete;\nListCache.prototype.get = listCacheGet;\nListCache.prototype.has = listCacheHas;\nListCache.prototype.set = listCacheSet;\n\nmodule.exports = ListCache;\n","var ListCache = require('./_ListCache');\n\n/**\n * Removes all key-value entries from the stack.\n *\n * @private\n * @name clear\n * @memberOf Stack\n */\nfunction stackClear() {\n this.__data__ = new ListCache;\n this.size = 0;\n}\n\nmodule.exports = stackClear;\n","/**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction stackDelete(key) {\n var data = this.__data__,\n result = data['delete'](key);\n\n this.size = data.size;\n return result;\n}\n\nmodule.exports = stackDelete;\n","/**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction stackGet(key) {\n return this.__data__.get(key);\n}\n\nmodule.exports = stackGet;\n","/**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction stackHas(key) {\n return this.__data__.has(key);\n}\n\nmodule.exports = stackHas;\n","/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nmodule.exports = freeGlobal;\n","var freeGlobal = require('./_freeGlobal');\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nmodule.exports = root;\n","var root = require('./_root');\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nmodule.exports = Symbol;\n","var Symbol = require('./_Symbol');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n}\n\nmodule.exports = getRawTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nmodule.exports = objectToString;\n","var Symbol = require('./_Symbol'),\n getRawTag = require('./_getRawTag'),\n objectToString = require('./_objectToString');\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n}\n\nmodule.exports = baseGetTag;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nmodule.exports = isObject;\n","var baseGetTag = require('./_baseGetTag'),\n isObject = require('./isObject');\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nmodule.exports = isFunction;\n","var root = require('./_root');\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nmodule.exports = coreJsData;\n","var coreJsData = require('./_coreJsData');\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n}\n\nmodule.exports = isMasked;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nmodule.exports = toSource;\n","var isFunction = require('./isFunction'),\n isMasked = require('./_isMasked'),\n isObject = require('./isObject'),\n toSource = require('./_toSource');\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\nfunction baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\n\nmodule.exports = baseIsNative;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nmodule.exports = getValue;\n","var baseIsNative = require('./_baseIsNative'),\n getValue = require('./_getValue');\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n}\n\nmodule.exports = getNative;\n","var getNative = require('./_getNative'),\n root = require('./_root');\n\n/* Built-in method references that are verified to be native. */\nvar Map = getNative(root, 'Map');\n\nmodule.exports = Map;\n","var getNative = require('./_getNative');\n\n/* Built-in method references that are verified to be native. */\nvar nativeCreate = getNative(Object, 'create');\n\nmodule.exports = nativeCreate;\n","var nativeCreate = require('./_nativeCreate');\n\n/**\n * Removes all key-value entries from the hash.\n *\n * @private\n * @name clear\n * @memberOf Hash\n */\nfunction hashClear() {\n this.__data__ = nativeCreate ? nativeCreate(null) : {};\n this.size = 0;\n}\n\nmodule.exports = hashClear;\n","/**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction hashDelete(key) {\n var result = this.has(key) && delete this.__data__[key];\n this.size -= result ? 1 : 0;\n return result;\n}\n\nmodule.exports = hashDelete;\n","var nativeCreate = require('./_nativeCreate');\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Gets the hash value for `key`.\n *\n * @private\n * @name get\n * @memberOf Hash\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction hashGet(key) {\n var data = this.__data__;\n if (nativeCreate) {\n var result = data[key];\n return result === HASH_UNDEFINED ? undefined : result;\n }\n return hasOwnProperty.call(data, key) ? data[key] : undefined;\n}\n\nmodule.exports = hashGet;\n","var nativeCreate = require('./_nativeCreate');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Checks if a hash value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Hash\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction hashHas(key) {\n var data = this.__data__;\n return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);\n}\n\nmodule.exports = hashHas;\n","var nativeCreate = require('./_nativeCreate');\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Sets the hash `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Hash\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the hash instance.\n */\nfunction hashSet(key, value) {\n var data = this.__data__;\n this.size += this.has(key) ? 0 : 1;\n data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n return this;\n}\n\nmodule.exports = hashSet;\n","var hashClear = require('./_hashClear'),\n hashDelete = require('./_hashDelete'),\n hashGet = require('./_hashGet'),\n hashHas = require('./_hashHas'),\n hashSet = require('./_hashSet');\n\n/**\n * Creates a hash object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Hash(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `Hash`.\nHash.prototype.clear = hashClear;\nHash.prototype['delete'] = hashDelete;\nHash.prototype.get = hashGet;\nHash.prototype.has = hashHas;\nHash.prototype.set = hashSet;\n\nmodule.exports = Hash;\n","var Hash = require('./_Hash'),\n ListCache = require('./_ListCache'),\n Map = require('./_Map');\n\n/**\n * Removes all key-value entries from the map.\n *\n * @private\n * @name clear\n * @memberOf MapCache\n */\nfunction mapCacheClear() {\n this.size = 0;\n this.__data__ = {\n 'hash': new Hash,\n 'map': new (Map || ListCache),\n 'string': new Hash\n };\n}\n\nmodule.exports = mapCacheClear;\n","/**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\nfunction isKeyable(value) {\n var type = typeof value;\n return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n ? (value !== '__proto__')\n : (value === null);\n}\n\nmodule.exports = isKeyable;\n","var isKeyable = require('./_isKeyable');\n\n/**\n * Gets the data for `map`.\n *\n * @private\n * @param {Object} map The map to query.\n * @param {string} key The reference key.\n * @returns {*} Returns the map data.\n */\nfunction getMapData(map, key) {\n var data = map.__data__;\n return isKeyable(key)\n ? data[typeof key == 'string' ? 'string' : 'hash']\n : data.map;\n}\n\nmodule.exports = getMapData;\n","var getMapData = require('./_getMapData');\n\n/**\n * Removes `key` and its value from the map.\n *\n * @private\n * @name delete\n * @memberOf MapCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction mapCacheDelete(key) {\n var result = getMapData(this, key)['delete'](key);\n this.size -= result ? 1 : 0;\n return result;\n}\n\nmodule.exports = mapCacheDelete;\n","var getMapData = require('./_getMapData');\n\n/**\n * Gets the map value for `key`.\n *\n * @private\n * @name get\n * @memberOf MapCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction mapCacheGet(key) {\n return getMapData(this, key).get(key);\n}\n\nmodule.exports = mapCacheGet;\n","var getMapData = require('./_getMapData');\n\n/**\n * Checks if a map value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf MapCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction mapCacheHas(key) {\n return getMapData(this, key).has(key);\n}\n\nmodule.exports = mapCacheHas;\n","var getMapData = require('./_getMapData');\n\n/**\n * Sets the map `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf MapCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the map cache instance.\n */\nfunction mapCacheSet(key, value) {\n var data = getMapData(this, key),\n size = data.size;\n\n data.set(key, value);\n this.size += data.size == size ? 0 : 1;\n return this;\n}\n\nmodule.exports = mapCacheSet;\n","var mapCacheClear = require('./_mapCacheClear'),\n mapCacheDelete = require('./_mapCacheDelete'),\n mapCacheGet = require('./_mapCacheGet'),\n mapCacheHas = require('./_mapCacheHas'),\n mapCacheSet = require('./_mapCacheSet');\n\n/**\n * Creates a map cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction MapCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `MapCache`.\nMapCache.prototype.clear = mapCacheClear;\nMapCache.prototype['delete'] = mapCacheDelete;\nMapCache.prototype.get = mapCacheGet;\nMapCache.prototype.has = mapCacheHas;\nMapCache.prototype.set = mapCacheSet;\n\nmodule.exports = MapCache;\n","var ListCache = require('./_ListCache'),\n Map = require('./_Map'),\n MapCache = require('./_MapCache');\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * Sets the stack `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Stack\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the stack cache instance.\n */\nfunction stackSet(key, value) {\n var data = this.__data__;\n if (data instanceof ListCache) {\n var pairs = data.__data__;\n if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n pairs.push([key, value]);\n this.size = ++data.size;\n return this;\n }\n data = this.__data__ = new MapCache(pairs);\n }\n data.set(key, value);\n this.size = data.size;\n return this;\n}\n\nmodule.exports = stackSet;\n","var ListCache = require('./_ListCache'),\n stackClear = require('./_stackClear'),\n stackDelete = require('./_stackDelete'),\n stackGet = require('./_stackGet'),\n stackHas = require('./_stackHas'),\n stackSet = require('./_stackSet');\n\n/**\n * Creates a stack cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Stack(entries) {\n var data = this.__data__ = new ListCache(entries);\n this.size = data.size;\n}\n\n// Add methods to `Stack`.\nStack.prototype.clear = stackClear;\nStack.prototype['delete'] = stackDelete;\nStack.prototype.get = stackGet;\nStack.prototype.has = stackHas;\nStack.prototype.set = stackSet;\n\nmodule.exports = Stack;\n","var getNative = require('./_getNative');\n\nvar defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n}());\n\nmodule.exports = defineProperty;\n","var defineProperty = require('./_defineProperty');\n\n/**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction baseAssignValue(object, key, value) {\n if (key == '__proto__' && defineProperty) {\n defineProperty(object, key, {\n 'configurable': true,\n 'enumerable': true,\n 'value': value,\n 'writable': true\n });\n } else {\n object[key] = value;\n }\n}\n\nmodule.exports = baseAssignValue;\n","var baseAssignValue = require('./_baseAssignValue'),\n eq = require('./eq');\n\n/**\n * This function is like `assignValue` except that it doesn't assign\n * `undefined` values.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignMergeValue(object, key, value) {\n if ((value !== undefined && !eq(object[key], value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nmodule.exports = assignMergeValue;\n","/**\n * Creates a base function for methods like `_.forIn` and `_.forOwn`.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseFor(fromRight) {\n return function(object, iteratee, keysFunc) {\n var index = -1,\n iterable = Object(object),\n props = keysFunc(object),\n length = props.length;\n\n while (length--) {\n var key = props[fromRight ? length : ++index];\n if (iteratee(iterable[key], key, iterable) === false) {\n break;\n }\n }\n return object;\n };\n}\n\nmodule.exports = createBaseFor;\n","var createBaseFor = require('./_createBaseFor');\n\n/**\n * The base implementation of `baseForOwn` which iterates over `object`\n * properties returned by `keysFunc` and invokes `iteratee` for each property.\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @returns {Object} Returns `object`.\n */\nvar baseFor = createBaseFor();\n\nmodule.exports = baseFor;\n","var root = require('./_root');\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined,\n allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;\n\n/**\n * Creates a clone of `buffer`.\n *\n * @private\n * @param {Buffer} buffer The buffer to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Buffer} Returns the cloned buffer.\n */\nfunction cloneBuffer(buffer, isDeep) {\n if (isDeep) {\n return buffer.slice();\n }\n var length = buffer.length,\n result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);\n\n buffer.copy(result);\n return result;\n}\n\nmodule.exports = cloneBuffer;\n","var root = require('./_root');\n\n/** Built-in value references. */\nvar Uint8Array = root.Uint8Array;\n\nmodule.exports = Uint8Array;\n","var Uint8Array = require('./_Uint8Array');\n\n/**\n * Creates a clone of `arrayBuffer`.\n *\n * @private\n * @param {ArrayBuffer} arrayBuffer The array buffer to clone.\n * @returns {ArrayBuffer} Returns the cloned array buffer.\n */\nfunction cloneArrayBuffer(arrayBuffer) {\n var result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n return result;\n}\n\nmodule.exports = cloneArrayBuffer;\n","var cloneArrayBuffer = require('./_cloneArrayBuffer');\n\n/**\n * Creates a clone of `typedArray`.\n *\n * @private\n * @param {Object} typedArray The typed array to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned typed array.\n */\nfunction cloneTypedArray(typedArray, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n}\n\nmodule.exports = cloneTypedArray;\n","/**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\nfunction copyArray(source, array) {\n var index = -1,\n length = source.length;\n\n array || (array = Array(length));\n while (++index < length) {\n array[index] = source[index];\n }\n return array;\n}\n\nmodule.exports = copyArray;\n","var isObject = require('./isObject');\n\n/** Built-in value references. */\nvar objectCreate = Object.create;\n\n/**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} proto The object to inherit from.\n * @returns {Object} Returns the new object.\n */\nvar baseCreate = (function() {\n function object() {}\n return function(proto) {\n if (!isObject(proto)) {\n return {};\n }\n if (objectCreate) {\n return objectCreate(proto);\n }\n object.prototype = proto;\n var result = new object;\n object.prototype = undefined;\n return result;\n };\n}());\n\nmodule.exports = baseCreate;\n","/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n}\n\nmodule.exports = overArg;\n","var overArg = require('./_overArg');\n\n/** Built-in value references. */\nvar getPrototype = overArg(Object.getPrototypeOf, Object);\n\nmodule.exports = getPrototype;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\nmodule.exports = isPrototype;\n","var baseCreate = require('./_baseCreate'),\n getPrototype = require('./_getPrototype'),\n isPrototype = require('./_isPrototype');\n\n/**\n * Initializes an object clone.\n *\n * @private\n * @param {Object} object The object to clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneObject(object) {\n return (typeof object.constructor == 'function' && !isPrototype(object))\n ? baseCreate(getPrototype(object))\n : {};\n}\n\nmodule.exports = initCloneObject;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nmodule.exports = isObjectLike;\n","var baseGetTag = require('./_baseGetTag'),\n isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]';\n\n/**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\nfunction baseIsArguments(value) {\n return isObjectLike(value) && baseGetTag(value) == argsTag;\n}\n\nmodule.exports = baseIsArguments;\n","var baseIsArguments = require('./_baseIsArguments'),\n isObjectLike = require('./isObjectLike');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nvar isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n !propertyIsEnumerable.call(value, 'callee');\n};\n\nmodule.exports = isArguments;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nmodule.exports = isArray;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nmodule.exports = isLength;\n","var isFunction = require('./isFunction'),\n isLength = require('./isLength');\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\nmodule.exports = isArrayLike;\n","var isArrayLike = require('./isArrayLike'),\n isObjectLike = require('./isObjectLike');\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n}\n\nmodule.exports = isArrayLikeObject;\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nmodule.exports = stubFalse;\n","var root = require('./_root'),\n stubFalse = require('./stubFalse');\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;\n\n/**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\nvar isBuffer = nativeIsBuffer || stubFalse;\n\nmodule.exports = isBuffer;\n","var baseGetTag = require('./_baseGetTag'),\n getPrototype = require('./_getPrototype'),\n isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to infer the `Object` constructor. */\nvar objectCtorString = funcToString.call(Object);\n\n/**\n * Checks if `value` is a plain object, that is, an object created by the\n * `Object` constructor or one with a `[[Prototype]]` of `null`.\n *\n * @static\n * @memberOf _\n * @since 0.8.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * _.isPlainObject(new Foo);\n * // => false\n *\n * _.isPlainObject([1, 2, 3]);\n * // => false\n *\n * _.isPlainObject({ 'x': 0, 'y': 0 });\n * // => true\n *\n * _.isPlainObject(Object.create(null));\n * // => true\n */\nfunction isPlainObject(value) {\n if (!isObjectLike(value) || baseGetTag(value) != objectTag) {\n return false;\n }\n var proto = getPrototype(value);\n if (proto === null) {\n return true;\n }\n var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;\n return typeof Ctor == 'function' && Ctor instanceof Ctor &&\n funcToString.call(Ctor) == objectCtorString;\n}\n\nmodule.exports = isPlainObject;\n","var baseGetTag = require('./_baseGetTag'),\n isLength = require('./isLength'),\n isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\ntypedArrayTags[errorTag] = typedArrayTags[funcTag] =\ntypedArrayTags[mapTag] = typedArrayTags[numberTag] =\ntypedArrayTags[objectTag] = typedArrayTags[regexpTag] =\ntypedArrayTags[setTag] = typedArrayTags[stringTag] =\ntypedArrayTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\nfunction baseIsTypedArray(value) {\n return isObjectLike(value) &&\n isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n}\n\nmodule.exports = baseIsTypedArray;\n","/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n return function(value) {\n return func(value);\n };\n}\n\nmodule.exports = baseUnary;\n","var freeGlobal = require('./_freeGlobal');\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Detect free variable `process` from Node.js. */\nvar freeProcess = moduleExports && freeGlobal.process;\n\n/** Used to access faster Node.js helpers. */\nvar nodeUtil = (function() {\n try {\n // Use `util.types` for Node.js 10+.\n var types = freeModule && freeModule.require && freeModule.require('util').types;\n\n if (types) {\n return types;\n }\n\n // Legacy `process.binding('util')` for Node.js < 10.\n return freeProcess && freeProcess.binding && freeProcess.binding('util');\n } catch (e) {}\n}());\n\nmodule.exports = nodeUtil;\n","var baseIsTypedArray = require('./_baseIsTypedArray'),\n baseUnary = require('./_baseUnary'),\n nodeUtil = require('./_nodeUtil');\n\n/* Node.js helper references. */\nvar nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nvar isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\nmodule.exports = isTypedArray;\n","/**\n * Gets the value at `key`, unless `key` is \"__proto__\" or \"constructor\".\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction safeGet(object, key) {\n if (key === 'constructor' && typeof object[key] === 'function') {\n return;\n }\n\n if (key == '__proto__') {\n return;\n }\n\n return object[key];\n}\n\nmodule.exports = safeGet;\n","var baseAssignValue = require('./_baseAssignValue'),\n eq = require('./eq');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nmodule.exports = assignValue;\n","var assignValue = require('./_assignValue'),\n baseAssignValue = require('./_baseAssignValue');\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n var isNew = !object;\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n if (newValue === undefined) {\n newValue = source[key];\n }\n if (isNew) {\n baseAssignValue(object, key, newValue);\n } else {\n assignValue(object, key, newValue);\n }\n }\n return object;\n}\n\nmodule.exports = copyObject;\n","/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nmodule.exports = baseTimes;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n var type = typeof value;\n length = length == null ? MAX_SAFE_INTEGER : length;\n\n return !!length &&\n (type == 'number' ||\n (type != 'symbol' && reIsUint.test(value))) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\nmodule.exports = isIndex;\n","var baseTimes = require('./_baseTimes'),\n isArguments = require('./isArguments'),\n isArray = require('./isArray'),\n isBuffer = require('./isBuffer'),\n isIndex = require('./_isIndex'),\n isTypedArray = require('./isTypedArray');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n var isArr = isArray(value),\n isArg = !isArr && isArguments(value),\n isBuff = !isArr && !isArg && isBuffer(value),\n isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n skipIndexes = isArr || isArg || isBuff || isType,\n result = skipIndexes ? baseTimes(value.length, String) : [],\n length = result.length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (\n // Safari 9 has enumerable `arguments.length` in strict mode.\n key == 'length' ||\n // Node.js 0.10 has enumerable non-index properties on buffers.\n (isBuff && (key == 'offset' || key == 'parent')) ||\n // PhantomJS 2 has enumerable non-index properties on typed arrays.\n (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n // Skip index properties.\n isIndex(key, length)\n ))) {\n result.push(key);\n }\n }\n return result;\n}\n\nmodule.exports = arrayLikeKeys;\n","/**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction nativeKeysIn(object) {\n var result = [];\n if (object != null) {\n for (var key in Object(object)) {\n result.push(key);\n }\n }\n return result;\n}\n\nmodule.exports = nativeKeysIn;\n","var isObject = require('./isObject'),\n isPrototype = require('./_isPrototype'),\n nativeKeysIn = require('./_nativeKeysIn');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeysIn(object) {\n if (!isObject(object)) {\n return nativeKeysIn(object);\n }\n var isProto = isPrototype(object),\n result = [];\n\n for (var key in object) {\n if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n result.push(key);\n }\n }\n return result;\n}\n\nmodule.exports = baseKeysIn;\n","var arrayLikeKeys = require('./_arrayLikeKeys'),\n baseKeysIn = require('./_baseKeysIn'),\n isArrayLike = require('./isArrayLike');\n\n/**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\nfunction keysIn(object) {\n return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n}\n\nmodule.exports = keysIn;\n","var copyObject = require('./_copyObject'),\n keysIn = require('./keysIn');\n\n/**\n * Converts `value` to a plain object flattening inherited enumerable string\n * keyed properties of `value` to own properties of the plain object.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {Object} Returns the converted plain object.\n * @example\n *\n * function Foo() {\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.assign({ 'a': 1 }, new Foo);\n * // => { 'a': 1, 'b': 2 }\n *\n * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));\n * // => { 'a': 1, 'b': 2, 'c': 3 }\n */\nfunction toPlainObject(value) {\n return copyObject(value, keysIn(value));\n}\n\nmodule.exports = toPlainObject;\n","var assignMergeValue = require('./_assignMergeValue'),\n cloneBuffer = require('./_cloneBuffer'),\n cloneTypedArray = require('./_cloneTypedArray'),\n copyArray = require('./_copyArray'),\n initCloneObject = require('./_initCloneObject'),\n isArguments = require('./isArguments'),\n isArray = require('./isArray'),\n isArrayLikeObject = require('./isArrayLikeObject'),\n isBuffer = require('./isBuffer'),\n isFunction = require('./isFunction'),\n isObject = require('./isObject'),\n isPlainObject = require('./isPlainObject'),\n isTypedArray = require('./isTypedArray'),\n safeGet = require('./_safeGet'),\n toPlainObject = require('./toPlainObject');\n\n/**\n * A specialized version of `baseMerge` for arrays and objects which performs\n * deep merges and tracks traversed objects enabling objects with circular\n * references to be merged.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {string} key The key of the value to merge.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} mergeFunc The function to merge values.\n * @param {Function} [customizer] The function to customize assigned values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\nfunction baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {\n var objValue = safeGet(object, key),\n srcValue = safeGet(source, key),\n stacked = stack.get(srcValue);\n\n if (stacked) {\n assignMergeValue(object, key, stacked);\n return;\n }\n var newValue = customizer\n ? customizer(objValue, srcValue, (key + ''), object, source, stack)\n : undefined;\n\n var isCommon = newValue === undefined;\n\n if (isCommon) {\n var isArr = isArray(srcValue),\n isBuff = !isArr && isBuffer(srcValue),\n isTyped = !isArr && !isBuff && isTypedArray(srcValue);\n\n newValue = srcValue;\n if (isArr || isBuff || isTyped) {\n if (isArray(objValue)) {\n newValue = objValue;\n }\n else if (isArrayLikeObject(objValue)) {\n newValue = copyArray(objValue);\n }\n else if (isBuff) {\n isCommon = false;\n newValue = cloneBuffer(srcValue, true);\n }\n else if (isTyped) {\n isCommon = false;\n newValue = cloneTypedArray(srcValue, true);\n }\n else {\n newValue = [];\n }\n }\n else if (isPlainObject(srcValue) || isArguments(srcValue)) {\n newValue = objValue;\n if (isArguments(objValue)) {\n newValue = toPlainObject(objValue);\n }\n else if (!isObject(objValue) || isFunction(objValue)) {\n newValue = initCloneObject(srcValue);\n }\n }\n else {\n isCommon = false;\n }\n }\n if (isCommon) {\n // Recursively merge objects and arrays (susceptible to call stack limits).\n stack.set(srcValue, newValue);\n mergeFunc(newValue, srcValue, srcIndex, customizer, stack);\n stack['delete'](srcValue);\n }\n assignMergeValue(object, key, newValue);\n}\n\nmodule.exports = baseMergeDeep;\n","var Stack = require('./_Stack'),\n assignMergeValue = require('./_assignMergeValue'),\n baseFor = require('./_baseFor'),\n baseMergeDeep = require('./_baseMergeDeep'),\n isObject = require('./isObject'),\n keysIn = require('./keysIn'),\n safeGet = require('./_safeGet');\n\n/**\n * The base implementation of `_.merge` without support for multiple sources.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} [customizer] The function to customize merged values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\nfunction baseMerge(object, source, srcIndex, customizer, stack) {\n if (object === source) {\n return;\n }\n baseFor(source, function(srcValue, key) {\n stack || (stack = new Stack);\n if (isObject(srcValue)) {\n baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);\n }\n else {\n var newValue = customizer\n ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)\n : undefined;\n\n if (newValue === undefined) {\n newValue = srcValue;\n }\n assignMergeValue(object, key, newValue);\n }\n }, keysIn);\n}\n\nmodule.exports = baseMerge;\n","/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nmodule.exports = identity;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nmodule.exports = apply;\n","var apply = require('./_apply');\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n}\n\nmodule.exports = overRest;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nmodule.exports = constant;\n","var constant = require('./constant'),\n defineProperty = require('./_defineProperty'),\n identity = require('./identity');\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n};\n\nmodule.exports = baseSetToString;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nmodule.exports = shortOut;\n","var baseSetToString = require('./_baseSetToString'),\n shortOut = require('./_shortOut');\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nmodule.exports = setToString;\n","var identity = require('./identity'),\n overRest = require('./_overRest'),\n setToString = require('./_setToString');\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n}\n\nmodule.exports = baseRest;\n","var eq = require('./eq'),\n isArrayLike = require('./isArrayLike'),\n isIndex = require('./_isIndex'),\n isObject = require('./isObject');\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n}\n\nmodule.exports = isIterateeCall;\n","var baseRest = require('./_baseRest'),\n isIterateeCall = require('./_isIterateeCall');\n\n/**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\nfunction createAssigner(assigner) {\n return baseRest(function(object, sources) {\n var index = -1,\n length = sources.length,\n customizer = length > 1 ? sources[length - 1] : undefined,\n guard = length > 2 ? sources[2] : undefined;\n\n customizer = (assigner.length > 3 && typeof customizer == 'function')\n ? (length--, customizer)\n : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n customizer = length < 3 ? undefined : customizer;\n length = 1;\n }\n object = Object(object);\n while (++index < length) {\n var source = sources[index];\n if (source) {\n assigner(object, source, index, customizer);\n }\n }\n return object;\n });\n}\n\nmodule.exports = createAssigner;\n","var baseMerge = require('./_baseMerge'),\n createAssigner = require('./_createAssigner');\n\n/**\n * This method is like `_.assign` except that it recursively merges own and\n * inherited enumerable string keyed properties of source objects into the\n * destination object. Source properties that resolve to `undefined` are\n * skipped if a destination value exists. Array and plain object properties\n * are merged recursively. Other objects and value types are overridden by\n * assignment. Source objects are applied from left to right. Subsequent\n * sources overwrite property assignments of previous sources.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 0.5.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {\n * 'a': [{ 'b': 2 }, { 'd': 4 }]\n * };\n *\n * var other = {\n * 'a': [{ 'c': 3 }, { 'e': 5 }]\n * };\n *\n * _.merge(object, other);\n * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }\n */\nvar merge = createAssigner(function(object, source, srcIndex) {\n baseMerge(object, source, srcIndex);\n});\n\nmodule.exports = merge;\n","var baseGetTag = require('./_baseGetTag'),\n isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && baseGetTag(value) == symbolTag);\n}\n\nmodule.exports = isSymbol;\n","var isArray = require('./isArray'),\n isSymbol = require('./isSymbol');\n\n/** Used to match property names within property paths. */\nvar reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,\n reIsPlainProp = /^\\w*$/;\n\n/**\n * Checks if `value` is a property name and not a property path.\n *\n * @private\n * @param {*} value The value to check.\n * @param {Object} [object] The object to query keys on.\n * @returns {boolean} Returns `true` if `value` is a property name, else `false`.\n */\nfunction isKey(value, object) {\n if (isArray(value)) {\n return false;\n }\n var type = typeof value;\n if (type == 'number' || type == 'symbol' || type == 'boolean' ||\n value == null || isSymbol(value)) {\n return true;\n }\n return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||\n (object != null && value in Object(object));\n}\n\nmodule.exports = isKey;\n","var MapCache = require('./_MapCache');\n\n/** Error message constants. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/**\n * Creates a function that memoizes the result of `func`. If `resolver` is\n * provided, it determines the cache key for storing the result based on the\n * arguments provided to the memoized function. By default, the first argument\n * provided to the memoized function is used as the map cache key. The `func`\n * is invoked with the `this` binding of the memoized function.\n *\n * **Note:** The cache is exposed as the `cache` property on the memoized\n * function. Its creation may be customized by replacing the `_.memoize.Cache`\n * constructor with one whose instances implement the\n * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)\n * method interface of `clear`, `delete`, `get`, `has`, and `set`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to have its output memoized.\n * @param {Function} [resolver] The function to resolve the cache key.\n * @returns {Function} Returns the new memoized function.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n * var other = { 'c': 3, 'd': 4 };\n *\n * var values = _.memoize(_.values);\n * values(object);\n * // => [1, 2]\n *\n * values(other);\n * // => [3, 4]\n *\n * object.a = 2;\n * values(object);\n * // => [1, 2]\n *\n * // Modify the result cache.\n * values.cache.set(object, ['a', 'b']);\n * values(object);\n * // => ['a', 'b']\n *\n * // Replace `_.memoize.Cache`.\n * _.memoize.Cache = WeakMap;\n */\nfunction memoize(func, resolver) {\n if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n var memoized = function() {\n var args = arguments,\n key = resolver ? resolver.apply(this, args) : args[0],\n cache = memoized.cache;\n\n if (cache.has(key)) {\n return cache.get(key);\n }\n var result = func.apply(this, args);\n memoized.cache = cache.set(key, result) || cache;\n return result;\n };\n memoized.cache = new (memoize.Cache || MapCache);\n return memoized;\n}\n\n// Expose `MapCache`.\nmemoize.Cache = MapCache;\n\nmodule.exports = memoize;\n","var memoize = require('./memoize');\n\n/** Used as the maximum memoize cache size. */\nvar MAX_MEMOIZE_SIZE = 500;\n\n/**\n * A specialized version of `_.memoize` which clears the memoized function's\n * cache when it exceeds `MAX_MEMOIZE_SIZE`.\n *\n * @private\n * @param {Function} func The function to have its output memoized.\n * @returns {Function} Returns the new memoized function.\n */\nfunction memoizeCapped(func) {\n var result = memoize(func, function(key) {\n if (cache.size === MAX_MEMOIZE_SIZE) {\n cache.clear();\n }\n return key;\n });\n\n var cache = result.cache;\n return result;\n}\n\nmodule.exports = memoizeCapped;\n","var memoizeCapped = require('./_memoizeCapped');\n\n/** Used to match property names within property paths. */\nvar rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g;\n\n/** Used to match backslashes in property paths. */\nvar reEscapeChar = /\\\\(\\\\)?/g;\n\n/**\n * Converts `string` to a property path array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the property path array.\n */\nvar stringToPath = memoizeCapped(function(string) {\n var result = [];\n if (string.charCodeAt(0) === 46 /* . */) {\n result.push('');\n }\n string.replace(rePropName, function(match, number, quote, subString) {\n result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));\n });\n return result;\n});\n\nmodule.exports = stringToPath;\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nmodule.exports = arrayMap;\n","var Symbol = require('./_Symbol'),\n arrayMap = require('./_arrayMap'),\n isArray = require('./isArray'),\n isSymbol = require('./isSymbol');\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolToString = symbolProto ? symbolProto.toString : undefined;\n\n/**\n * The base implementation of `_.toString` which doesn't convert nullish\n * values to empty strings.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\nfunction baseToString(value) {\n // Exit early for strings to avoid a performance hit in some environments.\n if (typeof value == 'string') {\n return value;\n }\n if (isArray(value)) {\n // Recursively convert values (susceptible to call stack limits).\n return arrayMap(value, baseToString) + '';\n }\n if (isSymbol(value)) {\n return symbolToString ? symbolToString.call(value) : '';\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nmodule.exports = baseToString;\n","var baseToString = require('./_baseToString');\n\n/**\n * Converts `value` to a string. An empty string is returned for `null`\n * and `undefined` values. The sign of `-0` is preserved.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.toString(null);\n * // => ''\n *\n * _.toString(-0);\n * // => '-0'\n *\n * _.toString([1, 2, 3]);\n * // => '1,2,3'\n */\nfunction toString(value) {\n return value == null ? '' : baseToString(value);\n}\n\nmodule.exports = toString;\n","var isArray = require('./isArray'),\n isKey = require('./_isKey'),\n stringToPath = require('./_stringToPath'),\n toString = require('./toString');\n\n/**\n * Casts `value` to a path array if it's not one.\n *\n * @private\n * @param {*} value The value to inspect.\n * @param {Object} [object] The object to query keys on.\n * @returns {Array} Returns the cast property path array.\n */\nfunction castPath(value, object) {\n if (isArray(value)) {\n return value;\n }\n return isKey(value, object) ? [value] : stringToPath(toString(value));\n}\n\nmodule.exports = castPath;\n","var isSymbol = require('./isSymbol');\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Converts `value` to a string key if it's not a string or symbol.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {string|symbol} Returns the key.\n */\nfunction toKey(value) {\n if (typeof value == 'string' || isSymbol(value)) {\n return value;\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nmodule.exports = toKey;\n","var castPath = require('./_castPath'),\n toKey = require('./_toKey');\n\n/**\n * The base implementation of `_.get` without support for default values.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @returns {*} Returns the resolved value.\n */\nfunction baseGet(object, path) {\n path = castPath(path, object);\n\n var index = 0,\n length = path.length;\n\n while (object != null && index < length) {\n object = object[toKey(path[index++])];\n }\n return (index && index == length) ? object : undefined;\n}\n\nmodule.exports = baseGet;\n","var baseGet = require('./_baseGet');\n\n/**\n * Gets the value at `path` of `object`. If the resolved value is\n * `undefined`, the `defaultValue` is returned in its place.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @param {*} [defaultValue] The value returned for `undefined` resolved values.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.get(object, 'a[0].b.c');\n * // => 3\n *\n * _.get(object, ['a', '0', 'b', 'c']);\n * // => 3\n *\n * _.get(object, 'a.b.c', 'default');\n * // => 'default'\n */\nfunction get(object, path, defaultValue) {\n var result = object == null ? undefined : baseGet(object, path);\n return result === undefined ? defaultValue : result;\n}\n\nmodule.exports = get;\n","!function(t,i){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=i():\"function\"==typeof define&&define.amd?define(i):(t=t||self).RBush=i()}(this,function(){\"use strict\";function t(t,r,e,a,h){!function t(n,r,e,a,h){for(;a>e;){if(a-e>600){var o=a-e+1,s=r-e+1,l=Math.log(o),f=.5*Math.exp(2*l/3),u=.5*Math.sqrt(l*f*(o-f)/o)*(s-o/2<0?-1:1),m=Math.max(e,Math.floor(r-s*f/o+u)),c=Math.min(a,Math.floor(r+(o-s)*f/o+u));t(n,r,m,c,h)}var p=n[r],d=e,x=a;for(i(n,e,r),h(n[a],p)>0&&i(n,e,a);d
0;)x--}0===h(n[e],p)?i(n,e,x):i(n,++x,a),x<=r&&(e=x+1),r<=x&&(a=x-1)}}(t,r,e||0,a||t.length-1,h||n)}function i(t,i,n){var r=t[i];t[i]=t[n],t[n]=r}function n(t,i){return ti?1:0}var r=function(t){void 0===t&&(t=9),this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(.4*this._maxEntries)),this.clear()};function e(t,i,n){if(!n)return i.indexOf(t);for(var r=0;r=t.minX&&i.maxY>=t.minY}function p(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function d(i,n,r,e,a){for(var h=[n,r];h.length;)if(!((r=h.pop())-(n=h.pop())<=e)){var o=n+Math.ceil((r-n)/e/2)*e;t(i,o,n,r,a),h.push(n,o,o,r)}}return r.prototype.all=function(){return this._all(this.data,[])},r.prototype.search=function(t){var i=this.data,n=[];if(!c(t,i))return n;for(var r=this.toBBox,e=[];i;){for(var a=0;a=0&&e[i].children.length>this._maxEntries;)this._split(e,i),i--;this._adjustParentBBoxes(r,e,i)},r.prototype._split=function(t,i){var n=t[i],r=n.children.length,e=this._minEntries;this._chooseSplitAxis(n,e,r);var h=this._chooseSplitIndex(n,e,r),o=p(n.children.splice(h,n.children.length-h));o.height=n.height,o.leaf=n.leaf,a(n,this.toBBox),a(o,this.toBBox),i?t[i-1].children.push(o):this._splitRoot(n,o)},r.prototype._splitRoot=function(t,i){this.data=p([t,i]),this.data.height=t.height+1,this.data.leaf=!1,a(this.data,this.toBBox)},r.prototype._chooseSplitIndex=function(t,i,n){for(var r,e,a,o,s,l,u,m=1/0,c=1/0,p=i;p<=n-i;p++){var d=h(t,0,p,this.toBBox),x=h(t,p,n,this.toBBox),v=(e=d,a=x,o=void 0,s=void 0,l=void 0,u=void 0,o=Math.max(e.minX,a.minX),s=Math.max(e.minY,a.minY),l=Math.min(e.maxX,a.maxX),u=Math.min(e.maxY,a.maxY),Math.max(0,l-o)*Math.max(0,u-s)),M=f(d)+f(x);v=i;c--){var p=t.children[c];o(s,t.leaf?e(p):p),l+=u(s)}return l},r.prototype._adjustParentBBoxes=function(t,i,n){for(var r=n;r>=0;r--)o(i[r],t)},r.prototype._condense=function(t){for(var i=t.length-1,n=void 0;i>=0;i--)0===t[i].children.length?i>0?(n=t[i-1].children).splice(n.indexOf(t[i]),1):this.clear():a(t[i],this.toBBox)},r});\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n/**\n * @module helpers\n */\n/**\n * Earth Radius used with the Harvesine formula and approximates using a spherical (non-ellipsoid) Earth.\n *\n * @memberof helpers\n * @type {number}\n */\nexports.earthRadius = 6371008.8;\n/**\n * Unit of measurement factors using a spherical (non-ellipsoid) earth radius.\n *\n * @memberof helpers\n * @type {Object}\n */\nexports.factors = {\n centimeters: exports.earthRadius * 100,\n centimetres: exports.earthRadius * 100,\n degrees: exports.earthRadius / 111325,\n feet: exports.earthRadius * 3.28084,\n inches: exports.earthRadius * 39.37,\n kilometers: exports.earthRadius / 1000,\n kilometres: exports.earthRadius / 1000,\n meters: exports.earthRadius,\n metres: exports.earthRadius,\n miles: exports.earthRadius / 1609.344,\n millimeters: exports.earthRadius * 1000,\n millimetres: exports.earthRadius * 1000,\n nauticalmiles: exports.earthRadius / 1852,\n radians: 1,\n yards: exports.earthRadius * 1.0936,\n};\n/**\n * Units of measurement factors based on 1 meter.\n *\n * @memberof helpers\n * @type {Object}\n */\nexports.unitsFactors = {\n centimeters: 100,\n centimetres: 100,\n degrees: 1 / 111325,\n feet: 3.28084,\n inches: 39.37,\n kilometers: 1 / 1000,\n kilometres: 1 / 1000,\n meters: 1,\n metres: 1,\n miles: 1 / 1609.344,\n millimeters: 1000,\n millimetres: 1000,\n nauticalmiles: 1 / 1852,\n radians: 1 / exports.earthRadius,\n yards: 1.0936133,\n};\n/**\n * Area of measurement factors based on 1 square meter.\n *\n * @memberof helpers\n * @type {Object}\n */\nexports.areaFactors = {\n acres: 0.000247105,\n centimeters: 10000,\n centimetres: 10000,\n feet: 10.763910417,\n hectares: 0.0001,\n inches: 1550.003100006,\n kilometers: 0.000001,\n kilometres: 0.000001,\n meters: 1,\n metres: 1,\n miles: 3.86e-7,\n millimeters: 1000000,\n millimetres: 1000000,\n yards: 1.195990046,\n};\n/**\n * Wraps a GeoJSON {@link Geometry} in a GeoJSON {@link Feature}.\n *\n * @name feature\n * @param {Geometry} geometry input geometry\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a GeoJSON Feature\n * @example\n * var geometry = {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 50]\n * };\n *\n * var feature = turf.feature(geometry);\n *\n * //=feature\n */\nfunction feature(geom, properties, options) {\n if (options === void 0) { options = {}; }\n var feat = { type: \"Feature\" };\n if (options.id === 0 || options.id) {\n feat.id = options.id;\n }\n if (options.bbox) {\n feat.bbox = options.bbox;\n }\n feat.properties = properties || {};\n feat.geometry = geom;\n return feat;\n}\nexports.feature = feature;\n/**\n * Creates a GeoJSON {@link Geometry} from a Geometry string type & coordinates.\n * For GeometryCollection type use `helpers.geometryCollection`\n *\n * @name geometry\n * @param {string} type Geometry Type\n * @param {Array} coordinates Coordinates\n * @param {Object} [options={}] Optional Parameters\n * @returns {Geometry} a GeoJSON Geometry\n * @example\n * var type = \"Point\";\n * var coordinates = [110, 50];\n * var geometry = turf.geometry(type, coordinates);\n * // => geometry\n */\nfunction geometry(type, coordinates, _options) {\n if (_options === void 0) { _options = {}; }\n switch (type) {\n case \"Point\":\n return point(coordinates).geometry;\n case \"LineString\":\n return lineString(coordinates).geometry;\n case \"Polygon\":\n return polygon(coordinates).geometry;\n case \"MultiPoint\":\n return multiPoint(coordinates).geometry;\n case \"MultiLineString\":\n return multiLineString(coordinates).geometry;\n case \"MultiPolygon\":\n return multiPolygon(coordinates).geometry;\n default:\n throw new Error(type + \" is invalid\");\n }\n}\nexports.geometry = geometry;\n/**\n * Creates a {@link Point} {@link Feature} from a Position.\n *\n * @name point\n * @param {Array} coordinates longitude, latitude position (each in decimal degrees)\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a Point feature\n * @example\n * var point = turf.point([-75.343, 39.984]);\n *\n * //=point\n */\nfunction point(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n if (!coordinates) {\n throw new Error(\"coordinates is required\");\n }\n if (!Array.isArray(coordinates)) {\n throw new Error(\"coordinates must be an Array\");\n }\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be at least 2 numbers long\");\n }\n if (!isNumber(coordinates[0]) || !isNumber(coordinates[1])) {\n throw new Error(\"coordinates must contain numbers\");\n }\n var geom = {\n type: \"Point\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\nexports.point = point;\n/**\n * Creates a {@link Point} {@link FeatureCollection} from an Array of Point coordinates.\n *\n * @name points\n * @param {Array>} coordinates an array of Points\n * @param {Object} [properties={}] Translate these properties to each Feature\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north]\n * associated with the FeatureCollection\n * @param {string|number} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection} Point Feature\n * @example\n * var points = turf.points([\n * [-75, 39],\n * [-80, 45],\n * [-78, 50]\n * ]);\n *\n * //=points\n */\nfunction points(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n return featureCollection(coordinates.map(function (coords) {\n return point(coords, properties);\n }), options);\n}\nexports.points = points;\n/**\n * Creates a {@link Polygon} {@link Feature} from an Array of LinearRings.\n *\n * @name polygon\n * @param {Array>>} coordinates an array of LinearRings\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} Polygon Feature\n * @example\n * var polygon = turf.polygon([[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]], { name: 'poly1' });\n *\n * //=polygon\n */\nfunction polygon(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n for (var _i = 0, coordinates_1 = coordinates; _i < coordinates_1.length; _i++) {\n var ring = coordinates_1[_i];\n if (ring.length < 4) {\n throw new Error(\"Each LinearRing of a Polygon must have 4 or more Positions.\");\n }\n for (var j = 0; j < ring[ring.length - 1].length; j++) {\n // Check if first point of Polygon contains two numbers\n if (ring[ring.length - 1][j] !== ring[0][j]) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n }\n }\n var geom = {\n type: \"Polygon\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\nexports.polygon = polygon;\n/**\n * Creates a {@link Polygon} {@link FeatureCollection} from an Array of Polygon coordinates.\n *\n * @name polygons\n * @param {Array>>>} coordinates an array of Polygon coordinates\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection} Polygon FeatureCollection\n * @example\n * var polygons = turf.polygons([\n * [[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]],\n * [[[-15, 42], [-14, 46], [-12, 41], [-17, 44], [-15, 42]]],\n * ]);\n *\n * //=polygons\n */\nfunction polygons(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n return featureCollection(coordinates.map(function (coords) {\n return polygon(coords, properties);\n }), options);\n}\nexports.polygons = polygons;\n/**\n * Creates a {@link LineString} {@link Feature} from an Array of Positions.\n *\n * @name lineString\n * @param {Array>} coordinates an array of Positions\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} LineString Feature\n * @example\n * var linestring1 = turf.lineString([[-24, 63], [-23, 60], [-25, 65], [-20, 69]], {name: 'line 1'});\n * var linestring2 = turf.lineString([[-14, 43], [-13, 40], [-15, 45], [-10, 49]], {name: 'line 2'});\n *\n * //=linestring1\n * //=linestring2\n */\nfunction lineString(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be an array of two or more positions\");\n }\n var geom = {\n type: \"LineString\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\nexports.lineString = lineString;\n/**\n * Creates a {@link LineString} {@link FeatureCollection} from an Array of LineString coordinates.\n *\n * @name lineStrings\n * @param {Array>>} coordinates an array of LinearRings\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north]\n * associated with the FeatureCollection\n * @param {string|number} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection} LineString FeatureCollection\n * @example\n * var linestrings = turf.lineStrings([\n * [[-24, 63], [-23, 60], [-25, 65], [-20, 69]],\n * [[-14, 43], [-13, 40], [-15, 45], [-10, 49]]\n * ]);\n *\n * //=linestrings\n */\nfunction lineStrings(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n return featureCollection(coordinates.map(function (coords) {\n return lineString(coords, properties);\n }), options);\n}\nexports.lineStrings = lineStrings;\n/**\n * Takes one or more {@link Feature|Features} and creates a {@link FeatureCollection}.\n *\n * @name featureCollection\n * @param {Feature[]} features input features\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {FeatureCollection} FeatureCollection of Features\n * @example\n * var locationA = turf.point([-75.343, 39.984], {name: 'Location A'});\n * var locationB = turf.point([-75.833, 39.284], {name: 'Location B'});\n * var locationC = turf.point([-75.534, 39.123], {name: 'Location C'});\n *\n * var collection = turf.featureCollection([\n * locationA,\n * locationB,\n * locationC\n * ]);\n *\n * //=collection\n */\nfunction featureCollection(features, options) {\n if (options === void 0) { options = {}; }\n var fc = { type: \"FeatureCollection\" };\n if (options.id) {\n fc.id = options.id;\n }\n if (options.bbox) {\n fc.bbox = options.bbox;\n }\n fc.features = features;\n return fc;\n}\nexports.featureCollection = featureCollection;\n/**\n * Creates a {@link Feature} based on a\n * coordinate array. Properties can be added optionally.\n *\n * @name multiLineString\n * @param {Array>>} coordinates an array of LineStrings\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a MultiLineString feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiLine = turf.multiLineString([[[0,0],[10,10]]]);\n *\n * //=multiLine\n */\nfunction multiLineString(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n var geom = {\n type: \"MultiLineString\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\nexports.multiLineString = multiLineString;\n/**\n * Creates a {@link Feature} based on a\n * coordinate array. Properties can be added optionally.\n *\n * @name multiPoint\n * @param {Array>} coordinates an array of Positions\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a MultiPoint feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiPt = turf.multiPoint([[0,0],[10,10]]);\n *\n * //=multiPt\n */\nfunction multiPoint(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n var geom = {\n type: \"MultiPoint\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\nexports.multiPoint = multiPoint;\n/**\n * Creates a {@link Feature} based on a\n * coordinate array. Properties can be added optionally.\n *\n * @name multiPolygon\n * @param {Array>>>} coordinates an array of Polygons\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a multipolygon feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiPoly = turf.multiPolygon([[[[0,0],[0,10],[10,10],[10,0],[0,0]]]]);\n *\n * //=multiPoly\n *\n */\nfunction multiPolygon(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n var geom = {\n type: \"MultiPolygon\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\nexports.multiPolygon = multiPolygon;\n/**\n * Creates a {@link Feature} based on a\n * coordinate array. Properties can be added optionally.\n *\n * @name geometryCollection\n * @param {Array} geometries an array of GeoJSON Geometries\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a GeoJSON GeometryCollection Feature\n * @example\n * var pt = turf.geometry(\"Point\", [100, 0]);\n * var line = turf.geometry(\"LineString\", [[101, 0], [102, 1]]);\n * var collection = turf.geometryCollection([pt, line]);\n *\n * // => collection\n */\nfunction geometryCollection(geometries, properties, options) {\n if (options === void 0) { options = {}; }\n var geom = {\n type: \"GeometryCollection\",\n geometries: geometries,\n };\n return feature(geom, properties, options);\n}\nexports.geometryCollection = geometryCollection;\n/**\n * Round number to precision\n *\n * @param {number} num Number\n * @param {number} [precision=0] Precision\n * @returns {number} rounded number\n * @example\n * turf.round(120.4321)\n * //=120\n *\n * turf.round(120.4321, 2)\n * //=120.43\n */\nfunction round(num, precision) {\n if (precision === void 0) { precision = 0; }\n if (precision && !(precision >= 0)) {\n throw new Error(\"precision must be a positive number\");\n }\n var multiplier = Math.pow(10, precision || 0);\n return Math.round(num * multiplier) / multiplier;\n}\nexports.round = round;\n/**\n * Convert a distance measurement (assuming a spherical Earth) from radians to a more friendly unit.\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet\n *\n * @name radiansToLength\n * @param {number} radians in radians across the sphere\n * @param {string} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} distance\n */\nfunction radiansToLength(radians, units) {\n if (units === void 0) { units = \"kilometers\"; }\n var factor = exports.factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return radians * factor;\n}\nexports.radiansToLength = radiansToLength;\n/**\n * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into radians\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet\n *\n * @name lengthToRadians\n * @param {number} distance in real units\n * @param {string} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} radians\n */\nfunction lengthToRadians(distance, units) {\n if (units === void 0) { units = \"kilometers\"; }\n var factor = exports.factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return distance / factor;\n}\nexports.lengthToRadians = lengthToRadians;\n/**\n * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into degrees\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, centimeters, kilometres, feet\n *\n * @name lengthToDegrees\n * @param {number} distance in real units\n * @param {string} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} degrees\n */\nfunction lengthToDegrees(distance, units) {\n return radiansToDegrees(lengthToRadians(distance, units));\n}\nexports.lengthToDegrees = lengthToDegrees;\n/**\n * Converts any bearing angle from the north line direction (positive clockwise)\n * and returns an angle between 0-360 degrees (positive clockwise), 0 being the north line\n *\n * @name bearingToAzimuth\n * @param {number} bearing angle, between -180 and +180 degrees\n * @returns {number} angle between 0 and 360 degrees\n */\nfunction bearingToAzimuth(bearing) {\n var angle = bearing % 360;\n if (angle < 0) {\n angle += 360;\n }\n return angle;\n}\nexports.bearingToAzimuth = bearingToAzimuth;\n/**\n * Converts an angle in radians to degrees\n *\n * @name radiansToDegrees\n * @param {number} radians angle in radians\n * @returns {number} degrees between 0 and 360 degrees\n */\nfunction radiansToDegrees(radians) {\n var degrees = radians % (2 * Math.PI);\n return (degrees * 180) / Math.PI;\n}\nexports.radiansToDegrees = radiansToDegrees;\n/**\n * Converts an angle in degrees to radians\n *\n * @name degreesToRadians\n * @param {number} degrees angle between 0 and 360 degrees\n * @returns {number} angle in radians\n */\nfunction degreesToRadians(degrees) {\n var radians = degrees % 360;\n return (radians * Math.PI) / 180;\n}\nexports.degreesToRadians = degreesToRadians;\n/**\n * Converts a length to the requested unit.\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet\n *\n * @param {number} length to be converted\n * @param {Units} [originalUnit=\"kilometers\"] of the length\n * @param {Units} [finalUnit=\"kilometers\"] returned unit\n * @returns {number} the converted length\n */\nfunction convertLength(length, originalUnit, finalUnit) {\n if (originalUnit === void 0) { originalUnit = \"kilometers\"; }\n if (finalUnit === void 0) { finalUnit = \"kilometers\"; }\n if (!(length >= 0)) {\n throw new Error(\"length must be a positive number\");\n }\n return radiansToLength(lengthToRadians(length, originalUnit), finalUnit);\n}\nexports.convertLength = convertLength;\n/**\n * Converts a area to the requested unit.\n * Valid units: kilometers, kilometres, meters, metres, centimetres, millimeters, acres, miles, yards, feet, inches, hectares\n * @param {number} area to be converted\n * @param {Units} [originalUnit=\"meters\"] of the distance\n * @param {Units} [finalUnit=\"kilometers\"] returned unit\n * @returns {number} the converted area\n */\nfunction convertArea(area, originalUnit, finalUnit) {\n if (originalUnit === void 0) { originalUnit = \"meters\"; }\n if (finalUnit === void 0) { finalUnit = \"kilometers\"; }\n if (!(area >= 0)) {\n throw new Error(\"area must be a positive number\");\n }\n var startFactor = exports.areaFactors[originalUnit];\n if (!startFactor) {\n throw new Error(\"invalid original units\");\n }\n var finalFactor = exports.areaFactors[finalUnit];\n if (!finalFactor) {\n throw new Error(\"invalid final units\");\n }\n return (area / startFactor) * finalFactor;\n}\nexports.convertArea = convertArea;\n/**\n * isNumber\n *\n * @param {*} num Number to validate\n * @returns {boolean} true/false\n * @example\n * turf.isNumber(123)\n * //=true\n * turf.isNumber('foo')\n * //=false\n */\nfunction isNumber(num) {\n return !isNaN(num) && num !== null && !Array.isArray(num);\n}\nexports.isNumber = isNumber;\n/**\n * isObject\n *\n * @param {*} input variable to validate\n * @returns {boolean} true/false\n * @example\n * turf.isObject({elevation: 10})\n * //=true\n * turf.isObject('foo')\n * //=false\n */\nfunction isObject(input) {\n return !!input && input.constructor === Object;\n}\nexports.isObject = isObject;\n/**\n * Validate BBox\n *\n * @private\n * @param {Array} bbox BBox to validate\n * @returns {void}\n * @throws Error if BBox is not valid\n * @example\n * validateBBox([-180, -40, 110, 50])\n * //=OK\n * validateBBox([-180, -40])\n * //=Error\n * validateBBox('Foo')\n * //=Error\n * validateBBox(5)\n * //=Error\n * validateBBox(null)\n * //=Error\n * validateBBox(undefined)\n * //=Error\n */\nfunction validateBBox(bbox) {\n if (!bbox) {\n throw new Error(\"bbox is required\");\n }\n if (!Array.isArray(bbox)) {\n throw new Error(\"bbox must be an Array\");\n }\n if (bbox.length !== 4 && bbox.length !== 6) {\n throw new Error(\"bbox must be an Array of 4 or 6 numbers\");\n }\n bbox.forEach(function (num) {\n if (!isNumber(num)) {\n throw new Error(\"bbox must only contain numbers\");\n }\n });\n}\nexports.validateBBox = validateBBox;\n/**\n * Validate Id\n *\n * @private\n * @param {string|number} id Id to validate\n * @returns {void}\n * @throws Error if Id is not valid\n * @example\n * validateId([-180, -40, 110, 50])\n * //=Error\n * validateId([-180, -40])\n * //=Error\n * validateId('Foo')\n * //=OK\n * validateId(5)\n * //=OK\n * validateId(null)\n * //=Error\n * validateId(undefined)\n * //=Error\n */\nfunction validateId(id) {\n if (!id) {\n throw new Error(\"id is required\");\n }\n if ([\"string\", \"number\"].indexOf(typeof id) === -1) {\n throw new Error(\"id must be a number or a string\");\n }\n}\nexports.validateId = validateId;\n","'use strict';\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\nvar helpers = require('@turf/helpers');\n\n/**\n * Callback for coordEach\n *\n * @callback coordEachCallback\n * @param {Array} currentCoord The current coordinate being processed.\n * @param {number} coordIndex The current index of the coordinate being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n * @param {number} geometryIndex The current index of the Geometry being processed.\n */\n\n/**\n * Iterate over coordinates in any GeoJSON object, similar to Array.forEach()\n *\n * @name coordEach\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (currentCoord, coordIndex, featureIndex, multiFeatureIndex)\n * @param {boolean} [excludeWrapCoord=false] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration.\n * @returns {void}\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {\"foo\": \"bar\"}),\n * turf.point([36, 53], {\"hello\": \"world\"})\n * ]);\n *\n * turf.coordEach(features, function (currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {\n * //=currentCoord\n * //=coordIndex\n * //=featureIndex\n * //=multiFeatureIndex\n * //=geometryIndex\n * });\n */\nfunction coordEach(geojson, callback, excludeWrapCoord) {\n // Handles null Geometry -- Skips this GeoJSON\n if (geojson === null) return;\n var j,\n k,\n l,\n geometry,\n stopG,\n coords,\n geometryMaybeCollection,\n wrapShrink = 0,\n coordIndex = 0,\n isGeometryCollection,\n type = geojson.type,\n isFeatureCollection = type === \"FeatureCollection\",\n isFeature = type === \"Feature\",\n stop = isFeatureCollection ? geojson.features.length : 1;\n\n // This logic may look a little weird. The reason why it is that way\n // is because it's trying to be fast. GeoJSON supports multiple kinds\n // of objects at its root: FeatureCollection, Features, Geometries.\n // This function has the responsibility of handling all of them, and that\n // means that some of the `for` loops you see below actually just don't apply\n // to certain inputs. For instance, if you give this just a\n // Point geometry, then both loops are short-circuited and all we do\n // is gradually rename the input until it's called 'geometry'.\n //\n // This also aims to allocate as few resources as possible: just a\n // few numbers and booleans, rather than any temporary arrays as would\n // be required with the normalization approach.\n for (var featureIndex = 0; featureIndex < stop; featureIndex++) {\n geometryMaybeCollection = isFeatureCollection\n ? geojson.features[featureIndex].geometry\n : isFeature\n ? geojson.geometry\n : geojson;\n isGeometryCollection = geometryMaybeCollection\n ? geometryMaybeCollection.type === \"GeometryCollection\"\n : false;\n stopG = isGeometryCollection\n ? geometryMaybeCollection.geometries.length\n : 1;\n\n for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {\n var multiFeatureIndex = 0;\n var geometryIndex = 0;\n geometry = isGeometryCollection\n ? geometryMaybeCollection.geometries[geomIndex]\n : geometryMaybeCollection;\n\n // Handles null Geometry -- Skips this geometry\n if (geometry === null) continue;\n coords = geometry.coordinates;\n var geomType = geometry.type;\n\n wrapShrink =\n excludeWrapCoord &&\n (geomType === \"Polygon\" || geomType === \"MultiPolygon\")\n ? 1\n : 0;\n\n switch (geomType) {\n case null:\n break;\n case \"Point\":\n if (\n callback(\n coords,\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n multiFeatureIndex++;\n break;\n case \"LineString\":\n case \"MultiPoint\":\n for (j = 0; j < coords.length; j++) {\n if (\n callback(\n coords[j],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n if (geomType === \"MultiPoint\") multiFeatureIndex++;\n }\n if (geomType === \"LineString\") multiFeatureIndex++;\n break;\n case \"Polygon\":\n case \"MultiLineString\":\n for (j = 0; j < coords.length; j++) {\n for (k = 0; k < coords[j].length - wrapShrink; k++) {\n if (\n callback(\n coords[j][k],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n }\n if (geomType === \"MultiLineString\") multiFeatureIndex++;\n if (geomType === \"Polygon\") geometryIndex++;\n }\n if (geomType === \"Polygon\") multiFeatureIndex++;\n break;\n case \"MultiPolygon\":\n for (j = 0; j < coords.length; j++) {\n geometryIndex = 0;\n for (k = 0; k < coords[j].length; k++) {\n for (l = 0; l < coords[j][k].length - wrapShrink; l++) {\n if (\n callback(\n coords[j][k][l],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n }\n geometryIndex++;\n }\n multiFeatureIndex++;\n }\n break;\n case \"GeometryCollection\":\n for (j = 0; j < geometry.geometries.length; j++)\n if (\n coordEach(geometry.geometries[j], callback, excludeWrapCoord) ===\n false\n )\n return false;\n break;\n default:\n throw new Error(\"Unknown Geometry Type\");\n }\n }\n }\n}\n\n/**\n * Callback for coordReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback coordReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Array} currentCoord The current coordinate being processed.\n * @param {number} coordIndex The current index of the coordinate being processed.\n * Starts at index 0, if an initialValue is provided, and at index 1 otherwise.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n * @param {number} geometryIndex The current index of the Geometry being processed.\n */\n\n/**\n * Reduce coordinates in any GeoJSON object, similar to Array.reduce()\n *\n * @name coordReduce\n * @param {FeatureCollection|Geometry|Feature} geojson any GeoJSON object\n * @param {Function} callback a method that takes (previousValue, currentCoord, coordIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @param {boolean} [excludeWrapCoord=false] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration.\n * @returns {*} The value that results from the reduction.\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {\"foo\": \"bar\"}),\n * turf.point([36, 53], {\"hello\": \"world\"})\n * ]);\n *\n * turf.coordReduce(features, function (previousValue, currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {\n * //=previousValue\n * //=currentCoord\n * //=coordIndex\n * //=featureIndex\n * //=multiFeatureIndex\n * //=geometryIndex\n * return currentCoord;\n * });\n */\nfunction coordReduce(geojson, callback, initialValue, excludeWrapCoord) {\n var previousValue = initialValue;\n coordEach(\n geojson,\n function (\n currentCoord,\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) {\n if (coordIndex === 0 && initialValue === undefined)\n previousValue = currentCoord;\n else\n previousValue = callback(\n previousValue,\n currentCoord,\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n );\n },\n excludeWrapCoord\n );\n return previousValue;\n}\n\n/**\n * Callback for propEach\n *\n * @callback propEachCallback\n * @param {Object} currentProperties The current Properties being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n */\n\n/**\n * Iterate over properties in any GeoJSON object, similar to Array.forEach()\n *\n * @name propEach\n * @param {FeatureCollection|Feature} geojson any GeoJSON object\n * @param {Function} callback a method that takes (currentProperties, featureIndex)\n * @returns {void}\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * turf.propEach(features, function (currentProperties, featureIndex) {\n * //=currentProperties\n * //=featureIndex\n * });\n */\nfunction propEach(geojson, callback) {\n var i;\n switch (geojson.type) {\n case \"FeatureCollection\":\n for (i = 0; i < geojson.features.length; i++) {\n if (callback(geojson.features[i].properties, i) === false) break;\n }\n break;\n case \"Feature\":\n callback(geojson.properties, 0);\n break;\n }\n}\n\n/**\n * Callback for propReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback propReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {*} currentProperties The current Properties being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n */\n\n/**\n * Reduce properties in any GeoJSON object into a single value,\n * similar to how Array.reduce works. However, in this case we lazily run\n * the reduction, so an array of all properties is unnecessary.\n *\n * @name propReduce\n * @param {FeatureCollection|Feature} geojson any GeoJSON object\n * @param {Function} callback a method that takes (previousValue, currentProperties, featureIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * turf.propReduce(features, function (previousValue, currentProperties, featureIndex) {\n * //=previousValue\n * //=currentProperties\n * //=featureIndex\n * return currentProperties\n * });\n */\nfunction propReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n propEach(geojson, function (currentProperties, featureIndex) {\n if (featureIndex === 0 && initialValue === undefined)\n previousValue = currentProperties;\n else\n previousValue = callback(previousValue, currentProperties, featureIndex);\n });\n return previousValue;\n}\n\n/**\n * Callback for featureEach\n *\n * @callback featureEachCallback\n * @param {Feature} currentFeature The current Feature being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n */\n\n/**\n * Iterate over features in any GeoJSON object, similar to\n * Array.forEach.\n *\n * @name featureEach\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (currentFeature, featureIndex)\n * @returns {void}\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * turf.featureEach(features, function (currentFeature, featureIndex) {\n * //=currentFeature\n * //=featureIndex\n * });\n */\nfunction featureEach(geojson, callback) {\n if (geojson.type === \"Feature\") {\n callback(geojson, 0);\n } else if (geojson.type === \"FeatureCollection\") {\n for (var i = 0; i < geojson.features.length; i++) {\n if (callback(geojson.features[i], i) === false) break;\n }\n }\n}\n\n/**\n * Callback for featureReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback featureReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Feature} currentFeature The current Feature being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n */\n\n/**\n * Reduce features in any GeoJSON object, similar to Array.reduce().\n *\n * @name featureReduce\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (previousValue, currentFeature, featureIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {\"foo\": \"bar\"}),\n * turf.point([36, 53], {\"hello\": \"world\"})\n * ]);\n *\n * turf.featureReduce(features, function (previousValue, currentFeature, featureIndex) {\n * //=previousValue\n * //=currentFeature\n * //=featureIndex\n * return currentFeature\n * });\n */\nfunction featureReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n featureEach(geojson, function (currentFeature, featureIndex) {\n if (featureIndex === 0 && initialValue === undefined)\n previousValue = currentFeature;\n else previousValue = callback(previousValue, currentFeature, featureIndex);\n });\n return previousValue;\n}\n\n/**\n * Get all coordinates from any GeoJSON object.\n *\n * @name coordAll\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @returns {Array>} coordinate position array\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * var coords = turf.coordAll(features);\n * //= [[26, 37], [36, 53]]\n */\nfunction coordAll(geojson) {\n var coords = [];\n coordEach(geojson, function (coord) {\n coords.push(coord);\n });\n return coords;\n}\n\n/**\n * Callback for geomEach\n *\n * @callback geomEachCallback\n * @param {Geometry} currentGeometry The current Geometry being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {Object} featureProperties The current Feature Properties being processed.\n * @param {Array} featureBBox The current Feature BBox being processed.\n * @param {number|string} featureId The current Feature Id being processed.\n */\n\n/**\n * Iterate over each geometry in any GeoJSON object, similar to Array.forEach()\n *\n * @name geomEach\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (currentGeometry, featureIndex, featureProperties, featureBBox, featureId)\n * @returns {void}\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * turf.geomEach(features, function (currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {\n * //=currentGeometry\n * //=featureIndex\n * //=featureProperties\n * //=featureBBox\n * //=featureId\n * });\n */\nfunction geomEach(geojson, callback) {\n var i,\n j,\n g,\n geometry,\n stopG,\n geometryMaybeCollection,\n isGeometryCollection,\n featureProperties,\n featureBBox,\n featureId,\n featureIndex = 0,\n isFeatureCollection = geojson.type === \"FeatureCollection\",\n isFeature = geojson.type === \"Feature\",\n stop = isFeatureCollection ? geojson.features.length : 1;\n\n // This logic may look a little weird. The reason why it is that way\n // is because it's trying to be fast. GeoJSON supports multiple kinds\n // of objects at its root: FeatureCollection, Features, Geometries.\n // This function has the responsibility of handling all of them, and that\n // means that some of the `for` loops you see below actually just don't apply\n // to certain inputs. For instance, if you give this just a\n // Point geometry, then both loops are short-circuited and all we do\n // is gradually rename the input until it's called 'geometry'.\n //\n // This also aims to allocate as few resources as possible: just a\n // few numbers and booleans, rather than any temporary arrays as would\n // be required with the normalization approach.\n for (i = 0; i < stop; i++) {\n geometryMaybeCollection = isFeatureCollection\n ? geojson.features[i].geometry\n : isFeature\n ? geojson.geometry\n : geojson;\n featureProperties = isFeatureCollection\n ? geojson.features[i].properties\n : isFeature\n ? geojson.properties\n : {};\n featureBBox = isFeatureCollection\n ? geojson.features[i].bbox\n : isFeature\n ? geojson.bbox\n : undefined;\n featureId = isFeatureCollection\n ? geojson.features[i].id\n : isFeature\n ? geojson.id\n : undefined;\n isGeometryCollection = geometryMaybeCollection\n ? geometryMaybeCollection.type === \"GeometryCollection\"\n : false;\n stopG = isGeometryCollection\n ? geometryMaybeCollection.geometries.length\n : 1;\n\n for (g = 0; g < stopG; g++) {\n geometry = isGeometryCollection\n ? geometryMaybeCollection.geometries[g]\n : geometryMaybeCollection;\n\n // Handle null Geometry\n if (geometry === null) {\n if (\n callback(\n null,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n continue;\n }\n switch (geometry.type) {\n case \"Point\":\n case \"LineString\":\n case \"MultiPoint\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\": {\n if (\n callback(\n geometry,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n break;\n }\n case \"GeometryCollection\": {\n for (j = 0; j < geometry.geometries.length; j++) {\n if (\n callback(\n geometry.geometries[j],\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n }\n break;\n }\n default:\n throw new Error(\"Unknown Geometry Type\");\n }\n }\n // Only increase `featureIndex` per each feature\n featureIndex++;\n }\n}\n\n/**\n * Callback for geomReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback geomReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Geometry} currentGeometry The current Geometry being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {Object} featureProperties The current Feature Properties being processed.\n * @param {Array} featureBBox The current Feature BBox being processed.\n * @param {number|string} featureId The current Feature Id being processed.\n */\n\n/**\n * Reduce geometry in any GeoJSON object, similar to Array.reduce().\n *\n * @name geomReduce\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * turf.geomReduce(features, function (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {\n * //=previousValue\n * //=currentGeometry\n * //=featureIndex\n * //=featureProperties\n * //=featureBBox\n * //=featureId\n * return currentGeometry\n * });\n */\nfunction geomReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n geomEach(\n geojson,\n function (\n currentGeometry,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) {\n if (featureIndex === 0 && initialValue === undefined)\n previousValue = currentGeometry;\n else\n previousValue = callback(\n previousValue,\n currentGeometry,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n );\n }\n );\n return previousValue;\n}\n\n/**\n * Callback for flattenEach\n *\n * @callback flattenEachCallback\n * @param {Feature} currentFeature The current flattened feature being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n */\n\n/**\n * Iterate over flattened features in any GeoJSON object, similar to\n * Array.forEach.\n *\n * @name flattenEach\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (currentFeature, featureIndex, multiFeatureIndex)\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.multiPoint([[40, 30], [36, 53]], {hello: 'world'})\n * ]);\n *\n * turf.flattenEach(features, function (currentFeature, featureIndex, multiFeatureIndex) {\n * //=currentFeature\n * //=featureIndex\n * //=multiFeatureIndex\n * });\n */\nfunction flattenEach(geojson, callback) {\n geomEach(geojson, function (geometry, featureIndex, properties, bbox, id) {\n // Callback for single geometry\n var type = geometry === null ? null : geometry.type;\n switch (type) {\n case null:\n case \"Point\":\n case \"LineString\":\n case \"Polygon\":\n if (\n callback(\n helpers.feature(geometry, properties, { bbox: bbox, id: id }),\n featureIndex,\n 0\n ) === false\n )\n return false;\n return;\n }\n\n var geomType;\n\n // Callback for multi-geometry\n switch (type) {\n case \"MultiPoint\":\n geomType = \"Point\";\n break;\n case \"MultiLineString\":\n geomType = \"LineString\";\n break;\n case \"MultiPolygon\":\n geomType = \"Polygon\";\n break;\n }\n\n for (\n var multiFeatureIndex = 0;\n multiFeatureIndex < geometry.coordinates.length;\n multiFeatureIndex++\n ) {\n var coordinate = geometry.coordinates[multiFeatureIndex];\n var geom = {\n type: geomType,\n coordinates: coordinate,\n };\n if (\n callback(helpers.feature(geom, properties), featureIndex, multiFeatureIndex) ===\n false\n )\n return false;\n }\n });\n}\n\n/**\n * Callback for flattenReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback flattenReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Feature} currentFeature The current Feature being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n */\n\n/**\n * Reduce flattened features in any GeoJSON object, similar to Array.reduce().\n *\n * @name flattenReduce\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (previousValue, currentFeature, featureIndex, multiFeatureIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.multiPoint([[40, 30], [36, 53]], {hello: 'world'})\n * ]);\n *\n * turf.flattenReduce(features, function (previousValue, currentFeature, featureIndex, multiFeatureIndex) {\n * //=previousValue\n * //=currentFeature\n * //=featureIndex\n * //=multiFeatureIndex\n * return currentFeature\n * });\n */\nfunction flattenReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n flattenEach(\n geojson,\n function (currentFeature, featureIndex, multiFeatureIndex) {\n if (\n featureIndex === 0 &&\n multiFeatureIndex === 0 &&\n initialValue === undefined\n )\n previousValue = currentFeature;\n else\n previousValue = callback(\n previousValue,\n currentFeature,\n featureIndex,\n multiFeatureIndex\n );\n }\n );\n return previousValue;\n}\n\n/**\n * Callback for segmentEach\n *\n * @callback segmentEachCallback\n * @param {Feature} currentSegment The current Segment being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n * @param {number} geometryIndex The current index of the Geometry being processed.\n * @param {number} segmentIndex The current index of the Segment being processed.\n * @returns {void}\n */\n\n/**\n * Iterate over 2-vertex line segment in any GeoJSON object, similar to Array.forEach()\n * (Multi)Point geometries do not contain segments therefore they are ignored during this operation.\n *\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON\n * @param {Function} callback a method that takes (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex)\n * @returns {void}\n * @example\n * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]);\n *\n * // Iterate over GeoJSON by 2-vertex segments\n * turf.segmentEach(polygon, function (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {\n * //=currentSegment\n * //=featureIndex\n * //=multiFeatureIndex\n * //=geometryIndex\n * //=segmentIndex\n * });\n *\n * // Calculate the total number of segments\n * var total = 0;\n * turf.segmentEach(polygon, function () {\n * total++;\n * });\n */\nfunction segmentEach(geojson, callback) {\n flattenEach(geojson, function (feature, featureIndex, multiFeatureIndex) {\n var segmentIndex = 0;\n\n // Exclude null Geometries\n if (!feature.geometry) return;\n // (Multi)Point geometries do not contain segments therefore they are ignored during this operation.\n var type = feature.geometry.type;\n if (type === \"Point\" || type === \"MultiPoint\") return;\n\n // Generate 2-vertex line segments\n var previousCoords;\n var previousFeatureIndex = 0;\n var previousMultiIndex = 0;\n var prevGeomIndex = 0;\n if (\n coordEach(\n feature,\n function (\n currentCoord,\n coordIndex,\n featureIndexCoord,\n multiPartIndexCoord,\n geometryIndex\n ) {\n // Simulating a meta.coordReduce() since `reduce` operations cannot be stopped by returning `false`\n if (\n previousCoords === undefined ||\n featureIndex > previousFeatureIndex ||\n multiPartIndexCoord > previousMultiIndex ||\n geometryIndex > prevGeomIndex\n ) {\n previousCoords = currentCoord;\n previousFeatureIndex = featureIndex;\n previousMultiIndex = multiPartIndexCoord;\n prevGeomIndex = geometryIndex;\n segmentIndex = 0;\n return;\n }\n var currentSegment = helpers.lineString(\n [previousCoords, currentCoord],\n feature.properties\n );\n if (\n callback(\n currentSegment,\n featureIndex,\n multiFeatureIndex,\n geometryIndex,\n segmentIndex\n ) === false\n )\n return false;\n segmentIndex++;\n previousCoords = currentCoord;\n }\n ) === false\n )\n return false;\n });\n}\n\n/**\n * Callback for segmentReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback segmentReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Feature} currentSegment The current Segment being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n * @param {number} geometryIndex The current index of the Geometry being processed.\n * @param {number} segmentIndex The current index of the Segment being processed.\n */\n\n/**\n * Reduce 2-vertex line segment in any GeoJSON object, similar to Array.reduce()\n * (Multi)Point geometries do not contain segments therefore they are ignored during this operation.\n *\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON\n * @param {Function} callback a method that takes (previousValue, currentSegment, currentIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {void}\n * @example\n * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]);\n *\n * // Iterate over GeoJSON by 2-vertex segments\n * turf.segmentReduce(polygon, function (previousSegment, currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {\n * //= previousSegment\n * //= currentSegment\n * //= featureIndex\n * //= multiFeatureIndex\n * //= geometryIndex\n * //= segmentIndex\n * return currentSegment\n * });\n *\n * // Calculate the total number of segments\n * var initialValue = 0\n * var total = turf.segmentReduce(polygon, function (previousValue) {\n * previousValue++;\n * return previousValue;\n * }, initialValue);\n */\nfunction segmentReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n var started = false;\n segmentEach(\n geojson,\n function (\n currentSegment,\n featureIndex,\n multiFeatureIndex,\n geometryIndex,\n segmentIndex\n ) {\n if (started === false && initialValue === undefined)\n previousValue = currentSegment;\n else\n previousValue = callback(\n previousValue,\n currentSegment,\n featureIndex,\n multiFeatureIndex,\n geometryIndex,\n segmentIndex\n );\n started = true;\n }\n );\n return previousValue;\n}\n\n/**\n * Callback for lineEach\n *\n * @callback lineEachCallback\n * @param {Feature} currentLine The current LineString|LinearRing being processed\n * @param {number} featureIndex The current index of the Feature being processed\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed\n * @param {number} geometryIndex The current index of the Geometry being processed\n */\n\n/**\n * Iterate over line or ring coordinates in LineString, Polygon, MultiLineString, MultiPolygon Features or Geometries,\n * similar to Array.forEach.\n *\n * @name lineEach\n * @param {Geometry|Feature} geojson object\n * @param {Function} callback a method that takes (currentLine, featureIndex, multiFeatureIndex, geometryIndex)\n * @example\n * var multiLine = turf.multiLineString([\n * [[26, 37], [35, 45]],\n * [[36, 53], [38, 50], [41, 55]]\n * ]);\n *\n * turf.lineEach(multiLine, function (currentLine, featureIndex, multiFeatureIndex, geometryIndex) {\n * //=currentLine\n * //=featureIndex\n * //=multiFeatureIndex\n * //=geometryIndex\n * });\n */\nfunction lineEach(geojson, callback) {\n // validation\n if (!geojson) throw new Error(\"geojson is required\");\n\n flattenEach(geojson, function (feature, featureIndex, multiFeatureIndex) {\n if (feature.geometry === null) return;\n var type = feature.geometry.type;\n var coords = feature.geometry.coordinates;\n switch (type) {\n case \"LineString\":\n if (callback(feature, featureIndex, multiFeatureIndex, 0, 0) === false)\n return false;\n break;\n case \"Polygon\":\n for (\n var geometryIndex = 0;\n geometryIndex < coords.length;\n geometryIndex++\n ) {\n if (\n callback(\n helpers.lineString(coords[geometryIndex], feature.properties),\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n }\n break;\n }\n });\n}\n\n/**\n * Callback for lineReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback lineReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Feature} currentLine The current LineString|LinearRing being processed.\n * @param {number} featureIndex The current index of the Feature being processed\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed\n * @param {number} geometryIndex The current index of the Geometry being processed\n */\n\n/**\n * Reduce features in any GeoJSON object, similar to Array.reduce().\n *\n * @name lineReduce\n * @param {Geometry|Feature} geojson object\n * @param {Function} callback a method that takes (previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var multiPoly = turf.multiPolygon([\n * turf.polygon([[[12,48],[2,41],[24,38],[12,48]], [[9,44],[13,41],[13,45],[9,44]]]),\n * turf.polygon([[[5, 5], [0, 0], [2, 2], [4, 4], [5, 5]]])\n * ]);\n *\n * turf.lineReduce(multiPoly, function (previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex) {\n * //=previousValue\n * //=currentLine\n * //=featureIndex\n * //=multiFeatureIndex\n * //=geometryIndex\n * return currentLine\n * });\n */\nfunction lineReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n lineEach(\n geojson,\n function (currentLine, featureIndex, multiFeatureIndex, geometryIndex) {\n if (featureIndex === 0 && initialValue === undefined)\n previousValue = currentLine;\n else\n previousValue = callback(\n previousValue,\n currentLine,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n );\n }\n );\n return previousValue;\n}\n\n/**\n * Finds a particular 2-vertex LineString Segment from a GeoJSON using `@turf/meta` indexes.\n *\n * Negative indexes are permitted.\n * Point & MultiPoint will always return null.\n *\n * @param {FeatureCollection|Feature|Geometry} geojson Any GeoJSON Feature or Geometry\n * @param {Object} [options={}] Optional parameters\n * @param {number} [options.featureIndex=0] Feature Index\n * @param {number} [options.multiFeatureIndex=0] Multi-Feature Index\n * @param {number} [options.geometryIndex=0] Geometry Index\n * @param {number} [options.segmentIndex=0] Segment Index\n * @param {Object} [options.properties={}] Translate Properties to output LineString\n * @param {BBox} [options.bbox={}] Translate BBox to output LineString\n * @param {number|string} [options.id={}] Translate Id to output LineString\n * @returns {Feature} 2-vertex GeoJSON Feature LineString\n * @example\n * var multiLine = turf.multiLineString([\n * [[10, 10], [50, 30], [30, 40]],\n * [[-10, -10], [-50, -30], [-30, -40]]\n * ]);\n *\n * // First Segment (defaults are 0)\n * turf.findSegment(multiLine);\n * // => Feature>\n *\n * // First Segment of 2nd Multi Feature\n * turf.findSegment(multiLine, {multiFeatureIndex: 1});\n * // => Feature>\n *\n * // Last Segment of Last Multi Feature\n * turf.findSegment(multiLine, {multiFeatureIndex: -1, segmentIndex: -1});\n * // => Feature>\n */\nfunction findSegment(geojson, options) {\n // Optional Parameters\n options = options || {};\n if (!helpers.isObject(options)) throw new Error(\"options is invalid\");\n var featureIndex = options.featureIndex || 0;\n var multiFeatureIndex = options.multiFeatureIndex || 0;\n var geometryIndex = options.geometryIndex || 0;\n var segmentIndex = options.segmentIndex || 0;\n\n // Find FeatureIndex\n var properties = options.properties;\n var geometry;\n\n switch (geojson.type) {\n case \"FeatureCollection\":\n if (featureIndex < 0)\n featureIndex = geojson.features.length + featureIndex;\n properties = properties || geojson.features[featureIndex].properties;\n geometry = geojson.features[featureIndex].geometry;\n break;\n case \"Feature\":\n properties = properties || geojson.properties;\n geometry = geojson.geometry;\n break;\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\":\n geometry = geojson;\n break;\n default:\n throw new Error(\"geojson is invalid\");\n }\n\n // Find SegmentIndex\n if (geometry === null) return null;\n var coords = geometry.coordinates;\n switch (geometry.type) {\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n if (segmentIndex < 0) segmentIndex = coords.length + segmentIndex - 1;\n return helpers.lineString(\n [coords[segmentIndex], coords[segmentIndex + 1]],\n properties,\n options\n );\n case \"Polygon\":\n if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex;\n if (segmentIndex < 0)\n segmentIndex = coords[geometryIndex].length + segmentIndex - 1;\n return helpers.lineString(\n [\n coords[geometryIndex][segmentIndex],\n coords[geometryIndex][segmentIndex + 1],\n ],\n properties,\n options\n );\n case \"MultiLineString\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (segmentIndex < 0)\n segmentIndex = coords[multiFeatureIndex].length + segmentIndex - 1;\n return helpers.lineString(\n [\n coords[multiFeatureIndex][segmentIndex],\n coords[multiFeatureIndex][segmentIndex + 1],\n ],\n properties,\n options\n );\n case \"MultiPolygon\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (geometryIndex < 0)\n geometryIndex = coords[multiFeatureIndex].length + geometryIndex;\n if (segmentIndex < 0)\n segmentIndex =\n coords[multiFeatureIndex][geometryIndex].length - segmentIndex - 1;\n return helpers.lineString(\n [\n coords[multiFeatureIndex][geometryIndex][segmentIndex],\n coords[multiFeatureIndex][geometryIndex][segmentIndex + 1],\n ],\n properties,\n options\n );\n }\n throw new Error(\"geojson is invalid\");\n}\n\n/**\n * Finds a particular Point from a GeoJSON using `@turf/meta` indexes.\n *\n * Negative indexes are permitted.\n *\n * @param {FeatureCollection|Feature|Geometry} geojson Any GeoJSON Feature or Geometry\n * @param {Object} [options={}] Optional parameters\n * @param {number} [options.featureIndex=0] Feature Index\n * @param {number} [options.multiFeatureIndex=0] Multi-Feature Index\n * @param {number} [options.geometryIndex=0] Geometry Index\n * @param {number} [options.coordIndex=0] Coord Index\n * @param {Object} [options.properties={}] Translate Properties to output Point\n * @param {BBox} [options.bbox={}] Translate BBox to output Point\n * @param {number|string} [options.id={}] Translate Id to output Point\n * @returns {Feature} 2-vertex GeoJSON Feature Point\n * @example\n * var multiLine = turf.multiLineString([\n * [[10, 10], [50, 30], [30, 40]],\n * [[-10, -10], [-50, -30], [-30, -40]]\n * ]);\n *\n * // First Segment (defaults are 0)\n * turf.findPoint(multiLine);\n * // => Feature>\n *\n * // First Segment of the 2nd Multi-Feature\n * turf.findPoint(multiLine, {multiFeatureIndex: 1});\n * // => Feature>\n *\n * // Last Segment of last Multi-Feature\n * turf.findPoint(multiLine, {multiFeatureIndex: -1, coordIndex: -1});\n * // => Feature>\n */\nfunction findPoint(geojson, options) {\n // Optional Parameters\n options = options || {};\n if (!helpers.isObject(options)) throw new Error(\"options is invalid\");\n var featureIndex = options.featureIndex || 0;\n var multiFeatureIndex = options.multiFeatureIndex || 0;\n var geometryIndex = options.geometryIndex || 0;\n var coordIndex = options.coordIndex || 0;\n\n // Find FeatureIndex\n var properties = options.properties;\n var geometry;\n\n switch (geojson.type) {\n case \"FeatureCollection\":\n if (featureIndex < 0)\n featureIndex = geojson.features.length + featureIndex;\n properties = properties || geojson.features[featureIndex].properties;\n geometry = geojson.features[featureIndex].geometry;\n break;\n case \"Feature\":\n properties = properties || geojson.properties;\n geometry = geojson.geometry;\n break;\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\":\n geometry = geojson;\n break;\n default:\n throw new Error(\"geojson is invalid\");\n }\n\n // Find Coord Index\n if (geometry === null) return null;\n var coords = geometry.coordinates;\n switch (geometry.type) {\n case \"Point\":\n return helpers.point(coords, properties, options);\n case \"MultiPoint\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n return helpers.point(coords[multiFeatureIndex], properties, options);\n case \"LineString\":\n if (coordIndex < 0) coordIndex = coords.length + coordIndex;\n return helpers.point(coords[coordIndex], properties, options);\n case \"Polygon\":\n if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex;\n if (coordIndex < 0)\n coordIndex = coords[geometryIndex].length + coordIndex;\n return helpers.point(coords[geometryIndex][coordIndex], properties, options);\n case \"MultiLineString\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (coordIndex < 0)\n coordIndex = coords[multiFeatureIndex].length + coordIndex;\n return helpers.point(coords[multiFeatureIndex][coordIndex], properties, options);\n case \"MultiPolygon\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (geometryIndex < 0)\n geometryIndex = coords[multiFeatureIndex].length + geometryIndex;\n if (coordIndex < 0)\n coordIndex =\n coords[multiFeatureIndex][geometryIndex].length - coordIndex;\n return helpers.point(\n coords[multiFeatureIndex][geometryIndex][coordIndex],\n properties,\n options\n );\n }\n throw new Error(\"geojson is invalid\");\n}\n\nexports.coordAll = coordAll;\nexports.coordEach = coordEach;\nexports.coordReduce = coordReduce;\nexports.featureEach = featureEach;\nexports.featureReduce = featureReduce;\nexports.findPoint = findPoint;\nexports.findSegment = findSegment;\nexports.flattenEach = flattenEach;\nexports.flattenReduce = flattenReduce;\nexports.geomEach = geomEach;\nexports.geomReduce = geomReduce;\nexports.lineEach = lineEach;\nexports.lineReduce = lineReduce;\nexports.propEach = propEach;\nexports.propReduce = propReduce;\nexports.segmentEach = segmentEach;\nexports.segmentReduce = segmentReduce;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar meta_1 = require(\"@turf/meta\");\n/**\n * Takes a set of features, calculates the bbox of all input features, and returns a bounding box.\n *\n * @name bbox\n * @param {GeoJSON} geojson any GeoJSON object\n * @returns {BBox} bbox extent in [minX, minY, maxX, maxY] order\n * @example\n * var line = turf.lineString([[-74, 40], [-78, 42], [-82, 35]]);\n * var bbox = turf.bbox(line);\n * var bboxPolygon = turf.bboxPolygon(bbox);\n *\n * //addToMap\n * var addToMap = [line, bboxPolygon]\n */\nfunction bbox(geojson) {\n var result = [Infinity, Infinity, -Infinity, -Infinity];\n meta_1.coordEach(geojson, function (coord) {\n if (result[0] > coord[0]) {\n result[0] = coord[0];\n }\n if (result[1] > coord[1]) {\n result[1] = coord[1];\n }\n if (result[2] < coord[0]) {\n result[2] = coord[0];\n }\n if (result[3] < coord[1]) {\n result[3] = coord[1];\n }\n });\n return result;\n}\nbbox[\"default\"] = bbox;\nexports.default = bbox;\n","var rbush = require('rbush');\nvar helpers = require('@turf/helpers');\nvar meta = require('@turf/meta');\nvar turfBBox = require('@turf/bbox').default;\nvar featureEach = meta.featureEach;\nvar coordEach = meta.coordEach;\nvar polygon = helpers.polygon;\nvar featureCollection = helpers.featureCollection;\n\n/**\n * GeoJSON implementation of [RBush](https://github.com/mourner/rbush#rbush) spatial index.\n *\n * @name rbush\n * @param {number} [maxEntries=9] defines the maximum number of entries in a tree node. 9 (used by default) is a\n * reasonable choice for most applications. Higher value means faster insertion and slower search, and vice versa.\n * @returns {RBush} GeoJSON RBush\n * @example\n * var geojsonRbush = require('geojson-rbush').default;\n * var tree = geojsonRbush();\n */\nfunction geojsonRbush(maxEntries) {\n var tree = new rbush(maxEntries);\n /**\n * [insert](https://github.com/mourner/rbush#data-format)\n *\n * @param {Feature} feature insert single GeoJSON Feature\n * @returns {RBush} GeoJSON RBush\n * @example\n * var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]);\n * tree.insert(poly)\n */\n tree.insert = function (feature) {\n if (feature.type !== 'Feature') throw new Error('invalid feature');\n feature.bbox = feature.bbox ? feature.bbox : turfBBox(feature);\n return rbush.prototype.insert.call(this, feature);\n };\n\n /**\n * [load](https://github.com/mourner/rbush#bulk-inserting-data)\n *\n * @param {FeatureCollection|Array} features load entire GeoJSON FeatureCollection\n * @returns {RBush} GeoJSON RBush\n * @example\n * var polys = turf.polygons([\n * [[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]],\n * [[[-93, 32], [-83, 32], [-83, 39], [-93, 39], [-93, 32]]]\n * ]);\n * tree.load(polys);\n */\n tree.load = function (features) {\n var load = [];\n // Load an Array of Features\n if (Array.isArray(features)) {\n features.forEach(function (feature) {\n if (feature.type !== 'Feature') throw new Error('invalid features');\n feature.bbox = feature.bbox ? feature.bbox : turfBBox(feature);\n load.push(feature);\n });\n } else {\n // Load a FeatureCollection\n featureEach(features, function (feature) {\n if (feature.type !== 'Feature') throw new Error('invalid features');\n feature.bbox = feature.bbox ? feature.bbox : turfBBox(feature);\n load.push(feature);\n });\n }\n return rbush.prototype.load.call(this, load);\n };\n\n /**\n * [remove](https://github.com/mourner/rbush#removing-data)\n *\n * @param {Feature} feature remove single GeoJSON Feature\n * @param {Function} equals Pass a custom equals function to compare by value for removal.\n * @returns {RBush} GeoJSON RBush\n * @example\n * var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]);\n *\n * tree.remove(poly);\n */\n tree.remove = function (feature, equals) {\n if (feature.type !== 'Feature') throw new Error('invalid feature');\n feature.bbox = feature.bbox ? feature.bbox : turfBBox(feature);\n return rbush.prototype.remove.call(this, feature, equals);\n };\n\n /**\n * [clear](https://github.com/mourner/rbush#removing-data)\n *\n * @returns {RBush} GeoJSON Rbush\n * @example\n * tree.clear()\n */\n tree.clear = function () {\n return rbush.prototype.clear.call(this);\n };\n\n /**\n * [search](https://github.com/mourner/rbush#search)\n *\n * @param {BBox|FeatureCollection|Feature} geojson search with GeoJSON\n * @returns {FeatureCollection} all features that intersects with the given GeoJSON.\n * @example\n * var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]);\n *\n * tree.search(poly);\n */\n tree.search = function (geojson) {\n var features = rbush.prototype.search.call(this, this.toBBox(geojson));\n return featureCollection(features);\n };\n\n /**\n * [collides](https://github.com/mourner/rbush#collisions)\n *\n * @param {BBox|FeatureCollection|Feature} geojson collides with GeoJSON\n * @returns {boolean} true if there are any items intersecting the given GeoJSON, otherwise false.\n * @example\n * var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]);\n *\n * tree.collides(poly);\n */\n tree.collides = function (geojson) {\n return rbush.prototype.collides.call(this, this.toBBox(geojson));\n };\n\n /**\n * [all](https://github.com/mourner/rbush#search)\n *\n * @returns {FeatureCollection} all the features in RBush\n * @example\n * tree.all()\n */\n tree.all = function () {\n var features = rbush.prototype.all.call(this);\n return featureCollection(features);\n };\n\n /**\n * [toJSON](https://github.com/mourner/rbush#export-and-import)\n *\n * @returns {any} export data as JSON object\n * @example\n * var exported = tree.toJSON()\n */\n tree.toJSON = function () {\n return rbush.prototype.toJSON.call(this);\n };\n\n /**\n * [fromJSON](https://github.com/mourner/rbush#export-and-import)\n *\n * @param {any} json import previously exported data\n * @returns {RBush} GeoJSON RBush\n * @example\n * var exported = {\n * \"children\": [\n * {\n * \"type\": \"Feature\",\n * \"geometry\": {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 50]\n * },\n * \"properties\": {},\n * \"bbox\": [110, 50, 110, 50]\n * }\n * ],\n * \"height\": 1,\n * \"leaf\": true,\n * \"minX\": 110,\n * \"minY\": 50,\n * \"maxX\": 110,\n * \"maxY\": 50\n * }\n * tree.fromJSON(exported)\n */\n tree.fromJSON = function (json) {\n return rbush.prototype.fromJSON.call(this, json);\n };\n\n /**\n * Converts GeoJSON to {minX, minY, maxX, maxY} schema\n *\n * @private\n * @param {BBox|FeatureCollection|Feature} geojson feature(s) to retrieve BBox from\n * @returns {Object} converted to {minX, minY, maxX, maxY}\n */\n tree.toBBox = function (geojson) {\n var bbox;\n if (geojson.bbox) bbox = geojson.bbox;\n else if (Array.isArray(geojson) && geojson.length === 4) bbox = geojson;\n else if (Array.isArray(geojson) && geojson.length === 6) bbox = [geojson[0], geojson[1], geojson[3], geojson[4]];\n else if (geojson.type === 'Feature') bbox = turfBBox(geojson);\n else if (geojson.type === 'FeatureCollection') bbox = turfBBox(geojson);\n else throw new Error('invalid geojson')\n\n return {\n minX: bbox[0],\n minY: bbox[1],\n maxX: bbox[2],\n maxY: bbox[3]\n };\n };\n return tree;\n}\n\nmodule.exports = geojsonRbush;\nmodule.exports.default = geojsonRbush;\n","/* eslint-disable */\n\n// Array.findIndex Polyfill\nArray.prototype.findIndex =\n Array.prototype.findIndex ||\n function (callback) {\n if (this === null) {\n throw new TypeError(\n 'Array.prototype.findIndex called on null or undefined'\n );\n } else if (typeof callback !== 'function') {\n throw new TypeError('callback must be a function');\n }\n var list = Object(this);\n // Makes sures is always has an positive integer as length.\n var length = list.length >>> 0;\n var thisArg = arguments[1];\n for (var i = 0; i < length; i++) {\n if (callback.call(thisArg, list[i], i, list)) {\n return i;\n }\n }\n return -1;\n };\n\n// Array.find Polyfill for IE<12.\n// Requested here: https://github.com/geoman-io/leaflet-geoman/issues/173\nArray.prototype.find =\n Array.prototype.find ||\n function (callback) {\n if (this === null) {\n throw new TypeError('Array.prototype.find called on null or undefined');\n } else if (typeof callback !== 'function') {\n throw new TypeError('callback must be a function');\n }\n var list = Object(this);\n // Makes sures is always has an positive integer as length.\n var length = list.length >>> 0;\n var thisArg = arguments[1];\n for (var i = 0; i < length; i++) {\n var element = list[i];\n if (callback.call(thisArg, element, i, list)) {\n return element;\n }\n }\n };\n\n// Polyfill for Object.assign()\n// https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill\nif (typeof Object.assign != 'function') {\n Object.assign = function (target) {\n 'use strict';\n if (target == null) {\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n target = Object(target);\n for (var index = 1; index < arguments.length; index++) {\n var source = arguments[index];\n if (source != null) {\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n }\n return target;\n };\n}\n\n// Polyfill for Element.remove()\n// https://developer.mozilla.org/de/docs/Web/API/ChildNode/remove#Polyfill\n(function (arr) {\n arr.forEach(function (item) {\n if (item.hasOwnProperty('remove')) {\n return;\n }\n Object.defineProperty(item, 'remove', {\n configurable: true,\n enumerable: true,\n writable: true,\n value: function remove() {\n this.parentNode.removeChild(this);\n },\n });\n });\n})([Element.prototype, CharacterData.prototype, DocumentType.prototype]);\n\n// Polyfill for Array.includes()\n// https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Polyfill\nif (!Array.prototype.includes) {\n Object.defineProperty(Array.prototype, 'includes', {\n value: function (searchElement, fromIndex) {\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n // 1. Let O be ? ToObject(this value).\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If len is 0, return false.\n if (len === 0) {\n return false;\n }\n\n // 4. Let n be ? ToInteger(fromIndex).\n // (If fromIndex is undefined, this step produces the value 0.)\n var n = fromIndex | 0;\n\n // 5. If n ≥ 0, then\n // a. Let k be n.\n // 6. Else n < 0,\n // a. Let k be len + n.\n // b. If k < 0, let k be 0.\n var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\n\n function sameValueZero(x, y) {\n return (\n x === y ||\n (typeof x === 'number' &&\n typeof y === 'number' &&\n isNaN(x) &&\n isNaN(y))\n );\n }\n\n // 7. Repeat, while k < len\n while (k < len) {\n // a. Let elementK be the result of ? Get(O, ! ToString(k)).\n // b. If SameValueZero(searchElement, elementK) is true, return true.\n if (sameValueZero(o[k], searchElement)) {\n return true;\n }\n // c. Increase k by 1.\n k++;\n }\n\n // 8. Return false\n return false;\n },\n });\n}\n","{\n \"name\": \"@geoman-io/leaflet-geoman-free\",\n \"version\": \"2.17.0\",\n \"description\": \"A Leaflet Plugin For Editing Geometry Layers in Leaflet 1.0\",\n \"keywords\": [\n \"leaflet\",\n \"geoman\",\n \"polygon management\",\n \"geometry editing\",\n \"map data\",\n \"map overlay\",\n \"polygon\",\n \"geojson\",\n \"leaflet-draw\",\n \"data-field-geojson\",\n \"ui-leaflet-draw\"\n ],\n \"files\": [\n \"dist\"\n ],\n \"main\": \"dist/leaflet-geoman.js\",\n \"types\": \"dist/leaflet-geoman.d.ts\",\n \"dependencies\": {\n \"@turf/boolean-contains\": \"^6.5.0\",\n \"@turf/kinks\": \"^6.5.0\",\n \"@turf/line-intersect\": \"^6.5.0\",\n \"@turf/line-split\": \"^6.5.0\",\n \"lodash\": \"4.17.21\",\n \"polyclip-ts\": \"^0.16.5\"\n },\n \"devDependencies\": {\n \"@types/leaflet\": \"^1.7.9\",\n \"cross-env\": \"^7.0.3\",\n \"cypress\": \"6.9.1\",\n \"cypress-wait-until\": \"1.7.1\",\n \"esbuild\": \"^0.20.0\",\n \"eslint\": \"8.56.0\",\n \"eslint-config-airbnb-base\": \"15.0.0\",\n \"eslint-config-prettier\": \"9.1.0\",\n \"eslint-plugin-cypress\": \"2.15.1\",\n \"eslint-plugin-import\": \"2.29.1\",\n \"husky\": \"^9.0.7\",\n \"leaflet\": \"1.9.3\",\n \"lint-staged\": \"^15.2.1\",\n \"prettier\": \"3.2.4\",\n \"prosthetic-hand\": \"1.3.1\",\n \"ts-node\": \"^10.9.2\"\n },\n \"peerDependencies\": {\n \"leaflet\": \"^1.2.0\"\n },\n \"scripts\": {\n \"start\": \"pnpm run dev\",\n \"dev\": \"cross-env DEV=true ts-node bundle.mjs\",\n \"build\": \"ts-node bundle.mjs\",\n \"test\": \"cypress run\",\n \"cypress\": \"cypress open\",\n \"prepare\": \"pnpm run build && husky\",\n \"eslint-check\": \"eslint --print-config . | eslint-config-prettier-check\",\n \"eslint\": \"eslint \\\"{src,cypress,demo}/**/*.js\\\" --fix \",\n \"prettier\": \"prettier --write \\\"{src,cypress,demo}/**/*.{js,css}\\\" --log-level=warn\",\n \"lint\": \"pnpm run eslint && pnpm run prettier\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git://github.com/geoman-io/leaflet-geoman.git\"\n },\n \"author\": {\n \"name\": \"Geoman.io\",\n \"email\": \"sales@geoman.io\",\n \"url\": \"http://geoman.io\"\n },\n \"license\": \"MIT\",\n \"bugs\": {\n \"url\": \"https://github.com/geoman-io/leaflet-geoman/issues\"\n },\n \"homepage\": \"https://geoman.io\",\n \"prettier\": {\n \"trailingComma\": \"es5\",\n \"tabWidth\": 2,\n \"semi\": true,\n \"singleQuote\": true\n },\n \"lint-staged\": {\n \"*.js\": \"eslint \\\"{src,cypress,demo}/**/*.js\\\" --fix\",\n \"*.{js,css,md}\": \"prettier --write \\\"{src,cypress,demo}/**/*.{js,css}\\\"\"\n }\n}\n","import merge from 'lodash/merge';\nimport translations from '../assets/translations';\nimport GlobalEditMode from './Mixins/Modes/Mode.Edit';\nimport GlobalDragMode from './Mixins/Modes/Mode.Drag';\nimport GlobalRemovalMode from './Mixins/Modes/Mode.Removal';\nimport GlobalRotateMode from './Mixins/Modes/Mode.Rotate';\nimport EventMixin from './Mixins/Events';\nimport createKeyboardMixins from './Mixins/Keyboard';\nimport { getRenderer } from './helpers';\n\nconst Map = L.Class.extend({\n includes: [\n GlobalEditMode,\n GlobalDragMode,\n GlobalRemovalMode,\n GlobalRotateMode,\n EventMixin,\n ],\n initialize(map) {\n this.map = map;\n this.Draw = new L.PM.Draw(map);\n this.Toolbar = new L.PM.Toolbar(map);\n this.Keyboard = createKeyboardMixins();\n\n this.globalOptions = {\n snappable: true,\n layerGroup: undefined,\n snappingOrder: [\n 'Marker',\n 'CircleMarker',\n 'Circle',\n 'Line',\n 'Polygon',\n 'Rectangle',\n ],\n panes: {\n vertexPane: 'markerPane',\n layerPane: 'overlayPane',\n markerPane: 'markerPane',\n },\n draggable: true,\n };\n\n this.Keyboard._initKeyListener(map);\n },\n // eslint-disable-next-line default-param-last\n setLang(lang = 'en', t, fallback = 'en') {\n const oldLang = L.PM.activeLang;\n if (t) {\n translations[lang] = merge(translations[fallback], t);\n }\n\n L.PM.activeLang = lang;\n this.map.pm.Toolbar.reinit();\n this._fireLangChange(oldLang, lang, fallback, translations[lang]);\n },\n addControls(options) {\n this.Toolbar.addControls(options);\n },\n removeControls() {\n this.Toolbar.removeControls();\n },\n toggleControls() {\n this.Toolbar.toggleControls();\n },\n controlsVisible() {\n return this.Toolbar.isVisible;\n },\n // eslint-disable-next-line default-param-last\n enableDraw(shape = 'Polygon', options) {\n // backwards compatible, remove after 3.0\n if (shape === 'Poly') {\n shape = 'Polygon';\n }\n\n this.Draw.enable(shape, options);\n },\n disableDraw(shape = 'Polygon') {\n // backwards compatible, remove after 3.0\n if (shape === 'Poly') {\n shape = 'Polygon';\n }\n\n this.Draw.disable(shape);\n },\n // optionsModifier for special options like ignoreShapes or merge\n setPathOptions(options, optionsModifier = {}) {\n const ignore = optionsModifier.ignoreShapes || [];\n const mergeOptions = optionsModifier.merge || false;\n\n this.map.pm.Draw.shapes.forEach((shape) => {\n if (ignore.indexOf(shape) === -1) {\n this.map.pm.Draw[shape].setPathOptions(options, mergeOptions);\n }\n });\n },\n\n getGlobalOptions() {\n return this.globalOptions;\n },\n setGlobalOptions(o) {\n // merge passed and existing options\n const options = merge(this.globalOptions, o);\n\n // TODO: remove with next major release\n if (options.editable) {\n options.resizeableCircleMarker = options.editable;\n delete options.editable;\n }\n\n // check if switched the editable mode for CircleMarker while drawing\n let reenableCircleMarker = false;\n if (\n this.map.pm.Draw.CircleMarker.enabled() &&\n !!this.map.pm.Draw.CircleMarker.options.resizeableCircleMarker !==\n !!options.resizeableCircleMarker\n ) {\n this.map.pm.Draw.CircleMarker.disable();\n reenableCircleMarker = true;\n }\n // check if switched the editable mode for Circle while drawing\n let reenableCircle = false;\n if (\n this.map.pm.Draw.Circle.enabled() &&\n !!this.map.pm.Draw.Circle.options.resizableCircle !==\n !!options.resizableCircle\n ) {\n this.map.pm.Draw.Circle.disable();\n reenableCircle = true;\n }\n\n // enable options for Drawing Shapes\n this.map.pm.Draw.shapes.forEach((shape) => {\n this.map.pm.Draw[shape].setOptions(options);\n });\n\n if (reenableCircleMarker) {\n this.map.pm.Draw.CircleMarker.enable();\n }\n\n if (reenableCircle) {\n this.map.pm.Draw.Circle.enable();\n }\n\n // enable options for Editing\n const layers = L.PM.Utils.findLayers(this.map);\n layers.forEach((layer) => {\n layer.pm.setOptions(options);\n });\n\n this.map.fire('pm:globaloptionschanged');\n\n // store options\n this.globalOptions = options;\n\n // apply the options (actually trigger the functionality)\n this.applyGlobalOptions();\n },\n applyGlobalOptions() {\n const layers = L.PM.Utils.findLayers(this.map);\n layers.forEach((layer) => {\n if (layer.pm.enabled()) {\n layer.pm.applyOptions();\n }\n });\n },\n globalDrawModeEnabled() {\n return !!this.Draw.getActiveShape();\n },\n globalCutModeEnabled() {\n return !!this.Draw.Cut.enabled();\n },\n enableGlobalCutMode(options) {\n return this.Draw.Cut.enable(options);\n },\n toggleGlobalCutMode(options) {\n return this.Draw.Cut.toggle(options);\n },\n disableGlobalCutMode() {\n return this.Draw.Cut.disable();\n },\n getGeomanLayers(asGroup = false) {\n const layers = L.PM.Utils.findLayers(this.map);\n if (!asGroup) {\n return layers;\n }\n const group = L.featureGroup();\n group._pmTempLayer = true;\n layers.forEach((layer) => {\n group.addLayer(layer);\n });\n return group;\n },\n getGeomanDrawLayers(asGroup = false) {\n const layers = L.PM.Utils.findLayers(this.map).filter(\n (l) => l._drawnByGeoman === true\n );\n if (!asGroup) {\n return layers;\n }\n const group = L.featureGroup();\n group._pmTempLayer = true;\n layers.forEach((layer) => {\n group.addLayer(layer);\n });\n return group;\n },\n // returns the map instance by default or a layergroup is set through global options\n _getContainingLayer() {\n return this.globalOptions.layerGroup &&\n this.globalOptions.layerGroup instanceof L.LayerGroup\n ? this.globalOptions.layerGroup\n : this.map;\n },\n _isCRSSimple() {\n return this.map.options.crs === L.CRS.Simple;\n },\n // in Canvas mode we need to convert touch- and pointerevents (IE) to mouseevents, because Leaflet don't support them.\n _touchEventCounter: 0,\n _addTouchEvents(elm) {\n if (this._touchEventCounter === 0) {\n L.DomEvent.on(elm, 'touchmove', this._canvasTouchMove, this);\n L.DomEvent.on(\n elm,\n 'touchstart touchend touchcancel',\n this._canvasTouchClick,\n this\n );\n }\n this._touchEventCounter += 1;\n },\n _removeTouchEvents(elm) {\n if (this._touchEventCounter === 1) {\n L.DomEvent.off(elm, 'touchmove', this._canvasTouchMove, this);\n L.DomEvent.off(\n elm,\n 'touchstart touchend touchcancel',\n this._canvasTouchClick,\n this\n );\n }\n this._touchEventCounter =\n this._touchEventCounter <= 1 ? 0 : this._touchEventCounter - 1;\n },\n _canvasTouchMove(e) {\n getRenderer(this.map)._onMouseMove(this._createMouseEvent('mousemove', e));\n },\n _canvasTouchClick(e) {\n let type = '';\n if (e.type === 'touchstart' || e.type === 'pointerdown') {\n type = 'mousedown';\n } else if (e.type === 'touchend' || e.type === 'pointerup') {\n type = 'mouseup';\n } else if (e.type === 'touchcancel' || e.type === 'pointercancel') {\n type = 'mouseup';\n }\n if (!type) {\n return;\n }\n getRenderer(this.map)._onClick(this._createMouseEvent(type, e));\n },\n _createMouseEvent(type, e) {\n let mouseEvent;\n const touchEvt = e.touches[0] || e.changedTouches[0];\n try {\n mouseEvent = new MouseEvent(type, {\n bubbles: e.bubbles,\n cancelable: e.cancelable,\n view: e.view,\n detail: touchEvt.detail,\n screenX: touchEvt.screenX,\n screenY: touchEvt.screenY,\n clientX: touchEvt.clientX,\n clientY: touchEvt.clientY,\n ctrlKey: e.ctrlKey,\n altKey: e.altKey,\n shiftKey: e.shiftKey,\n metaKey: e.metaKey,\n button: e.button,\n relatedTarget: e.relatedTarget,\n });\n } catch (ex) {\n mouseEvent = document.createEvent('MouseEvents');\n mouseEvent.initMouseEvent(\n type,\n e.bubbles,\n e.cancelable,\n e.view,\n touchEvt.detail,\n touchEvt.screenX,\n touchEvt.screenY,\n touchEvt.clientX,\n touchEvt.clientY,\n e.ctrlKey,\n e.altKey,\n e.shiftKey,\n e.metaKey,\n e.button,\n e.relatedTarget\n );\n }\n return mouseEvent;\n },\n});\n\nexport default Map;\n","import en from './en.json';\nimport de from './de.json';\nimport it from './it.json';\nimport id from './id.json';\nimport ro from './ro.json';\nimport ru from './ru.json';\nimport es from './es.json';\nimport nl from './nl.json';\nimport fr from './fr.json';\nimport zh from './zh.json';\n// eslint-disable-next-line camelcase\nimport zh_tw from './zh_tw.json';\n// eslint-disable-next-line camelcase\nimport pt_br from './pt_br.json';\n// eslint-disable-next-line camelcase\nimport pt_pt from './pt_pt.json';\nimport pl from './pl.json';\nimport sv from './sv.json';\nimport el from './el.json';\nimport hu from './hu.json';\nimport da from './da.json';\nimport no from './no.json';\nimport fa from './fa.json';\nimport ua from './ua.json';\nimport tr from './tr.json';\nimport cz from './cz.json';\nimport ja from './ja.json';\nimport fi from './fi.json';\nimport ko from './ko.json';\nimport ky from './ky.json';\n\nexport default {\n en,\n de,\n it,\n id,\n ro,\n ru,\n es,\n nl,\n fr,\n // eslint-disable-next-line camelcase\n pt_br,\n // eslint-disable-next-line camelcase\n pt_pt,\n zh,\n // eslint-disable-next-line camelcase\n zh_tw,\n pl,\n sv,\n el,\n hu,\n da,\n no,\n fa,\n ua,\n tr,\n cz,\n ja,\n fi,\n ko,\n ky,\n};\n","{\n \"tooltips\": {\n \"placeMarker\": \"Click to place marker\",\n \"firstVertex\": \"Click to place first vertex\",\n \"continueLine\": \"Click to continue drawing\",\n \"finishLine\": \"Click any existing marker to finish\",\n \"finishPoly\": \"Click first marker to finish\",\n \"finishRect\": \"Click to finish\",\n \"startCircle\": \"Click to place circle center\",\n \"finishCircle\": \"Click to finish circle\",\n \"placeCircleMarker\": \"Click to place circle marker\",\n \"placeText\": \"Click to place text\",\n \"selectFirstLayerFor\": \"Select first layer for {action}\",\n \"selectSecondLayerFor\": \"Select second layer for {action}\"\n },\n \"actions\": {\n \"finish\": \"Finish\",\n \"cancel\": \"Cancel\",\n \"removeLastVertex\": \"Remove Last Vertex\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Draw Marker\",\n \"drawPolyButton\": \"Draw Polygons\",\n \"drawLineButton\": \"Draw Polyline\",\n \"drawCircleButton\": \"Draw Circle\",\n \"drawRectButton\": \"Draw Rectangle\",\n \"editButton\": \"Edit Layers\",\n \"dragButton\": \"Drag Layers\",\n \"cutButton\": \"Cut Layers\",\n \"deleteButton\": \"Remove Layers\",\n \"drawCircleMarkerButton\": \"Draw Circle Marker\",\n \"snappingButton\": \"Snap dragged marker to other layers and vertices\",\n \"pinningButton\": \"Pin shared vertices together\",\n \"rotateButton\": \"Rotate Layers\",\n \"drawTextButton\": \"Draw Text\",\n \"scaleButton\": \"Scale Layers\",\n \"autoTracingButton\": \"Auto trace Line\",\n \"snapGuidesButton\": \"Show SnapGuides\",\n \"unionButton\": \"Union layers\",\n \"differenceButton\": \"Subtract layers\"\n },\n \"measurements\": {\n \"totalLength\": \"Length\",\n \"segmentLength\": \"Segment length\",\n \"area\": \"Area\",\n \"radius\": \"Radius\",\n \"perimeter\": \"Perimeter\",\n \"height\": \"Height\",\n \"width\": \"Width\",\n \"coordinates\": \"Position\",\n \"coordinatesMarker\": \"Position Marker\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Platziere den Marker mit Klick\",\n \"firstVertex\": \"Platziere den ersten Marker mit Klick\",\n \"continueLine\": \"Klicke, um weiter zu zeichnen\",\n \"finishLine\": \"Beende mit Klick auf existierenden Marker\",\n \"finishPoly\": \"Beende mit Klick auf ersten Marker\",\n \"finishRect\": \"Beende mit Klick\",\n \"startCircle\": \"Platziere das Kreiszentrum mit Klick\",\n \"finishCircle\": \"Beende den Kreis mit Klick\",\n \"placeCircleMarker\": \"Platziere den Kreismarker mit Klick\",\n \"placeText\": \"Platziere den Text mit Klick\"\n },\n \"actions\": {\n \"finish\": \"Beenden\",\n \"cancel\": \"Abbrechen\",\n \"removeLastVertex\": \"Letzten Vertex löschen\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Marker zeichnen\",\n \"drawPolyButton\": \"Polygon zeichnen\",\n \"drawLineButton\": \"Polyline zeichnen\",\n \"drawCircleButton\": \"Kreis zeichnen\",\n \"drawRectButton\": \"Rechteck zeichnen\",\n \"editButton\": \"Layer editieren\",\n \"dragButton\": \"Layer bewegen\",\n \"cutButton\": \"Layer schneiden\",\n \"deleteButton\": \"Layer löschen\",\n \"drawCircleMarkerButton\": \"Kreismarker zeichnen\",\n \"snappingButton\": \"Bewegter Layer an andere Layer oder Vertexe einhacken\",\n \"pinningButton\": \"Vertexe an der gleichen Position verknüpfen\",\n \"rotateButton\": \"Layer drehen\",\n \"drawTextButton\": \"Text zeichnen\",\n \"scaleButton\": \"Layer skalieren\",\n \"autoTracingButton\": \"Linie automatisch nachzeichen\"\n },\n \"measurements\": {\n \"totalLength\": \"Länge\",\n \"segmentLength\": \"Segment Länge\",\n \"area\": \"Fläche\",\n \"radius\": \"Radius\",\n \"perimeter\": \"Umfang\",\n \"height\": \"Höhe\",\n \"width\": \"Breite\",\n \"coordinates\": \"Position\",\n \"coordinatesMarker\": \"Position Marker\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Clicca per posizionare un Marker\",\n \"firstVertex\": \"Clicca per posizionare il primo vertice\",\n \"continueLine\": \"Clicca per continuare a disegnare\",\n \"finishLine\": \"Clicca qualsiasi marker esistente per terminare\",\n \"finishPoly\": \"Clicca il primo marker per terminare\",\n \"finishRect\": \"Clicca per terminare\",\n \"startCircle\": \"Clicca per posizionare il punto centrale del cerchio\",\n \"finishCircle\": \"Clicca per terminare il cerchio\",\n \"placeCircleMarker\": \"Clicca per posizionare un Marker del cherchio\"\n },\n \"actions\": {\n \"finish\": \"Termina\",\n \"cancel\": \"Annulla\",\n \"removeLastVertex\": \"Rimuovi l'ultimo vertice\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Disegna Marker\",\n \"drawPolyButton\": \"Disegna Poligoni\",\n \"drawLineButton\": \"Disegna Polilinea\",\n \"drawCircleButton\": \"Disegna Cerchio\",\n \"drawRectButton\": \"Disegna Rettangolo\",\n \"editButton\": \"Modifica Livelli\",\n \"dragButton\": \"Sposta Livelli\",\n \"cutButton\": \"Ritaglia Livelli\",\n \"deleteButton\": \"Elimina Livelli\",\n \"drawCircleMarkerButton\": \"Disegna Marker del Cerchio\",\n \"snappingButton\": \"Snap ha trascinato il pennarello su altri strati e vertici\",\n \"pinningButton\": \"Pin condiviso vertici insieme\",\n \"rotateButton\": \"Ruota livello\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Klik untuk menempatkan marker\",\n \"firstVertex\": \"Klik untuk menempatkan vertex pertama\",\n \"continueLine\": \"Klik untuk meneruskan digitasi\",\n \"finishLine\": \"Klik pada sembarang marker yang ada untuk mengakhiri\",\n \"finishPoly\": \"Klik marker pertama untuk mengakhiri\",\n \"finishRect\": \"Klik untuk mengakhiri\",\n \"startCircle\": \"Klik untuk menempatkan titik pusat lingkaran\",\n \"finishCircle\": \"Klik untuk mengakhiri lingkaran\",\n \"placeCircleMarker\": \"Klik untuk menempatkan penanda lingkarann\"\n },\n \"actions\": {\n \"finish\": \"Selesai\",\n \"cancel\": \"Batal\",\n \"removeLastVertex\": \"Hilangkan Vertex Terakhir\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Digitasi Marker\",\n \"drawPolyButton\": \"Digitasi Polygon\",\n \"drawLineButton\": \"Digitasi Polyline\",\n \"drawCircleButton\": \"Digitasi Lingkaran\",\n \"drawRectButton\": \"Digitasi Segi Empat\",\n \"editButton\": \"Edit Layer\",\n \"dragButton\": \"Geser Layer\",\n \"cutButton\": \"Potong Layer\",\n \"deleteButton\": \"Hilangkan Layer\",\n \"drawCircleMarkerButton\": \"Digitasi Penanda Lingkaran\",\n \"snappingButton\": \"Jepretkan penanda yang ditarik ke lapisan dan simpul lain\",\n \"pinningButton\": \"Sematkan simpul bersama bersama\",\n \"rotateButton\": \"Putar lapisan\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Adaugă un punct\",\n \"firstVertex\": \"Apasă aici pentru a adăuga primul Vertex\",\n \"continueLine\": \"Apasă aici pentru a continua desenul\",\n \"finishLine\": \"Apasă pe orice obiect pentru a finisa desenul\",\n \"finishPoly\": \"Apasă pe primul obiect pentru a finisa\",\n \"finishRect\": \"Apasă pentru a finisa\",\n \"startCircle\": \"Apasă pentru a desena un cerc\",\n \"finishCircle\": \"Apasă pentru a finisa un cerc\",\n \"placeCircleMarker\": \"Adaugă un punct\"\n },\n \"actions\": {\n \"finish\": \"Termină\",\n \"cancel\": \"Anulează\",\n \"removeLastVertex\": \"Șterge ultimul Vertex\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Adaugă o bulină\",\n \"drawPolyButton\": \"Desenează un poligon\",\n \"drawLineButton\": \"Desenează o linie\",\n \"drawCircleButton\": \"Desenează un cerc\",\n \"drawRectButton\": \"Desenează un dreptunghi\",\n \"editButton\": \"Editează straturile\",\n \"dragButton\": \"Mută straturile\",\n \"cutButton\": \"Taie straturile\",\n \"deleteButton\": \"Șterge straturile\",\n \"drawCircleMarkerButton\": \"Desenează marcatorul cercului\",\n \"snappingButton\": \"Fixați marcatorul glisat pe alte straturi și vârfuri\",\n \"pinningButton\": \"Fixați vârfurile partajate împreună\",\n \"rotateButton\": \"Rotiți stratul\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Нажмите, чтобы нанести маркер\",\n \"firstVertex\": \"Нажмите, чтобы нанести первый объект\",\n \"continueLine\": \"Нажмите, чтобы продолжить рисование\",\n \"finishLine\": \"Нажмите любой существующий маркер для завершения\",\n \"finishPoly\": \"Выберите первую точку, чтобы закончить\",\n \"finishRect\": \"Нажмите, чтобы закончить\",\n \"startCircle\": \"Нажмите, чтобы добавить центр круга\",\n \"finishCircle\": \"Нажмите, чтобы задать радиус\",\n \"placeCircleMarker\": \"Нажмите, чтобы нанести круговой маркер\"\n },\n \"actions\": {\n \"finish\": \"Завершить\",\n \"cancel\": \"Отменить\",\n \"removeLastVertex\": \"Отменить последнее действие\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Добавить маркер\",\n \"drawPolyButton\": \"Рисовать полигон\",\n \"drawLineButton\": \"Рисовать кривую\",\n \"drawCircleButton\": \"Рисовать круг\",\n \"drawRectButton\": \"Рисовать прямоугольник\",\n \"editButton\": \"Редактировать слой\",\n \"dragButton\": \"Перенести слой\",\n \"cutButton\": \"Вырезать слой\",\n \"deleteButton\": \"Удалить слой\",\n \"drawCircleMarkerButton\": \"Добавить круговой маркер\",\n \"snappingButton\": \"Привязать перетаскиваемый маркер к другим слоям и вершинам\",\n \"pinningButton\": \"Связать общие точки вместе\",\n \"rotateButton\": \"Поворот слоя\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Presiona para colocar un marcador\",\n \"firstVertex\": \"Presiona para colocar el primer vértice\",\n \"continueLine\": \"Presiona para continuar dibujando\",\n \"finishLine\": \"Presiona cualquier marcador existente para finalizar\",\n \"finishPoly\": \"Presiona el primer marcador para finalizar\",\n \"finishRect\": \"Presiona para finalizar\",\n \"startCircle\": \"Presiona para colocar el centro del círculo\",\n \"finishCircle\": \"Presiona para finalizar el círculo\",\n \"placeCircleMarker\": \"Presiona para colocar un marcador de círculo\"\n },\n \"actions\": {\n \"finish\": \"Finalizar\",\n \"cancel\": \"Cancelar\",\n \"removeLastVertex\": \"Eliminar último vértice\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Dibujar Marcador\",\n \"drawPolyButton\": \"Dibujar Polígono\",\n \"drawLineButton\": \"Dibujar Línea\",\n \"drawCircleButton\": \"Dibujar Círculo\",\n \"drawRectButton\": \"Dibujar Rectángulo\",\n \"editButton\": \"Editar Capas\",\n \"dragButton\": \"Arrastrar Capas\",\n \"cutButton\": \"Cortar Capas\",\n \"deleteButton\": \"Eliminar Capas\",\n \"drawCircleMarkerButton\": \"Dibujar Marcador de Círculo\",\n \"snappingButton\": \"El marcador de Snap arrastrado a otras capas y vértices\",\n \"pinningButton\": \"Fijar juntos los vértices compartidos\",\n \"rotateButton\": \"Rotar capa\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Klik om een marker te plaatsen\",\n \"firstVertex\": \"Klik om het eerste punt te plaatsen\",\n \"continueLine\": \"Klik om te blijven tekenen\",\n \"finishLine\": \"Klik op een bestaand punt om te beëindigen\",\n \"finishPoly\": \"Klik op het eerst punt om te beëindigen\",\n \"finishRect\": \"Klik om te beëindigen\",\n \"startCircle\": \"Klik om het middelpunt te plaatsen\",\n \"finishCircle\": \"Klik om de cirkel te beëindigen\",\n \"placeCircleMarker\": \"Klik om een marker te plaatsen\"\n },\n \"actions\": {\n \"finish\": \"Bewaar\",\n \"cancel\": \"Annuleer\",\n \"removeLastVertex\": \"Verwijder laatste punt\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Plaats Marker\",\n \"drawPolyButton\": \"Teken een vlak\",\n \"drawLineButton\": \"Teken een lijn\",\n \"drawCircleButton\": \"Teken een cirkel\",\n \"drawRectButton\": \"Teken een vierkant\",\n \"editButton\": \"Bewerk\",\n \"dragButton\": \"Verplaats\",\n \"cutButton\": \"Knip\",\n \"deleteButton\": \"Verwijder\",\n \"drawCircleMarkerButton\": \"Plaats Marker\",\n \"snappingButton\": \"Snap gesleepte marker naar andere lagen en hoekpunten\",\n \"pinningButton\": \"Speld gedeelde hoekpunten samen\",\n \"rotateButton\": \"Laag roteren\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Cliquez pour placer un marqueur\",\n \"firstVertex\": \"Cliquez pour placer le premier sommet\",\n \"continueLine\": \"Cliquez pour continuer à dessiner\",\n \"finishLine\": \"Cliquez sur n'importe quel marqueur pour terminer\",\n \"finishPoly\": \"Cliquez sur le premier marqueur pour terminer\",\n \"finishRect\": \"Cliquez pour terminer\",\n \"startCircle\": \"Cliquez pour placer le centre du cercle\",\n \"finishCircle\": \"Cliquez pour finir le cercle\",\n \"placeCircleMarker\": \"Cliquez pour placer le marqueur circulaire\"\n },\n \"actions\": {\n \"finish\": \"Terminer\",\n \"cancel\": \"Annuler\",\n \"removeLastVertex\": \"Retirer le dernier sommet\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Placer des marqueurs\",\n \"drawPolyButton\": \"Dessiner des polygones\",\n \"drawLineButton\": \"Dessiner des polylignes\",\n \"drawCircleButton\": \"Dessiner un cercle\",\n \"drawRectButton\": \"Dessiner un rectangle\",\n \"editButton\": \"Éditer des calques\",\n \"dragButton\": \"Déplacer des calques\",\n \"cutButton\": \"Couper des calques\",\n \"deleteButton\": \"Supprimer des calques\",\n \"drawCircleMarkerButton\": \"Dessiner un marqueur circulaire\",\n \"snappingButton\": \"Glisser le marqueur vers d'autres couches et sommets\",\n \"pinningButton\": \"Épingler ensemble les sommets partagés\",\n \"rotateButton\": \"Tourner des calques\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Clique para posicionar o marcador\",\n \"firstVertex\": \"Clique para posicionar o primeiro vértice\",\n \"continueLine\": \"Clique para continuar desenhando\",\n \"finishLine\": \"Clique em qualquer marcador existente para finalizar\",\n \"finishPoly\": \"Clique no primeiro marcador para finalizar\",\n \"finishRect\": \"Clique para finalizar\",\n \"startCircle\": \"Clique para posicionar o centro do círculo\",\n \"finishCircle\": \"Clique para finalizar o círculo\",\n \"placeCircleMarker\": \"Clique para posicionar o marcador circular\",\n \"placeText\": \"Clique para inserir texto\"\n },\n \"actions\": {\n \"finish\": \"Finalizar\",\n \"cancel\": \"Cancelar\",\n \"removeLastVertex\": \"Remover último vértice\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Desenhar Marcador\",\n \"drawPolyButton\": \"Desenhar Polígonos\",\n \"drawLineButton\": \"Desenhar Linha Poligonal\",\n \"drawCircleButton\": \"Desenhar Círculo\",\n \"drawRectButton\": \"Desenhar Retângulo\",\n \"editButton\": \"Editar Camadas\",\n \"dragButton\": \"Arrastar Camadas\",\n \"cutButton\": \"Recortar Camadas\",\n \"deleteButton\": \"Remover Camadas\",\n \"drawCircleMarkerButton\": \"Desenhar Marcador de Círculo\",\n \"snappingButton\": \"Ajustar marcador arrastado a outras camadas e vértices\",\n \"pinningButton\": \"Unir vértices compartilhados\",\n \"rotateButton\": \"Rotacionar Camadas\",\n \"drawTextButton\": \"Desenhar Texto\",\n \"scaleButton\": \"Redimensionar Camadas\",\n \"autoTracingButton\": \"Traçado Automático de Linha\"\n },\n \"measurements\": {\n \"totalLength\": \"Comprimento\",\n \"segmentLength\": \"Comprimento do Segmento\",\n \"area\": \"Área\",\n \"radius\": \"Raio\",\n \"perimeter\": \"Perímetro\",\n \"height\": \"Altura\",\n \"width\": \"Largura\",\n \"coordinates\": \"Posição\",\n \"coordinatesMarker\": \"Marcador de Posição\"\n }\n}","{\n \"tooltips\": {\n \"placeMarker\": \"Clique para colocar marcador\",\n \"firstVertex\": \"Clique para colocar primeiro vértice\",\n \"continueLine\": \"Clique para continuar a desenhar\",\n \"finishLine\": \"Clique num marcador existente para terminar\",\n \"finishPoly\": \"Clique no primeiro marcador para terminar\",\n \"finishRect\": \"Clique para terminar\",\n \"startCircle\": \"Clique para colocar o centro do círculo\",\n \"finishCircle\": \"Clique para terminar o círculo\",\n \"placeCircleMarker\": \"Clique para colocar marcador de círculo\",\n \"placeText\": \"Clique para colocar texto\"\n },\n \"actions\": {\n \"finish\": \"Terminar\",\n \"cancel\": \"Cancelar\",\n \"removeLastVertex\": \"Remover Último Vértice\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Desenhar Marcador\",\n \"drawPolyButton\": \"Desenhar Polígonos\",\n \"drawLineButton\": \"Desenhar Polilinha\",\n \"drawCircleButton\": \"Desenhar Círculo\",\n \"drawRectButton\": \"Desenhar Retângulo\",\n \"editButton\": \"Editar Camadas\",\n \"dragButton\": \"Arrastar Camadas\",\n \"cutButton\": \"Cortar Camadas\",\n \"deleteButton\": \"Remover Camadas\",\n \"drawCircleMarkerButton\": \"Desenhar Marcador de Círculo\",\n \"snappingButton\": \"Ajustar marcador arrastado a outras camadas e vértices\",\n \"pinningButton\": \"Unir vértices partilhados\",\n \"rotateButton\": \"Rodar Camadas\",\n \"drawTextButton\": \"Desenhar Texto\",\n \"scaleButton\": \"Escalar Camadas\",\n \"autoTracingButton\": \"Traçado Automático de Linha\"\n },\n \"measurements\": {\n \"totalLength\": \"Comprimento\",\n \"segmentLength\": \"Comprimento do Segmento\",\n \"area\": \"Área\",\n \"radius\": \"Raio\",\n \"perimeter\": \"Perímetro\",\n \"height\": \"Altura\",\n \"width\": \"Largura\",\n \"coordinates\": \"Posição\",\n \"coordinatesMarker\": \"Marcador de Posição\"\n }\n}","{\n \"tooltips\": {\n \"placeMarker\": \"单击放置标记\",\n \"firstVertex\": \"单击放置首个顶点\",\n \"continueLine\": \"单击继续绘制\",\n \"finishLine\": \"单击任何存在的标记以完成\",\n \"finishPoly\": \"单击第一个标记以完成\",\n \"finishRect\": \"单击完成\",\n \"startCircle\": \"单击放置圆心\",\n \"finishCircle\": \"单击完成圆形\",\n \"placeCircleMarker\": \"点击放置圆形标记\"\n },\n \"actions\": {\n \"finish\": \"完成\",\n \"cancel\": \"取消\",\n \"removeLastVertex\": \"移除最后的顶点\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"绘制标记\",\n \"drawPolyButton\": \"绘制多边形\",\n \"drawLineButton\": \"绘制线段\",\n \"drawCircleButton\": \"绘制圆形\",\n \"drawRectButton\": \"绘制长方形\",\n \"editButton\": \"编辑图层\",\n \"dragButton\": \"拖拽图层\",\n \"cutButton\": \"剪切图层\",\n \"deleteButton\": \"删除图层\",\n \"drawCircleMarkerButton\": \"画圆圈标记\",\n \"snappingButton\": \"将拖动的标记捕捉到其他图层和顶点\",\n \"pinningButton\": \"将共享顶点固定在一起\",\n \"rotateButton\": \"旋转图层\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"單擊放置標記\",\n \"firstVertex\": \"單擊放置第一個頂點\",\n \"continueLine\": \"單擊繼續繪製\",\n \"finishLine\": \"單擊任何存在的標記以完成\",\n \"finishPoly\": \"單擊第一個標記以完成\",\n \"finishRect\": \"單擊完成\",\n \"startCircle\": \"單擊放置圓心\",\n \"finishCircle\": \"單擊完成圓形\",\n \"placeCircleMarker\": \"點擊放置圓形標記\"\n },\n \"actions\": {\n \"finish\": \"完成\",\n \"cancel\": \"取消\",\n \"removeLastVertex\": \"移除最後一個頂點\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"放置標記\",\n \"drawPolyButton\": \"繪製多邊形\",\n \"drawLineButton\": \"繪製線段\",\n \"drawCircleButton\": \"繪製圓形\",\n \"drawRectButton\": \"繪製方形\",\n \"editButton\": \"編輯圖形\",\n \"dragButton\": \"移動圖形\",\n \"cutButton\": \"裁切圖形\",\n \"deleteButton\": \"刪除圖形\",\n \"drawCircleMarkerButton\": \"畫圓圈標記\",\n \"snappingButton\": \"將拖動的標記對齊到其他圖層和頂點\",\n \"pinningButton\": \"將共享頂點固定在一起\",\n \"rotateButton\": \"旋轉圖形\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Kliknij, aby umieścić znacznik\",\n \"firstVertex\": \"Kliknij, aby umieścić pierwszy wierzchołek\",\n \"continueLine\": \"Kliknij, aby kontynuować rysowanie\",\n \"finishLine\": \"Kliknij dowolny istniejący znacznik, aby zakończyć\",\n \"finishPoly\": \"Kliknij pierwszy znacznik, aby zakończyć\",\n \"finishRect\": \"Kliknij, aby zakończyć\",\n \"startCircle\": \"Kliknij, aby umieścić środek okręgu\",\n \"finishCircle\": \"Kliknij, aby zakończyć okrąg\",\n \"placeCircleMarker\": \"Kliknij, aby umieścić znacznik okręgu\",\n \"placeText\": \"Kliknij, aby umieścić tekst\"\n },\n \"actions\": {\n \"finish\": \"Zakończ\",\n \"cancel\": \"Anuluj\",\n \"removeLastVertex\": \"Usuń ostatni wierzchołek\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Rysuj znacznik\",\n \"drawPolyButton\": \"Rysuj wielokąt\",\n \"drawLineButton\": \"Rysuj linię\",\n \"drawCircleButton\": \"Rysuj okrąg\",\n \"drawRectButton\": \"Rysuj prostokąt\",\n \"editButton\": \"Edytuj warstwy\",\n \"dragButton\": \"Przeciągnij warstwy\",\n \"cutButton\": \"Wytnij warstwy\",\n \"deleteButton\": \"Usuń warstwy\",\n \"drawCircleMarkerButton\": \"Rysuj znacznik okrągły\",\n \"snappingButton\": \"Przyciągnij przenoszony znacznik do innych warstw i wierzchołków\",\n \"pinningButton\": \"Przypnij wspólne wierzchołki razem\",\n \"rotateButton\": \"Obróć warstwy\",\n \"drawTextButton\": \"Rysuj tekst\",\n \"scaleButton\": \"Skaluj warstwy\",\n \"autoTracingButton\": \"Automatyczne śledzenie linii\"\n },\n \"measurements\": {\n \"totalLength\": \"Długość\",\n \"segmentLength\": \"Długość odcinka\",\n \"area\": \"Obszar\",\n \"radius\": \"Promień\",\n \"perimeter\": \"Obwód\",\n \"height\": \"Wysokość\",\n \"width\": \"Szerokość\",\n \"coordinates\": \"Pozycja\",\n \"coordinatesMarker\": \"Znacznik pozycji\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Klicka för att placera markör\",\n \"firstVertex\": \"Klicka för att placera första hörnet\",\n \"continueLine\": \"Klicka för att fortsätta rita\",\n \"finishLine\": \"Klicka på en existerande punkt för att slutföra\",\n \"finishPoly\": \"Klicka på den första punkten för att slutföra\",\n \"finishRect\": \"Klicka för att slutföra\",\n \"startCircle\": \"Klicka för att placera cirkelns centrum\",\n \"finishCircle\": \"Klicka för att slutföra cirkeln\",\n \"placeCircleMarker\": \"Klicka för att placera cirkelmarkör\"\n },\n \"actions\": {\n \"finish\": \"Slutför\",\n \"cancel\": \"Avbryt\",\n \"removeLastVertex\": \"Ta bort sista hörnet\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Rita Markör\",\n \"drawPolyButton\": \"Rita Polygoner\",\n \"drawLineButton\": \"Rita Linje\",\n \"drawCircleButton\": \"Rita Cirkel\",\n \"drawRectButton\": \"Rita Rektangel\",\n \"editButton\": \"Redigera Lager\",\n \"dragButton\": \"Dra Lager\",\n \"cutButton\": \"Klipp i Lager\",\n \"deleteButton\": \"Ta bort Lager\",\n \"drawCircleMarkerButton\": \"Rita Cirkelmarkör\",\n \"snappingButton\": \"Snäpp dra markören till andra lager och hörn\",\n \"pinningButton\": \"Fäst delade hörn tillsammans\",\n \"rotateButton\": \"Rotera lagret\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Κάντε κλικ για να τοποθετήσετε Δείκτη\",\n \"firstVertex\": \"Κάντε κλικ για να τοποθετήσετε το πρώτο σημείο\",\n \"continueLine\": \"Κάντε κλικ για να συνεχίσετε να σχεδιάζετε\",\n \"finishLine\": \"Κάντε κλικ σε οποιονδήποτε υπάρχον σημείο για να ολοκληρωθεί\",\n \"finishPoly\": \"Κάντε κλικ στο πρώτο σημείο για να τελειώσετε\",\n \"finishRect\": \"Κάντε κλικ για να τελειώσετε\",\n \"startCircle\": \"Κάντε κλικ για να τοποθετήσετε κέντρο Κύκλου\",\n \"finishCircle\": \"Κάντε κλικ για να ολοκληρώσετε τον Κύκλο\",\n \"placeCircleMarker\": \"Κάντε κλικ για να τοποθετήσετε Κυκλικό Δείκτη\"\n },\n \"actions\": {\n \"finish\": \"Τέλος\",\n \"cancel\": \"Ακύρωση\",\n \"removeLastVertex\": \"Κατάργηση τελευταίου σημείου\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Σχεδίαση Δείκτη\",\n \"drawPolyButton\": \"Σχεδίαση Πολυγώνου\",\n \"drawLineButton\": \"Σχεδίαση Γραμμής\",\n \"drawCircleButton\": \"Σχεδίαση Κύκλου\",\n \"drawRectButton\": \"Σχεδίαση Ορθογωνίου\",\n \"editButton\": \"Επεξεργασία Επιπέδων\",\n \"dragButton\": \"Μεταφορά Επιπέδων\",\n \"cutButton\": \"Αποκοπή Επιπέδων\",\n \"deleteButton\": \"Κατάργηση Επιπέδων\",\n \"drawCircleMarkerButton\": \"Σχεδίαση Κυκλικού Δείκτη\",\n \"snappingButton\": \"Προσκόλληση του Δείκτη μεταφοράς σε άλλα Επίπεδα και Κορυφές\",\n \"pinningButton\": \"Περικοπή κοινών κορυφών μαζί\",\n \"rotateButton\": \"Περιστρέψτε το στρώμα\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Kattintson a jelölő elhelyezéséhez\",\n \"firstVertex\": \"Kattintson az első pont elhelyezéséhez\",\n \"continueLine\": \"Kattintson a következő pont elhelyezéséhez\",\n \"finishLine\": \"A befejezéshez kattintson egy meglévő pontra\",\n \"finishPoly\": \"A befejezéshez kattintson az első pontra\",\n \"finishRect\": \"Kattintson a befejezéshez\",\n \"startCircle\": \"Kattintson a kör középpontjának elhelyezéséhez\",\n \"finishCircle\": \"Kattintson a kör befejezéséhez\",\n \"placeCircleMarker\": \"Kattintson a körjelölő elhelyezéséhez\"\n },\n \"actions\": {\n \"finish\": \"Befejezés\",\n \"cancel\": \"Mégse\",\n \"removeLastVertex\": \"Utolsó pont eltávolítása\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Jelölő rajzolása\",\n \"drawPolyButton\": \"Poligon rajzolása\",\n \"drawLineButton\": \"Vonal rajzolása\",\n \"drawCircleButton\": \"Kör rajzolása\",\n \"drawRectButton\": \"Négyzet rajzolása\",\n \"editButton\": \"Elemek szerkesztése\",\n \"dragButton\": \"Elemek mozgatása\",\n \"cutButton\": \"Elemek vágása\",\n \"deleteButton\": \"Elemek törlése\",\n \"drawCircleMarkerButton\": \"Kör jelölő rajzolása\",\n \"snappingButton\": \"Kapcsolja a jelöltőt másik elemhez vagy ponthoz\",\n \"pinningButton\": \"Közös pontok összekötése\",\n \"rotateButton\": \"Fólia elforgatása\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Tryk for at placere en markør\",\n \"firstVertex\": \"Tryk for at placere det første punkt\",\n \"continueLine\": \"Tryk for at fortsætte linjen\",\n \"finishLine\": \"Tryk på et eksisterende punkt for at afslutte\",\n \"finishPoly\": \"Tryk på det første punkt for at afslutte\",\n \"finishRect\": \"Tryk for at afslutte\",\n \"startCircle\": \"Tryk for at placere cirklens center\",\n \"finishCircle\": \"Tryk for at afslutte cirklen\",\n \"placeCircleMarker\": \"Tryk for at placere en cirkelmarkør\"\n },\n \"actions\": {\n \"finish\": \"Afslut\",\n \"cancel\": \"Afbryd\",\n \"removeLastVertex\": \"Fjern sidste punkt\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Placer markør\",\n \"drawPolyButton\": \"Tegn polygon\",\n \"drawLineButton\": \"Tegn linje\",\n \"drawCircleButton\": \"Tegn cirkel\",\n \"drawRectButton\": \"Tegn firkant\",\n \"editButton\": \"Rediger\",\n \"dragButton\": \"Træk\",\n \"cutButton\": \"Klip\",\n \"deleteButton\": \"Fjern\",\n \"drawCircleMarkerButton\": \"Tegn cirkelmarkør\",\n \"snappingButton\": \"Fastgør trukket markør til andre elementer\",\n \"pinningButton\": \"Sammenlæg delte elementer\",\n \"rotateButton\": \"Roter laget\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Klikk for å plassere punkt\",\n \"firstVertex\": \"Klikk for å plassere første punkt\",\n \"continueLine\": \"Klikk for å tegne videre\",\n \"finishLine\": \"Klikk på et eksisterende punkt for å fullføre\",\n \"finishPoly\": \"Klikk første punkt for å fullføre\",\n \"finishRect\": \"Klikk for å fullføre\",\n \"startCircle\": \"Klikk for å sette sirkel midtpunkt\",\n \"finishCircle\": \"Klikk for å fullføre sirkel\",\n \"placeCircleMarker\": \"Klikk for å plassere sirkel\",\n \"placeText\": \"Klikk for å plassere tekst\"\n },\n \"actions\": {\n \"finish\": \"Fullfør\",\n \"cancel\": \"Kanseller\",\n \"removeLastVertex\": \"Fjern forrige punkt\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Tegn punkt\",\n \"drawPolyButton\": \"Tegn flate\",\n \"drawLineButton\": \"Tegn linje\",\n \"drawCircleButton\": \"Tegn sirkel\",\n \"drawRectButton\": \"Tegn rektangel\",\n \"editButton\": \"Rediger objekter\",\n \"dragButton\": \"Dra objekter\",\n \"cutButton\": \"Kutt objekter\",\n \"deleteButton\": \"Fjern objekter\",\n \"drawCircleMarkerButton\": \"Tegn sirkel-punkt\",\n \"snappingButton\": \"Fest dratt punkt til andre objekter og punkt\",\n \"pinningButton\": \"Pin delte punkter sammen\",\n \"rotateButton\": \"Rotér objekter\",\n \"drawTextButton\": \"Tegn tekst\",\n \"scaleButton\": \"Skalér objekter\",\n \"autoTracingButton\": \"Automatisk sporing av linje\"\n },\n \"measurements\": {\n \"totalLength\": \"Lengde\",\n \"segmentLength\": \"Segmentlengde\",\n \"area\": \"Område\",\n \"radius\": \"Radius\",\n \"perimeter\": \"Omriss\",\n \"height\": \"Høyde\",\n \"width\": \"Bredde\",\n \"coordinates\": \"Posisjon\",\n \"coordinatesMarker\": \"Posisjonsmarkør\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"کلیک برای جانمایی نشان\",\n \"firstVertex\": \"کلیک برای رسم اولین رأس\",\n \"continueLine\": \"کلیک برای ادامه رسم\",\n \"finishLine\": \"کلیک روی هر نشان موجود برای پایان\",\n \"finishPoly\": \"کلیک روی اولین نشان برای پایان\",\n \"finishRect\": \"کلیک برای پایان\",\n \"startCircle\": \"کلیک برای رسم مرکز دایره\",\n \"finishCircle\": \"کلیک برای پایان رسم دایره\",\n \"placeCircleMarker\": \"کلیک برای رسم نشان دایره\",\n \"placeText\": \"کلیک برای نوشتن متن\"\n },\n \"actions\": {\n \"finish\": \"پایان\",\n \"cancel\": \"لفو\",\n \"removeLastVertex\": \"حذف آخرین رأس\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"درج نشان\",\n \"drawPolyButton\": \"رسم چندضلعی\",\n \"drawLineButton\": \"رسم خط\",\n \"drawCircleButton\": \"رسم دایره\",\n \"drawRectButton\": \"رسم چهارضلعی\",\n \"editButton\": \"ویرایش لایهها\",\n \"dragButton\": \"جابجایی لایهها\",\n \"cutButton\": \"برش لایهها\",\n \"deleteButton\": \"حذف لایهها\",\n \"drawCircleMarkerButton\": \"رسم نشان دایره\",\n \"snappingButton\": \"نشانگر را به لایهها و رئوس دیگر بکشید\",\n \"pinningButton\": \"رئوس مشترک را با هم پین کنید\",\n \"rotateButton\": \"چرخش لایه\",\n \"drawTextButton\": \"رسم متن\",\n \"scaleButton\": \"مقیاسگذاری\",\n \"autoTracingButton\": \"ردیاب خودکار\"\n },\n \"measurements\": {\n \"totalLength\": \"طول\",\n \"segmentLength\": \"طول بخش\",\n \"area\": \"ناحیه\",\n \"radius\": \"شعاع\",\n \"perimeter\": \"محیط\",\n \"height\": \"ارتفاع\",\n \"width\": \"عرض\",\n \"coordinates\": \"موقعیت\",\n \"coordinatesMarker\": \"موقعیت نشان\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Натисніть, щоб нанести маркер\",\n \"firstVertex\": \"Натисніть, щоб нанести першу вершину\",\n \"continueLine\": \"Натисніть, щоб продовжити малювати\",\n \"finishLine\": \"Натисніть будь-який існуючий маркер для завершення\",\n \"finishPoly\": \"Виберіть перший маркер, щоб завершити\",\n \"finishRect\": \"Натисніть, щоб завершити\",\n \"startCircle\": \"Натисніть, щоб додати центр кола\",\n \"finishCircle\": \"Натисніть, щоб завершити коло\",\n \"placeCircleMarker\": \"Натисніть, щоб нанести круговий маркер\"\n },\n \"actions\": {\n \"finish\": \"Завершити\",\n \"cancel\": \"Відмінити\",\n \"removeLastVertex\": \"Видалити попередню вершину\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Малювати маркер\",\n \"drawPolyButton\": \"Малювати полігон\",\n \"drawLineButton\": \"Малювати криву\",\n \"drawCircleButton\": \"Малювати коло\",\n \"drawRectButton\": \"Малювати прямокутник\",\n \"editButton\": \"Редагувати шари\",\n \"dragButton\": \"Перенести шари\",\n \"cutButton\": \"Вирізати шари\",\n \"deleteButton\": \"Видалити шари\",\n \"drawCircleMarkerButton\": \"Малювати круговий маркер\",\n \"snappingButton\": \"Прив’язати перетягнутий маркер до інших шарів та вершин\",\n \"pinningButton\": \"Зв'язати спільні вершини разом\",\n \"rotateButton\": \"Повернути шар\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"İşaretçi yerleştirmek için tıklayın\",\n \"firstVertex\": \"İlk tepe noktasını yerleştirmek için tıklayın\",\n \"continueLine\": \"Çizime devam etmek için tıklayın\",\n \"finishLine\": \"Bitirmek için mevcut herhangi bir işaretçiyi tıklayın\",\n \"finishPoly\": \"Bitirmek için ilk işaretçiyi tıklayın\",\n \"finishRect\": \"Bitirmek için tıklayın\",\n \"startCircle\": \"Daire merkezine yerleştirmek için tıklayın\",\n \"finishCircle\": \"Daireyi bitirmek için tıklayın\",\n \"placeCircleMarker\": \"Daire işaretçisi yerleştirmek için tıklayın\"\n },\n \"actions\": {\n \"finish\": \"Bitir\",\n \"cancel\": \"İptal\",\n \"removeLastVertex\": \"Son köşeyi kaldır\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Çizim İşaretçisi\",\n \"drawPolyButton\": \"Çokgenler çiz\",\n \"drawLineButton\": \"Çoklu çizgi çiz\",\n \"drawCircleButton\": \"Çember çiz\",\n \"drawRectButton\": \"Dikdörtgen çiz\",\n \"editButton\": \"Katmanları düzenle\",\n \"dragButton\": \"Katmanları sürükle\",\n \"cutButton\": \"Katmanları kes\",\n \"deleteButton\": \"Katmanları kaldır\",\n \"drawCircleMarkerButton\": \"Daire işaretçisi çiz\",\n \"snappingButton\": \"Sürüklenen işaretçiyi diğer katmanlara ve köşelere yapıştır\",\n \"pinningButton\": \"Paylaşılan köşeleri birbirine sabitle\",\n \"rotateButton\": \"Katmanı döndür\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Kliknutím vytvoříte značku\",\n \"firstVertex\": \"Kliknutím vytvoříte první objekt\",\n \"continueLine\": \"Kliknutím pokračujte v kreslení\",\n \"finishLine\": \"Kliknutí na libovolnou existující značku pro dokončení\",\n \"finishPoly\": \"Vyberte první bod pro dokončení\",\n \"finishRect\": \"Klikněte pro dokončení\",\n \"startCircle\": \"Kliknutím přidejte střed kruhu\",\n \"finishCircle\": \"Нажмите, чтобы задать радиус\",\n \"placeCircleMarker\": \"Kliknutím nastavte poloměr\"\n },\n \"actions\": {\n \"finish\": \"Dokončit\",\n \"cancel\": \"Zrušit\",\n \"removeLastVertex\": \"Zrušit poslední akci\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Přidat značku\",\n \"drawPolyButton\": \"Nakreslit polygon\",\n \"drawLineButton\": \"Nakreslit křivku\",\n \"drawCircleButton\": \"Nakreslit kruh\",\n \"drawRectButton\": \"Nakreslit obdélník\",\n \"editButton\": \"Upravit vrstvu\",\n \"dragButton\": \"Přeneste vrstvu\",\n \"cutButton\": \"Vyjmout vrstvu\",\n \"deleteButton\": \"Smazat vrstvu\",\n \"drawCircleMarkerButton\": \"Přidat kruhovou značku\",\n \"snappingButton\": \"Navázat tažnou značku k dalším vrstvám a vrcholům\",\n \"pinningButton\": \"Spojit společné body dohromady\",\n \"rotateButton\": \"Otočte vrstvu\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"クリックしてマーカーを配置\",\n \"firstVertex\": \"クリックして最初の頂点を配置\",\n \"continueLine\": \"クリックして描画を続ける\",\n \"finishLine\": \"任意のマーカーをクリックして終了\",\n \"finishPoly\": \"最初のマーカーをクリックして終了\",\n \"finishRect\": \"クリックして終了\",\n \"startCircle\": \"クリックして円の中心を配置\",\n \"finishCircle\": \"クリックして円の描画を終了\",\n \"placeCircleMarker\": \"クリックして円マーカーを配置\",\n \"placeText\": \"クリックしてテキストを配置\"\n },\n \"actions\": {\n \"finish\": \"終了\",\n \"cancel\": \"キャンセル\",\n \"removeLastVertex\": \"最後の頂点を削除\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"マーカーを描画\",\n \"drawPolyButton\": \"ポリゴンを描画\",\n \"drawLineButton\": \"折れ線を描画\",\n \"drawCircleButton\": \"円を描画\",\n \"drawRectButton\": \"矩形を描画\",\n \"editButton\": \"レイヤーを編集\",\n \"dragButton\": \"レイヤーをドラッグ\",\n \"cutButton\": \"レイヤーを切り取り\",\n \"deleteButton\": \"レイヤーを削除\",\n \"drawCircleMarkerButton\": \"円マーカーを描画\",\n \"snappingButton\": \"ドラッグしたマーカーを他のレイヤーや頂点にスナップする\",\n \"pinningButton\": \"共有する頂点を同時に動かす\",\n \"rotateButton\": \"レイヤーを回転\",\n \"drawTextButton\": \"テキストを描画\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Klikkaa asettaaksesi merkin\",\n \"firstVertex\": \"Klikkaa asettaakseni ensimmäisen osuuden\",\n \"continueLine\": \"Klikkaa jatkaaksesi piirtämistä\",\n \"finishLine\": \"Klikkaa olemassa olevaa merkkiä lopettaaksesi\",\n \"finishPoly\": \"Klikkaa ensimmäistä merkkiä lopettaaksesi\",\n \"finishRect\": \"Klikkaa lopettaaksesi\",\n \"startCircle\": \"Klikkaa asettaaksesi ympyrän keskipisteen\",\n \"finishCircle\": \"Klikkaa lopettaaksesi ympyrän\",\n \"placeCircleMarker\": \"Klikkaa asettaaksesi ympyrämerkin\",\n \"placeText\": \"Klikkaa asettaaksesi tekstin\"\n },\n \"actions\": {\n \"finish\": \"Valmis\",\n \"cancel\": \"Peruuta\",\n \"removeLastVertex\": \"Poista viimeinen osuus\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Piirrä merkkejä\",\n \"drawPolyButton\": \"Piirrä monikulmioita\",\n \"drawLineButton\": \"Piirrä viivoja\",\n \"drawCircleButton\": \"Piirrä ympyrä\",\n \"drawRectButton\": \"Piirrä neliskulmioita\",\n \"editButton\": \"Muokkaa\",\n \"dragButton\": \"Siirrä\",\n \"cutButton\": \"Leikkaa\",\n \"deleteButton\": \"Poista\",\n \"drawCircleMarkerButton\": \"Piirrä ympyrämerkki\",\n \"snappingButton\": \"Kiinnitä siirrettävä merkki toisiin muotoihin\",\n \"pinningButton\": \"Kiinnitä jaetut muodot yhteen\",\n \"rotateButton\": \"Käännä\",\n \"drawTextButton\": \"Piirrä tekstiä\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"마커 위치를 클릭하세요\",\n \"firstVertex\": \"첫번째 꼭지점 위치을 클릭하세요\",\n \"continueLine\": \"계속 그리려면 클릭하세요\",\n \"finishLine\": \"끝내려면 기존 마커를 클릭하세요\",\n \"finishPoly\": \"끝내려면 처음 마커를 클릭하세요\",\n \"finishRect\": \"끝내려면 클릭하세요\",\n \"startCircle\": \"원의 중심이 될 위치를 클릭하세요\",\n \"finishCircle\": \"원을 끝내려면 클릭하세요\",\n \"placeCircleMarker\": \"원 마커 위치를 클릭하세요\",\n \"placeText\": \"텍스트 위치를 클릭하세요\"\n },\n \"actions\": {\n \"finish\": \"끝내기\",\n \"cancel\": \"취소\",\n \"removeLastVertex\": \"마지막 꼭지점 제거\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"마커 그리기\",\n \"drawPolyButton\": \"다각형 그리기\",\n \"drawLineButton\": \"다각선 그리기\",\n \"drawCircleButton\": \"원 그리기\",\n \"drawRectButton\": \"직사각형 그리기\",\n \"editButton\": \"레이어 편집하기\",\n \"dragButton\": \"레이어 끌기\",\n \"cutButton\": \"레이어 자르기\",\n \"deleteButton\": \"레이어 제거하기\",\n \"drawCircleMarkerButton\": \"원 마커 그리기\",\n \"snappingButton\": \"잡아끈 마커를 다른 레이어 및 꼭지점에 들러붙게 하기\",\n \"pinningButton\": \"공유 꼭지점을 함께 찍기\",\n \"rotateButton\": \"레이어 회전하기\",\n \"drawTextButton\": \"텍스트 그리기\"\n }\n}\n","{\n \"tooltips\": {\n \"placeMarker\": \"Маркерди жайгаштыруу үчүн басыңыз\",\n \"firstVertex\": \"Биринчи чокуну жайгаштырууну үчүн басыңыз\",\n \"continueLine\": \"Сүрөт тартууну улантуу үчүн басыңыз\",\n \"finishLine\": \"Аяктоо үчүн учурдагы маркерди басыңыз\",\n \"finishPoly\": \"Бүтүрүү үчүн биринчи маркерди басыңыз\",\n \"finishRect\": \"Бүтүрүү үчүн басыңыз\",\n \"startCircle\": \"Айлананын борборун жайгаштырууну үчүн басыңыз\",\n \"finishCircle\": \"Айлананы бүтүрүү үчүн басыңыз\",\n \"placeCircleMarker\": \"Тегерек маркерди жайгаштыруу үчүн басыңыз\",\n \"placeText\": \"Текстти жайгаштыруу үчүн басыңыз\"\n },\n \"actions\": {\n \"finish\": \"Аягы\",\n \"cancel\": \"Жок кылуу\",\n \"removeLastVertex\": \"Акыркы чокуну өчүрүү\"\n },\n \"buttonTitles\": {\n \"drawMarkerButton\": \"Маркерди чизуу\",\n \"drawPolyButton\": \"Полигон чизуу\",\n \"drawLineButton\": \"Полилиния чизуу\",\n \"drawCircleButton\": \"Дайынды чизуу\",\n \"drawRectButton\": \"Прямоугольник чизуу\",\n \"editButton\": \"Слоопту түзөтүү\",\n \"dragButton\": \"Слоопту карап сүйлөү\",\n \"cutButton\": \"Слооптун башын кесүү\",\n \"deleteButton\": \"Слооптун өчүрүү\",\n \"drawCircleMarkerButton\": \"Дайынды маркерди чизуу\",\n \"snappingButton\": \"Башка слооптордун жана вертекстердин арасына чекилдөө\",\n \"pinningButton\": \"Бөлүшкөн вертекстерди бирге тутуштуруу\",\n \"rotateButton\": \"Слооптун өзгөртүү\",\n \"drawTextButton\": \"Текст чизуу\",\n \"scaleButton\": \"Слооптун өлчөмүн өзгөртүү\",\n \"autoTracingButton\": \"Автоматтык тизмеги чизуу\"\n },\n \"measurements\": {\n \"totalLength\": \"Узундук\",\n \"segmentLength\": \"Сегмент узундугу\",\n \"area\": \"Аймак\",\n \"radius\": \"Радиус\",\n \"perimeter\": \"Периметр\",\n \"height\": \"Диаметр\",\n \"width\": \"Кенчилик\",\n \"coordinates\": \"Координаттар\",\n \"coordinatesMarker\": \"Маркердин координаттары\"\n }\n}\n","// this mixin adds a global edit mode to the map\nconst GlobalEditMode = {\n _globalEditModeEnabled: false,\n enableGlobalEditMode(o) {\n const options = {\n ...o,\n };\n // set status\n this._globalEditModeEnabled = true;\n\n // Set toolbar button to currect status\n this.Toolbar.toggleButton('editMode', this.globalEditModeEnabled());\n\n // find all layers handled by leaflet-geoman\n const layers = L.PM.Utils.findLayers(this.map);\n\n // enable all layers\n layers.forEach((layer) => {\n if (this._isRelevantForEdit(layer)) {\n layer.pm.enable(options);\n }\n });\n\n if (!this.throttledReInitEdit) {\n this.throttledReInitEdit = L.Util.throttle(\n this.handleLayerAdditionInGlobalEditMode,\n 100,\n this\n );\n }\n\n // save the added layers into the _addedLayersEdit array, to read it later out\n this._addedLayersEdit = {};\n this.map.on('layeradd', this._layerAddedEdit, this);\n // handle layers that are added while in edit mode\n this.map.on('layeradd', this.throttledReInitEdit, this);\n\n // fire event\n this._fireGlobalEditModeToggled(true);\n },\n disableGlobalEditMode() {\n // set status\n this._globalEditModeEnabled = false;\n\n // find all layers handles by leaflet-geoman\n const layers = L.PM.Utils.findLayers(this.map);\n\n // disable all layers\n layers.forEach((layer) => {\n layer.pm.disable();\n });\n\n // cleanup layer off event\n this.map.off('layeradd', this._layerAddedEdit, this);\n this.map.off('layeradd', this.throttledReInitEdit, this);\n\n // Set toolbar button to currect status\n this.Toolbar.toggleButton('editMode', this.globalEditModeEnabled());\n\n // fire event\n this._fireGlobalEditModeToggled(false);\n },\n // TODO: Remove in the next major release\n globalEditEnabled() {\n return this.globalEditModeEnabled();\n },\n globalEditModeEnabled() {\n return this._globalEditModeEnabled;\n },\n // TODO: this should maybe removed, it will overwrite explicit options on the layers\n toggleGlobalEditMode(options = this.globalOptions) {\n if (this.globalEditModeEnabled()) {\n // disable\n this.disableGlobalEditMode();\n } else {\n // enable\n this.enableGlobalEditMode(options);\n }\n },\n handleLayerAdditionInGlobalEditMode() {\n const layers = this._addedLayersEdit;\n this._addedLayersEdit = {};\n if (this.globalEditModeEnabled()) {\n for (const id in layers) {\n const layer = layers[id];\n // when global edit mode is enabled and a layer is added to the map,\n // enable edit for that layer if it's relevant\n\n if (this._isRelevantForEdit(layer)) {\n layer.pm.enable({ ...this.globalOptions });\n }\n }\n }\n },\n _layerAddedEdit({ layer }) {\n this._addedLayersEdit[L.stamp(layer)] = layer;\n },\n _isRelevantForEdit(layer) {\n return (\n layer.pm &&\n !(layer instanceof L.LayerGroup) &&\n ((!L.PM.optIn && !layer.options.pmIgnore) || // if optIn is not set / true and pmIgnore is not set / true (default)\n (L.PM.optIn && layer.options.pmIgnore === false)) && // if optIn is true and pmIgnore is false\n !layer._pmTempLayer &&\n layer.pm.options.allowEditing\n );\n },\n};\n\nexport default GlobalEditMode;\n","const GlobalDragMode = {\n _globalDragModeEnabled: false,\n enableGlobalDragMode() {\n const layers = L.PM.Utils.findLayers(this.map);\n\n this._globalDragModeEnabled = true;\n this._addedLayersDrag = {};\n\n layers.forEach((layer) => {\n if (this._isRelevantForDrag(layer)) {\n layer.pm.enableLayerDrag();\n }\n });\n\n if (!this.throttledReInitDrag) {\n this.throttledReInitDrag = L.Util.throttle(\n this.reinitGlobalDragMode,\n 100,\n this\n );\n }\n\n // add map handler\n this.map.on('layeradd', this._layerAddedDrag, this);\n this.map.on('layeradd', this.throttledReInitDrag, this);\n\n // toogle the button in the toolbar if this is called programatically\n this.Toolbar.toggleButton('dragMode', this.globalDragModeEnabled());\n\n this._fireGlobalDragModeToggled(true);\n },\n disableGlobalDragMode() {\n const layers = L.PM.Utils.findLayers(this.map);\n\n this._globalDragModeEnabled = false;\n\n layers.forEach((layer) => {\n layer.pm.disableLayerDrag();\n });\n\n // remove map handler\n this.map.off('layeradd', this._layerAddedDrag, this);\n this.map.off('layeradd', this.throttledReInitDrag, this);\n\n // toogle the button in the toolbar if this is called programatically\n this.Toolbar.toggleButton('dragMode', this.globalDragModeEnabled());\n\n this._fireGlobalDragModeToggled(false);\n },\n globalDragModeEnabled() {\n return !!this._globalDragModeEnabled;\n },\n toggleGlobalDragMode() {\n if (this.globalDragModeEnabled()) {\n this.disableGlobalDragMode();\n } else {\n this.enableGlobalDragMode();\n }\n },\n reinitGlobalDragMode() {\n const layers = this._addedLayersDrag;\n this._addedLayersDrag = {};\n if (this.globalDragModeEnabled()) {\n for (const id in layers) {\n const layer = layers[id];\n\n if (this._isRelevantForDrag(layer)) {\n layer.pm.enableLayerDrag();\n }\n }\n }\n },\n _layerAddedDrag({ layer }) {\n this._addedLayersDrag[L.stamp(layer)] = layer;\n },\n _isRelevantForDrag(layer) {\n return (\n layer.pm &&\n !(layer instanceof L.LayerGroup) &&\n ((!L.PM.optIn && !layer.options.pmIgnore) || // if optIn is not set / true and pmIgnore is not set / true (default)\n (L.PM.optIn && layer.options.pmIgnore === false)) && // if optIn is true and pmIgnore is false\n !layer._pmTempLayer &&\n layer.pm.options.draggable\n );\n },\n};\n\nexport default GlobalDragMode;\n","const GlobalRemovalMode = {\n _globalRemovalModeEnabled: false,\n enableGlobalRemovalMode() {\n this._globalRemovalModeEnabled = true;\n // handle existing layers\n this.map.eachLayer((layer) => {\n if (this._isRelevantForRemoval(layer)) {\n if (layer.pm.enabled()) {\n layer.pm.disable();\n }\n layer.on('click', this.removeLayer, this);\n }\n });\n\n if (!this.throttledReInitRemoval) {\n this.throttledReInitRemoval = L.Util.throttle(\n this.handleLayerAdditionInGlobalRemovalMode,\n 100,\n this\n );\n }\n // save the added layers into the _addedLayersRemoval array, to read it later out\n this._addedLayersRemoval = {};\n // handle layers that are added while in removal mode\n this.map.on('layeradd', this._layerAddedRemoval, this);\n this.map.on('layeradd', this.throttledReInitRemoval, this);\n\n // toogle the button in the toolbar if this is called programatically\n this.Toolbar.toggleButton('removalMode', this.globalRemovalModeEnabled());\n\n this._fireGlobalRemovalModeToggled(true);\n },\n disableGlobalRemovalMode() {\n this._globalRemovalModeEnabled = false;\n this.map.eachLayer((layer) => {\n layer.off('click', this.removeLayer, this);\n });\n\n // remove map handler\n this.map.off('layeradd', this._layerAddedRemoval, this);\n this.map.off('layeradd', this.throttledReInitRemoval, this);\n\n // toogle the button in the toolbar if this is called programatically\n this.Toolbar.toggleButton('removalMode', this.globalRemovalModeEnabled());\n\n this._fireGlobalRemovalModeToggled(false);\n },\n // TODO: Remove in the next major release\n globalRemovalEnabled() {\n return this.globalRemovalModeEnabled();\n },\n globalRemovalModeEnabled() {\n return !!this._globalRemovalModeEnabled;\n },\n toggleGlobalRemovalMode() {\n // toggle global edit mode\n if (this.globalRemovalModeEnabled()) {\n this.disableGlobalRemovalMode();\n } else {\n this.enableGlobalRemovalMode();\n }\n },\n removeLayer(e) {\n const layer = e.target;\n // only remove layer, if it's handled by leaflet-geoman,\n // not a tempLayer and not currently being dragged\n const removeable =\n this._isRelevantForRemoval(layer) && !layer.pm.dragging();\n\n if (removeable) {\n layer.removeFrom(this.map.pm._getContainingLayer());\n layer.remove();\n if (layer instanceof L.LayerGroup) {\n this._fireRemoveLayerGroup(layer);\n this._fireRemoveLayerGroup(this.map, layer);\n } else {\n layer.pm._fireRemove(layer);\n layer.pm._fireRemove(this.map, layer);\n }\n }\n },\n _isRelevantForRemoval(layer) {\n return (\n layer.pm &&\n !(layer instanceof L.LayerGroup) &&\n ((!L.PM.optIn && !layer.options.pmIgnore) || // if optIn is not set / true and pmIgnore is not set / true (default)\n (L.PM.optIn && layer.options.pmIgnore === false)) && // if optIn is true and pmIgnore is false\n !layer._pmTempLayer &&\n layer.pm.options.allowRemoval\n );\n },\n handleLayerAdditionInGlobalRemovalMode() {\n const layers = this._addedLayersRemoval;\n this._addedLayersRemoval = {};\n if (this.globalRemovalModeEnabled()) {\n for (const id in layers) {\n const layer = layers[id];\n if (this._isRelevantForRemoval(layer)) {\n if (layer.pm.enabled()) {\n layer.pm.disable();\n }\n layer.on('click', this.removeLayer, this);\n }\n }\n }\n },\n _layerAddedRemoval({ layer }) {\n this._addedLayersRemoval[L.stamp(layer)] = layer;\n },\n};\n\nexport default GlobalRemovalMode;\n","const GlobalRotateMode = {\n _globalRotateModeEnabled: false,\n enableGlobalRotateMode() {\n this._globalRotateModeEnabled = true;\n const layers = L.PM.Utils.findLayers(this.map).filter(\n (l) => l instanceof L.Polyline\n );\n layers.forEach((layer) => {\n if (this._isRelevantForRotate(layer)) {\n layer.pm.enableRotate();\n }\n });\n\n if (!this.throttledReInitRotate) {\n this.throttledReInitRotate = L.Util.throttle(\n this.handleLayerAdditionInGlobalRotateMode,\n 100,\n this\n );\n }\n\n this._addedLayersRotate = {};\n // handle layers that are added while in rotate mode\n this.map.on('layeradd', this._layerAddedRotate, this);\n this.map.on('layeradd', this.throttledReInitRotate, this);\n\n // toogle the button in the toolbar if this is called programatically\n this.Toolbar.toggleButton('rotateMode', this.globalRotateModeEnabled());\n this._fireGlobalRotateModeToggled();\n },\n disableGlobalRotateMode() {\n this._globalRotateModeEnabled = false;\n const layers = L.PM.Utils.findLayers(this.map).filter(\n (l) => l instanceof L.Polyline\n );\n layers.forEach((layer) => {\n layer.pm.disableRotate();\n });\n\n // remove map handler\n this.map.off('layeradd', this._layerAddedRotate, this);\n this.map.off('layeradd', this.throttledReInitRotate, this);\n\n // toogle the button in the toolbar if this is called programatically\n this.Toolbar.toggleButton('rotateMode', this.globalRotateModeEnabled());\n this._fireGlobalRotateModeToggled();\n },\n globalRotateModeEnabled() {\n return !!this._globalRotateModeEnabled;\n },\n toggleGlobalRotateMode() {\n if (this.globalRotateModeEnabled()) {\n this.disableGlobalRotateMode();\n } else {\n this.enableGlobalRotateMode();\n }\n },\n _isRelevantForRotate(layer) {\n return (\n layer.pm &&\n layer instanceof L.Polyline &&\n !(layer instanceof L.LayerGroup) &&\n ((!L.PM.optIn && !layer.options.pmIgnore) || // if optIn is not set / true and pmIgnore is not set / true (default)\n (L.PM.optIn && layer.options.pmIgnore === false)) && // if optIn is true and pmIgnore is false\n !layer._pmTempLayer &&\n layer.pm.options.allowRotation\n );\n },\n handleLayerAdditionInGlobalRotateMode() {\n const layers = this._addedLayersRotate;\n this._addedLayersRotate = {};\n if (this.globalRotateModeEnabled()) {\n for (const id in layers) {\n const layer = layers[id];\n if (this._isRelevantForRemoval(layer)) {\n layer.pm.enableRotate();\n }\n }\n }\n },\n _layerAddedRotate({ layer }) {\n this._addedLayersRotate[L.stamp(layer)] = layer;\n },\n};\nexport default GlobalRotateMode;\n","import merge from 'lodash/merge';\n\nconst EventMixin = {\n // Draw Events\n // Fired when enableDraw() is called -> draw start\n _fireDrawStart(source = 'Draw', customPayload = {}) {\n this.__fire(\n this._map,\n 'pm:drawstart',\n {\n shape: this._shape,\n workingLayer: this._layer,\n },\n source,\n customPayload\n );\n },\n // Fired when disableDraw() is called -> draw stop\n _fireDrawEnd(source = 'Draw', customPayload = {}) {\n this.__fire(\n this._map,\n 'pm:drawend',\n {\n shape: this._shape,\n },\n source,\n customPayload\n );\n },\n // Fired when layer is created while drawing\n _fireCreate(layer, source = 'Draw', customPayload = {}) {\n this.__fire(\n this._map,\n 'pm:create',\n {\n shape: this._shape,\n marker: layer, // TODO: Deprecated\n layer,\n },\n source,\n customPayload\n );\n },\n // Fired when Circle / CircleMarker center is placed\n // if source == \"Draw\" then `workingLayer` is passed else `layer`\n _fireCenterPlaced(source = 'Draw', customPayload = {}) {\n const workingLayer = source === 'Draw' ? this._layer : undefined;\n const layer = source !== 'Draw' ? this._layer : undefined;\n\n this.__fire(\n this._layer,\n 'pm:centerplaced',\n {\n shape: this._shape,\n workingLayer,\n layer,\n latlng: this._layer.getLatLng(),\n },\n source,\n customPayload\n );\n },\n // Fired when layer is cutted\n // TODO: is Cut \"Draw\" or \"Edit\"? The event `pm:edit` in the same scope is called as source \"Edit\"\n _fireCut(\n fireLayer,\n layer,\n originalLayer,\n source = 'Draw',\n customPayload = {}\n ) {\n this.__fire(\n fireLayer,\n 'pm:cut',\n {\n shape: this._shape,\n layer,\n originalLayer,\n },\n source,\n customPayload\n );\n },\n\n // Edit Events\n // Fired when layer is edited / changed\n _fireEdit(fireLayer = this._layer, source = 'Edit', customPayload = {}) {\n this.__fire(\n fireLayer,\n 'pm:edit',\n { layer: this._layer, shape: this.getShape() },\n source,\n customPayload\n );\n },\n // Fired when layer is enabled for editing\n _fireEnable(source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:enable',\n { layer: this._layer, shape: this.getShape() },\n source,\n customPayload\n );\n },\n // Fired when layer is disabled for editing\n _fireDisable(source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:disable',\n { layer: this._layer, shape: this.getShape() },\n source,\n customPayload\n );\n },\n // Fired when layer is disabled and was edited / changed\n _fireUpdate(source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:update',\n { layer: this._layer, shape: this.getShape() },\n source,\n customPayload\n );\n },\n // Fired when a vertex-marker is started dragging\n // indexPath is only passed from Line / Polygon\n _fireMarkerDragStart(\n e,\n indexPath = undefined,\n source = 'Edit',\n customPayload = {}\n ) {\n this.__fire(\n this._layer,\n 'pm:markerdragstart',\n {\n layer: this._layer,\n markerEvent: e,\n shape: this.getShape(),\n indexPath,\n },\n source,\n customPayload\n );\n },\n // Fired while dragging a vertex-marker\n // indexPath is only passed from Line / Polygon\n _fireMarkerDrag(\n e,\n indexPath = undefined,\n source = 'Edit',\n customPayload = {}\n ) {\n this.__fire(\n this._layer,\n 'pm:markerdrag',\n {\n layer: this._layer,\n markerEvent: e,\n shape: this.getShape(),\n indexPath,\n },\n source,\n customPayload\n );\n },\n // Fired when a vertex-marker is stopped dragging\n // indexPath and intersectionReset is only passed from Line / Polygon\n _fireMarkerDragEnd(\n e,\n indexPath = undefined,\n intersectionReset = undefined,\n source = 'Edit',\n customPayload = {}\n ) {\n this.__fire(\n this._layer,\n 'pm:markerdragend',\n {\n layer: this._layer,\n markerEvent: e,\n shape: this.getShape(),\n indexPath,\n intersectionReset,\n },\n source,\n customPayload\n );\n },\n // Fired when a layer is started dragging\n _fireDragStart(source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:dragstart',\n {\n layer: this._layer,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n // Fired while dragging a layer\n _fireDrag(e, source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:drag',\n { ...e, shape: this.getShape() },\n source,\n customPayload\n );\n },\n // Fired when a layer is stopped dragging\n _fireDragEnd(source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:dragend',\n {\n layer: this._layer,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n // Fired when layer is enabled for editing\n _fireDragEnable(source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:dragenable',\n { layer: this._layer, shape: this.getShape() },\n source,\n customPayload\n );\n },\n // Fired when layer is disabled for editing\n _fireDragDisable(source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:dragdisable',\n { layer: this._layer, shape: this.getShape() },\n source,\n customPayload\n );\n },\n // Fired when a layer is removed\n _fireRemove(\n fireLayer,\n refLayer = fireLayer,\n source = 'Edit',\n customPayload = {}\n ) {\n this.__fire(\n fireLayer,\n 'pm:remove',\n { layer: refLayer, shape: this.getShape() },\n source,\n customPayload\n );\n },\n // Fired when a vertex-marker is created\n _fireVertexAdded(\n marker,\n indexPath,\n latlng,\n source = 'Edit',\n customPayload = {}\n ) {\n this.__fire(\n this._layer,\n 'pm:vertexadded',\n {\n layer: this._layer,\n workingLayer: this._layer,\n marker,\n indexPath,\n latlng,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n // Fired when a vertex-marker is removed\n _fireVertexRemoved(marker, indexPath, source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:vertexremoved',\n {\n layer: this._layer,\n marker,\n indexPath,\n shape: this.getShape(),\n // TODO: maybe add latlng as well?\n },\n source,\n customPayload\n );\n },\n // Fired when a vertex-marker is clicked\n _fireVertexClick(e, indexPath, source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:vertexclick',\n {\n layer: this._layer,\n markerEvent: e,\n indexPath,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n // Fired when a Line / Polygon has self intersection\n _fireIntersect(\n intersection,\n fireLayer = this._layer,\n source = 'Edit',\n customPayload = {}\n ) {\n this.__fire(\n fireLayer,\n 'pm:intersect',\n {\n layer: this._layer,\n intersection,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n // Fired when a Line / Polygon is reset because of self intersection\n _fireLayerReset(e, indexPath, source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:layerreset',\n {\n layer: this._layer,\n markerEvent: e,\n indexPath,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n\n // Fired coordinates of the layer changed\n _fireChange(latlngs, source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:change',\n {\n layer: this._layer,\n latlngs,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n\n // Fired when text of a text layer changed\n _fireTextChange(text, source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:textchange',\n {\n layer: this._layer,\n text,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n\n // Fired when text layer focused\n _fireTextFocus(source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:textfocus',\n {\n layer: this._layer,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n // Fired when text layer blurred\n _fireTextBlur(source = 'Edit', customPayload = {}) {\n this.__fire(\n this._layer,\n 'pm:textblur',\n {\n layer: this._layer,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n\n // Snapping Events\n // Fired during a marker move/drag and other layers are existing\n _fireSnapDrag(fireLayer, eventInfo, source = 'Snapping', customPayload = {}) {\n this.__fire(fireLayer, 'pm:snapdrag', eventInfo, source, customPayload);\n },\n // Fired when a vertex is snapped\n _fireSnap(fireLayer, eventInfo, source = 'Snapping', customPayload = {}) {\n this.__fire(fireLayer, 'pm:snap', eventInfo, source, customPayload);\n },\n // Fired when a vertex is unsnapped\n _fireUnsnap(fireLayer, eventInfo, source = 'Snapping', customPayload = {}) {\n this.__fire(fireLayer, 'pm:unsnap', eventInfo, source, customPayload);\n },\n\n // Rotation Events\n // Fired when rotation is enabled\n _fireRotationEnable(\n fireLayer,\n helpLayer,\n source = 'Rotation',\n customPayload = {}\n ) {\n this.__fire(\n fireLayer,\n 'pm:rotateenable',\n {\n layer: this._layer,\n helpLayer: this._rotatePoly,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n // Fired when rotation is disabled\n _fireRotationDisable(fireLayer, source = 'Rotation', customPayload = {}) {\n this.__fire(\n fireLayer,\n 'pm:rotatedisable',\n {\n layer: this._layer,\n shape: this.getShape(),\n },\n source,\n customPayload\n );\n },\n // Fired when rotation starts\n _fireRotationStart(\n fireLayer,\n originLatLngs,\n source = 'Rotation',\n customPayload = {}\n ) {\n this.__fire(\n fireLayer,\n 'pm:rotatestart',\n {\n layer: this._rotationLayer,\n helpLayer: this._layer,\n startAngle: this._startAngle,\n originLatLngs,\n },\n source,\n customPayload\n );\n },\n // Fired while rotation\n _fireRotation(\n fireLayer,\n angleDiff,\n oldLatLngs,\n rotationLayer = this._rotationLayer,\n source = 'Rotation',\n customPayload = {}\n ) {\n this.__fire(\n fireLayer,\n 'pm:rotate',\n {\n layer: rotationLayer,\n helpLayer: this._layer,\n startAngle: this._startAngle,\n angle: rotationLayer.pm.getAngle(),\n angleDiff,\n oldLatLngs,\n newLatLngs: rotationLayer.getLatLngs(),\n },\n source,\n customPayload\n );\n },\n // Fired when rotation ends\n _fireRotationEnd(\n fireLayer,\n startAngle,\n originLatLngs,\n source = 'Rotation',\n customPayload = {}\n ) {\n this.__fire(\n fireLayer,\n 'pm:rotateend',\n {\n layer: this._rotationLayer,\n helpLayer: this._layer,\n startAngle,\n angle: this._rotationLayer.pm.getAngle(),\n originLatLngs,\n newLatLngs: this._rotationLayer.getLatLngs(),\n },\n source,\n customPayload\n );\n },\n\n // Global Events\n // Fired when a Toolbar action is clicked\n _fireActionClick(\n action,\n btnName,\n button,\n source = 'Toolbar',\n customPayload = {}\n ) {\n // this._map is used because this is fired from L.Controls (PMButton)\n this.__fire(\n this._map,\n 'pm:actionclick',\n {\n text: action.text,\n action,\n btnName,\n button,\n },\n source,\n customPayload\n );\n },\n // Fired when a Toolbar button is clicked\n _fireButtonClick(btnName, button, source = 'Toolbar', customPayload = {}) {\n // this._map is used because this is fired from L.Controls (PMButton)\n this.__fire(\n this._map,\n 'pm:buttonclick',\n { btnName, button },\n source,\n customPayload\n );\n },\n // Fired when language is changed\n _fireLangChange(\n oldLang,\n activeLang,\n fallback,\n translations,\n source = 'Global',\n customPayload = {}\n ) {\n this.__fire(\n this.map,\n 'pm:langchange',\n {\n oldLang,\n activeLang,\n fallback,\n translations,\n },\n source,\n customPayload\n );\n },\n // Fired when Drag Mode is toggled.\n _fireGlobalDragModeToggled(enabled, source = 'Global', customPayload = {}) {\n this.__fire(\n this.map,\n 'pm:globaldragmodetoggled',\n {\n enabled,\n map: this.map,\n },\n source,\n customPayload\n );\n },\n // Fired when Edit Mode is toggled.\n _fireGlobalEditModeToggled(enabled, source = 'Global', customPayload = {}) {\n this.__fire(\n this.map,\n 'pm:globaleditmodetoggled',\n {\n enabled,\n map: this.map,\n },\n source,\n customPayload\n );\n },\n // Fired when Removal Mode is toggled.\n _fireGlobalRemovalModeToggled(\n enabled,\n source = 'Global',\n customPayload = {}\n ) {\n this.__fire(\n this.map,\n 'pm:globalremovalmodetoggled',\n {\n enabled,\n map: this.map,\n },\n source,\n customPayload\n );\n },\n // Fired when Cut Mode is toggled.\n _fireGlobalCutModeToggled(source = 'Global', customPayload = {}) {\n this.__fire(\n this._map,\n 'pm:globalcutmodetoggled',\n {\n enabled: !!this._enabled,\n map: this._map,\n },\n source,\n customPayload\n );\n },\n // Fired when Draw Mode is toggled.\n _fireGlobalDrawModeToggled(source = 'Global', customPayload = {}) {\n this.__fire(\n this._map,\n 'pm:globaldrawmodetoggled',\n {\n enabled: this._enabled,\n shape: this._shape,\n map: this._map,\n },\n source,\n customPayload\n );\n },\n // Fired when Rotation Mode is toggled.\n _fireGlobalRotateModeToggled(source = 'Global', customPayload = {}) {\n this.__fire(\n this.map,\n 'pm:globalrotatemodetoggled',\n {\n enabled: this.globalRotateModeEnabled(),\n map: this.map,\n },\n source,\n customPayload\n );\n },\n // Fired when LayerGroup is removed\n _fireRemoveLayerGroup(\n fireLayer,\n refLayer = fireLayer,\n source = 'Edit',\n customPayload = {}\n ) {\n this.__fire(\n fireLayer,\n 'pm:remove',\n { layer: refLayer, shape: undefined },\n source,\n customPayload\n );\n },\n // Fired when `keydown` or `keyup` on the document is fired.\n _fireKeyeventEvent(\n event,\n eventType,\n focusOn,\n source = 'Global',\n customPayload = {}\n ) {\n this.__fire(\n this.map,\n 'pm:keyevent',\n {\n event,\n eventType,\n focusOn,\n },\n source,\n customPayload\n );\n },\n\n // private (very private) fire function\n __fire(fireLayer, type, payload, source, customPayload = {}) {\n payload = merge(payload, customPayload, { source });\n L.PM.Utils._fireEvent(fireLayer, type, payload);\n },\n};\n\nexport default EventMixin;\n","// use function to create a new mixin object for keeping isolation\n// to make it work for multiple map instances\nconst createKeyboardMixins = () => ({\n _lastEvents: { keydown: undefined, keyup: undefined, current: undefined },\n _initKeyListener(map) {\n this.map = map;\n L.DomEvent.on(document, 'keydown keyup', this._onKeyListener, this);\n L.DomEvent.on(window, 'blur', this._onBlur, this);\n // clean up global listeners when current map instance is destroyed\n map.once('unload', this._unbindKeyListenerEvents, this);\n },\n _unbindKeyListenerEvents() {\n L.DomEvent.off(document, 'keydown keyup', this._onKeyListener, this);\n L.DomEvent.off(window, 'blur', this._onBlur, this);\n },\n _onKeyListener(e) {\n let focusOn = 'document';\n\n // .contains only supported since IE9, if you want to use Geoman with IE8 or lower you need to implement a polyfill for .contains\n // with focusOn the user can add a check if the key was pressed while the user interacts with the map\n if (this.map.getContainer().contains(e.target)) {\n focusOn = 'map';\n }\n\n const data = { event: e, eventType: e.type, focusOn };\n this._lastEvents[e.type] = data;\n this._lastEvents.current = data;\n\n this.map.pm._fireKeyeventEvent(e, e.type, focusOn);\n },\n _onBlur(e) {\n e.altKey = false;\n const data = { event: e, eventType: e.type, focusOn: 'document' };\n this._lastEvents[e.type] = data;\n this._lastEvents.current = data;\n },\n getLastKeyEvent(type = 'current') {\n return this._lastEvents[type];\n },\n isShiftKeyPressed() {\n return this._lastEvents.current?.event.shiftKey;\n },\n isAltKeyPressed() {\n return this._lastEvents.current?.event.altKey;\n },\n isCtrlKeyPressed() {\n return this._lastEvents.current?.event.ctrlKey;\n },\n isMetaKeyPressed() {\n return this._lastEvents.current?.event.metaKey;\n },\n getPressedKey() {\n return this._lastEvents.current?.event.key;\n },\n});\n\nexport default createKeyboardMixins;\n","import get from 'lodash/get';\nimport translations from '../../assets/translations';\n\nexport function getTranslation(path) {\n const lang = L.PM.activeLang;\n // if translation is not found, fallback to english\n return get(translations[lang], path) || get(translations.en, path) || path;\n}\n\nexport function hasValues(list) {\n for (let i = 0; i < list.length; i += 1) {\n const item = list[i];\n\n if (Array.isArray(item)) {\n if (hasValues(item)) {\n return true;\n }\n } else if (item !== null && item !== undefined && item !== '') {\n return true;\n }\n }\n\n return false;\n}\n\nexport function removeEmptyCoordRings(arr) {\n return arr.reduce((result, item) => {\n if (item.length !== 0) {\n const newItem = Array.isArray(item) ? removeEmptyCoordRings(item) : item;\n if (Array.isArray(newItem)) {\n if (newItem.length !== 0) {\n result.push(newItem);\n }\n } else {\n result.push(newItem);\n }\n }\n return result;\n }, []);\n}\n\n// Code from https://stackoverflow.com/a/24153998/8283938\nfunction destinationVincenty(lonlat, brng, dist) {\n // rewritten to work with leaflet\n const VincentyConstants = {\n a: L.CRS.Earth.R,\n b: 6356752.3142,\n f: 1 / 298.257223563,\n };\n\n const { a, b, f } = VincentyConstants;\n const lon1 = lonlat.lng;\n const lat1 = lonlat.lat;\n const s = dist;\n const pi = Math.PI;\n const alpha1 = (brng * pi) / 180; // converts brng degrees to radius\n const sinAlpha1 = Math.sin(alpha1);\n const cosAlpha1 = Math.cos(alpha1);\n const tanU1 =\n (1 - f) * Math.tan((lat1 * pi) / 180 /* converts lat1 degrees to radius */);\n const cosU1 = 1 / Math.sqrt(1 + tanU1 * tanU1);\n const sinU1 = tanU1 * cosU1;\n const sigma1 = Math.atan2(tanU1, cosAlpha1);\n const sinAlpha = cosU1 * sinAlpha1;\n const cosSqAlpha = 1 - sinAlpha * sinAlpha;\n const uSq = (cosSqAlpha * (a * a - b * b)) / (b * b);\n const A = 1 + (uSq / 16384) * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));\n const B = (uSq / 1024) * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));\n let sigma = s / (b * A);\n let sigmaP = 2 * Math.PI;\n\n let cos2SigmaM;\n let sinSigma;\n let cosSigma;\n while (Math.abs(sigma - sigmaP) > 1e-12) {\n cos2SigmaM = Math.cos(2 * sigma1 + sigma);\n sinSigma = Math.sin(sigma);\n cosSigma = Math.cos(sigma);\n const deltaSigma =\n B *\n sinSigma *\n (cos2SigmaM +\n (B / 4) *\n (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -\n (B / 6) *\n cos2SigmaM *\n (-3 + 4 * sinSigma * sinSigma) *\n (-3 + 4 * cos2SigmaM * cos2SigmaM)));\n sigmaP = sigma;\n sigma = s / (b * A) + deltaSigma;\n }\n const tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;\n const lat2 = Math.atan2(\n sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,\n (1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp)\n );\n const lambda = Math.atan2(\n sinSigma * sinAlpha1,\n cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1\n );\n const C = (f / 16) * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));\n const lam =\n lambda -\n (1 - C) *\n f *\n sinAlpha *\n (sigma +\n C *\n sinSigma *\n (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));\n // const revAz = Math.atan2(sinAlpha, -tmp); // final bearing\n const lamFunc = lon1 + (lam * 180) / pi; // converts lam radius to degrees\n const lat2a = (lat2 * 180) / pi; // converts lat2a radius to degrees\n\n return L.latLng(lamFunc, lat2a);\n}\n\nexport function createGeodesicPolygon(\n origin,\n radius,\n sides,\n rotation,\n withBearing = true\n) {\n let trueAngle;\n let newLonlat;\n let geomPoint;\n const points = [];\n\n for (let i = 0; i < sides; i += 1) {\n if (withBearing) {\n trueAngle = (i * 360) / sides + rotation;\n newLonlat = destinationVincenty(origin, trueAngle, radius);\n geomPoint = L.latLng(newLonlat.lng, newLonlat.lat);\n } else {\n const pLat = origin.lat + Math.cos((2 * i * Math.PI) / sides) * radius;\n const pLng = origin.lng + Math.sin((2 * i * Math.PI) / sides) * radius;\n geomPoint = L.latLng(pLat, pLng);\n }\n points.push(geomPoint);\n }\n\n return points;\n}\n\n/* Copied from L.GeometryUtil */\nfunction destination(latlng, heading, distance) {\n heading = (heading + 360) % 360;\n const rad = Math.PI / 180;\n const radInv = 180 / Math.PI;\n const { R } = L.CRS.Earth; // approximation of Earth's radius\n const lon1 = latlng.lng * rad;\n const lat1 = latlng.lat * rad;\n const rheading = heading * rad;\n const sinLat1 = Math.sin(lat1);\n const cosLat1 = Math.cos(lat1);\n const cosDistR = Math.cos(distance / R);\n const sinDistR = Math.sin(distance / R);\n const lat2 = Math.asin(\n sinLat1 * cosDistR + cosLat1 * sinDistR * Math.cos(rheading)\n );\n let lon2 =\n lon1 +\n Math.atan2(\n Math.sin(rheading) * sinDistR * cosLat1,\n cosDistR - sinLat1 * Math.sin(lat2)\n );\n lon2 *= radInv;\n\n const optA = lon2 - 360;\n const optB = lon2 < -180 ? lon2 + 360 : lon2;\n\n lon2 = lon2 > 180 ? optA : optB;\n return L.latLng([lat2 * radInv, lon2]);\n}\n/* Copied from L.GeometryUtil */\nexport function calcAngle(map, latlngA, latlngB) {\n const pointA = map.latLngToContainerPoint(latlngA);\n const pointB = map.latLngToContainerPoint(latlngB);\n let angleDeg =\n (Math.atan2(pointB.y - pointA.y, pointB.x - pointA.x) * 180) / Math.PI + 90;\n angleDeg += angleDeg < 0 ? 360 : 0;\n return angleDeg;\n}\n\nexport function destinationOnLine(map, latlngA, latlngB, distance) {\n const angleDeg = calcAngle(map, latlngA, latlngB);\n return destination(latlngA, angleDeg, distance);\n}\n\n// this function is used with the .sort(prioritiseSort(key, sortingOrder)) function of arrays\nexport function prioritiseSort(key, _sortingOrder, order = 'asc') {\n /* the sorting order has all possible keys (lowercase) with the index and then it is sorted by the key on the object */\n\n if (!_sortingOrder || Object.keys(_sortingOrder).length === 0) {\n return (a, b) => a - b; // default sort method\n }\n\n // change the keys to lowercase\n const keys = Object.keys(_sortingOrder);\n let objKey;\n let n = keys.length - 1;\n const sortingOrder = {};\n while (n >= 0) {\n objKey = keys[n];\n sortingOrder[objKey.toLowerCase()] = _sortingOrder[objKey];\n n -= 1;\n }\n\n function getShape(layer) {\n if (layer instanceof L.Marker) {\n return 'Marker';\n }\n if (layer instanceof L.Circle) {\n return 'Circle';\n }\n if (layer instanceof L.CircleMarker) {\n return 'CircleMarker';\n }\n if (layer instanceof L.Rectangle) {\n return 'Rectangle';\n }\n if (layer instanceof L.Polygon) {\n return 'Polygon';\n }\n if (layer instanceof L.Polyline) {\n return 'Line';\n }\n return undefined;\n }\n\n return (a, b) => {\n let keyA;\n let keyB;\n if (key === 'instanceofShape') {\n keyA = getShape(a.layer).toLowerCase();\n keyB = getShape(b.layer).toLowerCase();\n if (!keyA || !keyB) return 0;\n } else {\n /* eslint-disable-next-line no-prototype-builtins */\n if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) return 0;\n keyA = a[key].toLowerCase();\n keyB = b[key].toLowerCase();\n }\n\n const first =\n keyA in sortingOrder ? sortingOrder[keyA] : Number.MAX_SAFE_INTEGER;\n\n const second =\n keyB in sortingOrder ? sortingOrder[keyB] : Number.MAX_SAFE_INTEGER;\n\n let result = 0;\n if (first < second) result = -1;\n else if (first > second) result = 1;\n return order === 'desc' ? result * -1 : result;\n };\n}\n\nexport function copyLatLngs(layer, latlngs = layer.getLatLngs()) {\n if (layer instanceof L.Polygon) {\n return L.polygon(latlngs).getLatLngs();\n }\n return L.polyline(latlngs).getLatLngs();\n}\n\n// Replaces the lat value with the MAX_LATITUDE of CRS if it is lower / higher\nexport function fixLatOffset(latlng, map) {\n if (map.options.crs?.projection?.MAX_LATITUDE) {\n const max = map.options.crs?.projection?.MAX_LATITUDE;\n latlng.lat = Math.max(Math.min(max, latlng.lat), -max);\n }\n return latlng;\n}\n\nexport function getRenderer(layer) {\n return (\n layer.options.renderer ||\n (layer._map &&\n (layer._map._getPaneRenderer(layer.options.pane) ||\n layer._map.options.renderer ||\n layer._map._renderer)) ||\n layer._renderer\n );\n}\n","import { getTranslation } from '../helpers';\nimport EventMixin from '../Mixins/Events';\n\nconst PMButton = L.Control.extend({\n includes: [EventMixin],\n options: {\n position: 'topleft',\n disableByOtherButtons: true,\n },\n // TODO: clean up variable names like _button should be _options and that domNodeVariable stuff\n initialize(options) {\n // replaced setOptions with this because classNames returned undefined 🤔\n this._button = L.Util.extend({}, this.options, options);\n },\n onAdd(map) {\n this._map = map;\n if (!this._map.pm.Toolbar.options.oneBlock) {\n if (this._button.tool === 'edit') {\n this._container = this._map.pm.Toolbar.editContainer;\n } else if (this._button.tool === 'options') {\n this._container = this._map.pm.Toolbar.optionsContainer;\n } else if (this._button.tool === 'custom') {\n this._container = this._map.pm.Toolbar.customContainer;\n } else {\n this._container = this._map.pm.Toolbar.drawContainer;\n }\n } else {\n this._container = this._map.pm.Toolbar._createContainer(\n this.options.position\n );\n }\n this._renderButton();\n\n return this._container;\n },\n _renderButton() {\n const oldDomNode = this.buttonsDomNode;\n this.buttonsDomNode = this._makeButton(this._button);\n if (oldDomNode) {\n oldDomNode.replaceWith(this.buttonsDomNode);\n } else {\n this._container.appendChild(this.buttonsDomNode);\n }\n },\n onRemove() {\n this.buttonsDomNode.remove();\n\n return this._container;\n },\n getText() {\n return this._button.text;\n },\n getIconUrl() {\n return this._button.iconUrl;\n },\n destroy() {\n this._button = {};\n this._update();\n },\n toggle(e) {\n if (typeof e === 'boolean') {\n this._button.toggleStatus = e;\n } else {\n this._button.toggleStatus = !this._button.toggleStatus;\n }\n this._applyStyleClasses();\n\n return this._button.toggleStatus;\n },\n toggled() {\n return this._button.toggleStatus;\n },\n onCreate() {\n this.toggle(false);\n },\n disable() {\n this.toggle(false); // is needed to prevent active button disabled\n this._button.disabled = true;\n this._updateDisabled();\n },\n enable() {\n this._button.disabled = false;\n this._updateDisabled();\n },\n _triggerClick(e) {\n if (e) {\n // is needed to prevent scrolling when clicking on a-element with href=\"a\"\n e.preventDefault();\n }\n if (this._button.disabled) {\n return;\n }\n // TODO is this a big change when we change from e to a object with the event and the button? Now it's the second argument\n this._button.onClick(e, { button: this, event: e });\n this._clicked(e);\n this._button.afterClick(e, { button: this, event: e });\n },\n _makeButton(button) {\n const pos = this.options.position.indexOf('right') > -1 ? 'pos-right' : '';\n\n // button container\n const buttonContainer = L.DomUtil.create(\n 'div',\n `button-container ${pos}`,\n this._container\n );\n\n if (button.title) {\n buttonContainer.setAttribute('title', button.title);\n }\n\n // the button itself\n const newButton = L.DomUtil.create(\n 'a',\n 'leaflet-buttons-control-button',\n buttonContainer\n );\n newButton.setAttribute('role', 'button');\n newButton.setAttribute('tabindex', '0');\n newButton.href = '#';\n\n // the buttons actions\n const actionContainer = L.DomUtil.create(\n 'div',\n `leaflet-pm-actions-container ${pos}`,\n buttonContainer\n );\n\n const activeActions = button.actions;\n\n const actions = {\n cancel: {\n text: getTranslation('actions.cancel'),\n title: getTranslation('actions.cancel'),\n onClick() {\n this._triggerClick();\n },\n },\n finishMode: {\n text: getTranslation('actions.finish'),\n title: getTranslation('actions.finish'),\n onClick() {\n this._triggerClick();\n },\n },\n removeLastVertex: {\n text: getTranslation('actions.removeLastVertex'),\n title: getTranslation('actions.removeLastVertex'),\n onClick() {\n this._map.pm.Draw[button.jsClass]._removeLastVertex();\n },\n },\n finish: {\n text: getTranslation('actions.finish'),\n title: getTranslation('actions.finish'),\n onClick(e) {\n this._map.pm.Draw[button.jsClass]._finishShape(e);\n },\n },\n };\n\n activeActions.forEach((_action) => {\n const name = typeof _action === 'string' ? _action : _action.name;\n let action;\n if (actions[name]) {\n action = actions[name];\n } else if (_action.text) {\n action = _action;\n } else {\n return;\n }\n const actionNode = L.DomUtil.create(\n 'a',\n `leaflet-pm-action ${pos} action-${name}`,\n actionContainer\n );\n actionNode.setAttribute('role', 'button');\n actionNode.setAttribute('tabindex', '0');\n actionNode.href = '#';\n\n if (action.title) {\n actionNode.title = action.title;\n }\n\n actionNode.innerHTML = action.text;\n\n L.DomEvent.disableClickPropagation(actionNode);\n L.DomEvent.on(actionNode, 'click', L.DomEvent.stop);\n\n if (!button.disabled) {\n if (action.onClick) {\n const actionClick = (e) => {\n // is needed to prevent scrolling when clicking on a-element with href=\"a\"\n e.preventDefault();\n let btnName = '';\n const { buttons } = this._map.pm.Toolbar;\n for (const btn in buttons) {\n if (buttons[btn]._button === button) {\n btnName = btn;\n break;\n }\n }\n this._fireActionClick(action, btnName, button);\n };\n\n L.DomEvent.addListener(actionNode, 'click', actionClick, this);\n L.DomEvent.addListener(actionNode, 'click', action.onClick, this);\n }\n }\n });\n\n if (button.toggleStatus) {\n L.DomUtil.addClass(buttonContainer, 'active');\n }\n\n const image = L.DomUtil.create('div', 'control-icon', newButton);\n\n if (button.iconUrl) {\n image.setAttribute('src', button.iconUrl);\n }\n if (button.className) {\n L.DomUtil.addClass(image, button.className);\n }\n\n L.DomEvent.disableClickPropagation(newButton);\n L.DomEvent.on(newButton, 'click', L.DomEvent.stop);\n\n if (!button.disabled) {\n // before the actual click, trigger a click on currently toggled buttons to\n // untoggle them and their functionality\n L.DomEvent.addListener(newButton, 'click', this._onBtnClick, this);\n L.DomEvent.addListener(newButton, 'click', this._triggerClick, this);\n }\n\n if (button.disabled) {\n L.DomUtil.addClass(newButton, 'pm-disabled');\n newButton.setAttribute('aria-disabled', 'true');\n }\n\n return buttonContainer;\n },\n\n _applyStyleClasses() {\n if (!this._container) {\n return;\n }\n\n if (!this._button.toggleStatus || this._button.cssToggle === false) {\n L.DomUtil.removeClass(this.buttonsDomNode, 'active');\n L.DomUtil.removeClass(this._container, 'activeChild');\n } else {\n L.DomUtil.addClass(this.buttonsDomNode, 'active');\n L.DomUtil.addClass(this._container, 'activeChild');\n }\n },\n\n _onBtnClick() {\n if (this._button.disabled) {\n return;\n }\n if (this._button.disableOtherButtons) {\n this._map.pm.Toolbar.triggerClickOnToggledButtons(this);\n }\n let btnName = '';\n const { buttons } = this._map.pm.Toolbar;\n for (const btn in buttons) {\n if (buttons[btn]._button === this._button) {\n btnName = btn;\n break;\n }\n }\n this._fireButtonClick(btnName, this._button);\n },\n\n _clicked() {\n if (this._button.doToggle) {\n this.toggle();\n }\n },\n\n _updateDisabled() {\n if (!this._container) {\n return;\n }\n\n const className = 'pm-disabled';\n const button = this.buttonsDomNode.children[0];\n\n if (this._button.disabled) {\n L.DomUtil.addClass(button, className);\n button.setAttribute('aria-disabled', 'true');\n } else {\n L.DomUtil.removeClass(button, className);\n button.setAttribute('aria-disabled', 'false');\n }\n },\n});\n\nexport default PMButton;\n","import PMButton from './L.Controls';\n\nimport { getTranslation } from '../helpers';\n\nL.Control.PMButton = PMButton;\n\nconst Toolbar = L.Class.extend({\n options: {\n drawMarker: true,\n drawRectangle: true,\n drawPolyline: true,\n drawPolygon: true,\n drawCircle: true,\n drawCircleMarker: true,\n drawText: true,\n editMode: true,\n dragMode: true,\n cutPolygon: true,\n removalMode: true,\n rotateMode: true,\n snappingOption: true,\n drawControls: true,\n editControls: true,\n optionsControls: true,\n customControls: true,\n oneBlock: false,\n position: 'topleft',\n positions: {\n draw: '',\n edit: '',\n options: '',\n custom: '',\n },\n },\n customButtons: [],\n initialize(map) {\n // For some reason there is an reference between multiple maps instances\n this.customButtons = [];\n this.options.positions = {\n draw: '',\n edit: '',\n options: '',\n custom: '',\n };\n\n this.init(map);\n },\n reinit() {\n const addControls = this.isVisible;\n\n this.removeControls();\n this._defineButtons();\n\n if (addControls) {\n this.addControls();\n }\n },\n init(map) {\n this.map = map;\n\n this.buttons = {};\n this.isVisible = false;\n this.drawContainer = L.DomUtil.create(\n 'div',\n 'leaflet-pm-toolbar leaflet-pm-draw leaflet-bar leaflet-control'\n );\n this.editContainer = L.DomUtil.create(\n 'div',\n 'leaflet-pm-toolbar leaflet-pm-edit leaflet-bar leaflet-control'\n );\n this.optionsContainer = L.DomUtil.create(\n 'div',\n 'leaflet-pm-toolbar leaflet-pm-options leaflet-bar leaflet-control'\n );\n this.customContainer = L.DomUtil.create(\n 'div',\n 'leaflet-pm-toolbar leaflet-pm-custom leaflet-bar leaflet-control'\n );\n\n this._defineButtons();\n },\n _createContainer(name) {\n const container = `${name}Container`;\n if (!this[container]) {\n this[container] = L.DomUtil.create(\n 'div',\n `leaflet-pm-toolbar leaflet-pm-${name} leaflet-bar leaflet-control`\n );\n }\n return this[container];\n },\n getButtons() {\n return this.buttons;\n },\n\n addControls(options = this.options) {\n // adds all buttons to the map specified inside options\n\n // make button renaming backwards compatible\n if (typeof options.editPolygon !== 'undefined') {\n options.editMode = options.editPolygon;\n }\n if (typeof options.deleteLayer !== 'undefined') {\n options.removalMode = options.deleteLayer;\n }\n\n // first set the options\n L.Util.setOptions(this, options);\n\n this.applyIconStyle();\n\n this.isVisible = true;\n // now show the specified buttons\n this._showHideButtons();\n },\n applyIconStyle() {\n const buttons = this.getButtons();\n\n const iconClasses = {\n geomanIcons: {\n drawMarker: 'control-icon leaflet-pm-icon-marker',\n drawPolyline: 'control-icon leaflet-pm-icon-polyline',\n drawRectangle: 'control-icon leaflet-pm-icon-rectangle',\n drawPolygon: 'control-icon leaflet-pm-icon-polygon',\n drawCircle: 'control-icon leaflet-pm-icon-circle',\n drawCircleMarker: 'control-icon leaflet-pm-icon-circle-marker',\n editMode: 'control-icon leaflet-pm-icon-edit',\n dragMode: 'control-icon leaflet-pm-icon-drag',\n cutPolygon: 'control-icon leaflet-pm-icon-cut',\n removalMode: 'control-icon leaflet-pm-icon-delete',\n drawText: 'control-icon leaflet-pm-icon-text',\n },\n };\n\n for (const name in buttons) {\n const button = buttons[name];\n\n L.Util.setOptions(button, {\n className: iconClasses.geomanIcons[name],\n });\n }\n },\n removeControls() {\n // grab all buttons to loop through\n const buttons = this.getButtons();\n\n // remove all buttons\n for (const btn in buttons) {\n buttons[btn].remove();\n }\n\n this.isVisible = false;\n },\n toggleControls(options = this.options) {\n if (this.isVisible) {\n this.removeControls();\n } else {\n this.addControls(options);\n }\n },\n _addButton(name, button) {\n this.buttons[name] = button;\n this.options[name] = !!this.options[name] || false;\n\n return this.buttons[name];\n },\n triggerClickOnToggledButtons(exceptThisButton) {\n // this function is used when - e.g. drawing mode is enabled and a possible\n // other active mode (like removal tool) is already active.\n // we can't have two active modes because of possible event conflicts\n // so, we trigger a click on all currently active (toggled) buttons\n\n for (const name in this.buttons) {\n const button = this.buttons[name];\n if (\n button._button.disableByOtherButtons &&\n button !== exceptThisButton &&\n button.toggled()\n ) {\n button._triggerClick();\n }\n }\n },\n toggleButton(name, status, disableOthers = true) {\n // does not fire the events/functionality of the button\n // this just changes the state and is used if a functionality (like Draw)\n // is enabled manually via script\n\n // backwards compatibility with button rename\n if (name === 'editPolygon') {\n name = 'editMode';\n }\n if (name === 'deleteLayer') {\n name = 'removalMode';\n }\n\n // as some mode got enabled, we still have to trigger the click on the other buttons\n // to disable their mode\n if (disableOthers) {\n this.triggerClickOnToggledButtons(this.buttons[name]);\n }\n\n if (!this.buttons[name]) {\n return false;\n }\n // now toggle the state of the button\n return this.buttons[name].toggle(status);\n },\n _defineButtons() {\n // some buttons are still in their respective classes, like L.PM.Draw.Polygon\n const drawMarkerButton = {\n className: 'control-icon leaflet-pm-icon-marker',\n title: getTranslation('buttonTitles.drawMarkerButton'),\n jsClass: 'Marker',\n onClick: () => {},\n afterClick: (e, ctx) => {\n // toggle drawing mode\n this.map.pm.Draw[ctx.button._button.jsClass].toggle();\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n actions: ['cancel'],\n };\n\n const drawPolyButton = {\n title: getTranslation('buttonTitles.drawPolyButton'),\n className: 'control-icon leaflet-pm-icon-polygon',\n jsClass: 'Polygon',\n onClick: () => {},\n afterClick: (e, ctx) => {\n // toggle drawing mode\n this.map.pm.Draw[ctx.button._button.jsClass].toggle();\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n actions: ['finish', 'removeLastVertex', 'cancel'],\n };\n\n const drawLineButton = {\n className: 'control-icon leaflet-pm-icon-polyline',\n title: getTranslation('buttonTitles.drawLineButton'),\n jsClass: 'Line',\n onClick: () => {},\n afterClick: (e, ctx) => {\n // toggle drawing mode\n this.map.pm.Draw[ctx.button._button.jsClass].toggle();\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n actions: ['finish', 'removeLastVertex', 'cancel'],\n };\n\n const drawCircleButton = {\n title: getTranslation('buttonTitles.drawCircleButton'),\n className: 'control-icon leaflet-pm-icon-circle',\n jsClass: 'Circle',\n onClick: () => {},\n afterClick: (e, ctx) => {\n // toggle drawing mode\n this.map.pm.Draw[ctx.button._button.jsClass].toggle();\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n actions: ['cancel'],\n };\n\n const drawCircleMarkerButton = {\n title: getTranslation('buttonTitles.drawCircleMarkerButton'),\n className: 'control-icon leaflet-pm-icon-circle-marker',\n jsClass: 'CircleMarker',\n onClick: () => {},\n afterClick: (e, ctx) => {\n // toggle drawing mode\n this.map.pm.Draw[ctx.button._button.jsClass].toggle();\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n actions: ['cancel'],\n };\n\n const drawRectButton = {\n title: getTranslation('buttonTitles.drawRectButton'),\n className: 'control-icon leaflet-pm-icon-rectangle',\n jsClass: 'Rectangle',\n onClick: () => {},\n afterClick: (e, ctx) => {\n // toggle drawing mode\n this.map.pm.Draw[ctx.button._button.jsClass].toggle();\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n actions: ['cancel'],\n };\n\n const editButton = {\n title: getTranslation('buttonTitles.editButton'),\n className: 'control-icon leaflet-pm-icon-edit',\n onClick: () => {},\n afterClick: () => {\n this.map.pm.toggleGlobalEditMode();\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n tool: 'edit',\n actions: ['finishMode'],\n };\n\n const dragButton = {\n title: getTranslation('buttonTitles.dragButton'),\n className: 'control-icon leaflet-pm-icon-drag',\n onClick: () => {},\n afterClick: () => {\n this.map.pm.toggleGlobalDragMode();\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n tool: 'edit',\n actions: ['finishMode'],\n };\n\n const cutButton = {\n title: getTranslation('buttonTitles.cutButton'),\n className: 'control-icon leaflet-pm-icon-cut',\n jsClass: 'Cut',\n onClick: () => {},\n afterClick: (e, ctx) => {\n // enable polygon drawing mode without snap\n this.map.pm.Draw[ctx.button._button.jsClass].toggle({\n snappable: true,\n cursorMarker: true,\n allowSelfIntersection: false,\n });\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n tool: 'edit',\n actions: ['finish', 'removeLastVertex', 'cancel'],\n };\n\n const deleteButton = {\n title: getTranslation('buttonTitles.deleteButton'),\n className: 'control-icon leaflet-pm-icon-delete',\n onClick: () => {},\n afterClick: () => {\n this.map.pm.toggleGlobalRemovalMode();\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n tool: 'edit',\n actions: ['finishMode'],\n };\n\n const rotateButton = {\n title: getTranslation('buttonTitles.rotateButton'),\n className: 'control-icon leaflet-pm-icon-rotate',\n onClick: () => {},\n afterClick: () => {\n this.map.pm.toggleGlobalRotateMode();\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n tool: 'edit',\n actions: ['finishMode'],\n };\n\n const drawTextButton = {\n className: 'control-icon leaflet-pm-icon-text',\n title: getTranslation('buttonTitles.drawTextButton'),\n jsClass: 'Text',\n onClick: () => {},\n afterClick: (e, ctx) => {\n // toggle drawing mode\n this.map.pm.Draw[ctx.button._button.jsClass].toggle();\n },\n doToggle: true,\n toggleStatus: false,\n disableOtherButtons: true,\n position: this.options.position,\n actions: ['cancel'],\n };\n\n this._addButton('drawMarker', new L.Control.PMButton(drawMarkerButton));\n this._addButton('drawPolyline', new L.Control.PMButton(drawLineButton));\n this._addButton('drawRectangle', new L.Control.PMButton(drawRectButton));\n this._addButton('drawPolygon', new L.Control.PMButton(drawPolyButton));\n this._addButton('drawCircle', new L.Control.PMButton(drawCircleButton));\n this._addButton(\n 'drawCircleMarker',\n new L.Control.PMButton(drawCircleMarkerButton)\n );\n this._addButton('drawText', new L.Control.PMButton(drawTextButton));\n this._addButton('editMode', new L.Control.PMButton(editButton));\n this._addButton('dragMode', new L.Control.PMButton(dragButton));\n this._addButton('cutPolygon', new L.Control.PMButton(cutButton));\n this._addButton('removalMode', new L.Control.PMButton(deleteButton));\n this._addButton('rotateMode', new L.Control.PMButton(rotateButton));\n },\n\n _showHideButtons() {\n // if Toolbar is not visible, we don't need to update button positions\n if (!this.isVisible) {\n return;\n }\n\n // remove all buttons, that's because the Toolbar can be added again with\n // different options so it's basically a reset and add again\n this.removeControls();\n // we need to set isVisible = true again, because removeControls() set it to false\n this.isVisible = true;\n\n const buttons = this.getButtons();\n let ignoreBtns = [];\n\n if (this.options.drawControls === false) {\n ignoreBtns = ignoreBtns.concat(\n Object.keys(buttons).filter((btn) => !buttons[btn]._button.tool)\n );\n }\n if (this.options.editControls === false) {\n ignoreBtns = ignoreBtns.concat(\n Object.keys(buttons).filter(\n (btn) => buttons[btn]._button.tool === 'edit'\n )\n );\n }\n if (this.options.optionsControls === false) {\n ignoreBtns = ignoreBtns.concat(\n Object.keys(buttons).filter(\n (btn) => buttons[btn]._button.tool === 'options'\n )\n );\n }\n if (this.options.customControls === false) {\n ignoreBtns = ignoreBtns.concat(\n Object.keys(buttons).filter(\n (btn) => buttons[btn]._button.tool === 'custom'\n )\n );\n }\n\n for (const btn in buttons) {\n if (this.options[btn] && ignoreBtns.indexOf(btn) === -1) {\n // if options say the button should be visible, add it to the map\n let block = buttons[btn]._button.tool;\n if (!block) {\n // undefined is the draw block\n block = 'draw';\n }\n buttons[btn].setPosition(this._getBtnPosition(block));\n buttons[btn].addTo(this.map);\n }\n }\n },\n _getBtnPosition(block) {\n return this.options.positions && this.options.positions[block]\n ? this.options.positions[block]\n : this.options.position;\n },\n setBlockPosition(block, position) {\n this.options.positions[block] = position;\n this._showHideButtons();\n this.changeControlOrder();\n },\n getBlockPositions() {\n return this.options.positions;\n },\n copyDrawControl(copyInstance, options) {\n if (!options) {\n throw new TypeError('Button has no name');\n } else if (typeof options !== 'object') {\n // if only the name is passed and no options object\n options = { name: options };\n }\n\n const instance = this._btnNameMapping(copyInstance);\n\n if (!options.name) {\n throw new TypeError('Button has no name');\n }\n\n if (this.buttons[options.name]) {\n throw new TypeError('Button with this name already exists');\n }\n const drawInstance = this.map.pm.Draw.createNewDrawInstance(\n options.name,\n instance\n );\n\n const btn = this.buttons[instance]._button;\n options = { ...btn, ...options };\n const control = this.createCustomControl(options);\n return { drawInstance, control };\n },\n createCustomControl(options) {\n if (!options.name) {\n throw new TypeError('Button has no name');\n }\n\n if (this.buttons[options.name]) {\n throw new TypeError('Button with this name already exists');\n }\n if (!options.onClick) {\n options.onClick = () => {};\n }\n if (!options.afterClick) {\n options.afterClick = () => {};\n }\n if (options.toggle !== false) {\n options.toggle = true;\n }\n\n if (options.block) {\n options.block = options.block.toLowerCase();\n }\n if (!options.block || options.block === 'draw') {\n options.block = '';\n }\n\n if (!options.className) {\n options.className = 'control-icon';\n } else if (options.className.indexOf('control-icon') === -1) {\n options.className = `control-icon ${options.className}`;\n }\n\n const _options = {\n tool: options.block,\n className: options.className,\n title: options.title || '',\n jsClass: options.name,\n onClick: options.onClick,\n afterClick: options.afterClick,\n doToggle: options.toggle,\n toggleStatus: false,\n disableOtherButtons: options.disableOtherButtons ?? true,\n disableByOtherButtons: options.disableByOtherButtons ?? true,\n cssToggle: options.toggle,\n position: this.options.position,\n actions: options.actions || [],\n disabled: !!options.disabled,\n };\n\n if (this.options[options.name] !== false) {\n this.options[options.name] = true;\n }\n\n const control = this._addButton(\n options.name,\n new L.Control.PMButton(_options)\n );\n this.changeControlOrder();\n return control;\n },\n controlExists(name) {\n return Boolean(this.getButton(name));\n },\n getButton(name) {\n return this.getButtons()[name];\n },\n getButtonsInBlock(name) {\n const buttonsInBlock = {};\n if (name) {\n for (const buttonName in this.getButtons()) {\n const button = this.getButtons()[buttonName];\n // draw controls doesn't have a block\n if (\n button._button.tool === name ||\n (name === 'draw' && !button._button.tool)\n ) {\n buttonsInBlock[buttonName] = button;\n }\n }\n }\n return buttonsInBlock;\n },\n changeControlOrder(order = []) {\n const shapeMapping = this._shapeMapping();\n\n const _order = [];\n order.forEach((shape) => {\n if (shapeMapping[shape]) {\n _order.push(shapeMapping[shape]);\n } else {\n _order.push(shape);\n }\n });\n\n const buttons = this.getButtons();\n\n // This steps are needed to create a new Object which contains the buttons in the correct sorted order.\n const newbtnorder = {};\n _order.forEach((control) => {\n if (buttons[control]) {\n newbtnorder[control] = buttons[control];\n }\n });\n\n const drawBtns = Object.keys(buttons).filter(\n (btn) => !buttons[btn]._button.tool\n );\n drawBtns.forEach((btn) => {\n if (_order.indexOf(btn) === -1) {\n newbtnorder[btn] = buttons[btn];\n }\n });\n const editBtns = Object.keys(buttons).filter(\n (btn) => buttons[btn]._button.tool === 'edit'\n );\n editBtns.forEach((btn) => {\n if (_order.indexOf(btn) === -1) {\n newbtnorder[btn] = buttons[btn];\n }\n });\n const optionsBtns = Object.keys(buttons).filter(\n (btn) => buttons[btn]._button.tool === 'options'\n );\n optionsBtns.forEach((btn) => {\n if (_order.indexOf(btn) === -1) {\n newbtnorder[btn] = buttons[btn];\n }\n });\n const customBtns = Object.keys(buttons).filter(\n (btn) => buttons[btn]._button.tool === 'custom'\n );\n customBtns.forEach((btn) => {\n if (_order.indexOf(btn) === -1) {\n newbtnorder[btn] = buttons[btn];\n }\n });\n // To add all other buttons they are not in a container from above (maybe added manually by a developer)\n Object.keys(buttons).forEach((btn) => {\n if (_order.indexOf(btn) === -1) {\n newbtnorder[btn] = buttons[btn];\n }\n });\n\n this.map.pm.Toolbar.buttons = newbtnorder;\n this._showHideButtons();\n },\n getControlOrder() {\n const buttons = this.getButtons();\n const order = [];\n for (const btn in buttons) {\n order.push(btn);\n }\n return order;\n },\n changeActionsOfControl(name, actions) {\n const btnName = this._btnNameMapping(name);\n\n if (!btnName) {\n throw new TypeError('No name passed');\n }\n if (!actions) {\n throw new TypeError('No actions passed');\n }\n\n if (!this.buttons[btnName]) {\n throw new TypeError('Button with this name not exists');\n }\n this.buttons[btnName]._button.actions = actions;\n this.changeControlOrder();\n },\n setButtonDisabled(name, state) {\n const btnName = this._btnNameMapping(name);\n if (state) {\n this.buttons[btnName].disable();\n } else {\n this.buttons[btnName].enable();\n }\n },\n _shapeMapping() {\n return {\n Marker: 'drawMarker',\n Circle: 'drawCircle',\n Polygon: 'drawPolygon',\n Rectangle: 'drawRectangle',\n Polyline: 'drawPolyline',\n Line: 'drawPolyline',\n CircleMarker: 'drawCircleMarker',\n Edit: 'editMode',\n Drag: 'dragMode',\n Cut: 'cutPolygon',\n Removal: 'removalMode',\n Rotate: 'rotateMode',\n Text: 'drawText',\n };\n },\n _btnNameMapping(name) {\n const shapeMapping = this._shapeMapping();\n return shapeMapping[name] ? shapeMapping[name] : name;\n },\n});\n\nexport default Toolbar;\n","import merge from 'lodash/merge';\nimport SnapMixin from '../Mixins/Snapping';\nimport EventMixin from '../Mixins/Events';\n\nconst Draw = L.Class.extend({\n includes: [SnapMixin, EventMixin],\n options: {\n snappable: true, // TODO: next major Release, rename it to allowSnapping\n snapDistance: 20,\n snapMiddle: false,\n allowSelfIntersection: true,\n tooltips: true,\n templineStyle: {},\n hintlineStyle: {\n color: '#3388ff',\n dashArray: '5,5',\n },\n pathOptions: null,\n cursorMarker: true,\n finishOn: null,\n markerStyle: {\n draggable: true,\n icon: L.icon(),\n },\n hideMiddleMarkers: false,\n minRadiusCircle: null,\n maxRadiusCircle: null,\n minRadiusCircleMarker: null,\n maxRadiusCircleMarker: null,\n resizeableCircleMarker: false,\n resizableCircle: true,\n markerEditable: true,\n continueDrawing: false,\n snapSegment: true,\n requireSnapToFinish: false,\n rectangleAngle: 0,\n },\n setOptions(options) {\n L.Util.setOptions(this, options);\n this.setStyle(this.options);\n },\n setStyle() {},\n getOptions() {\n return this.options;\n },\n initialize(map) {\n // Overwriting the default tooltipAnchor of the default Marker Icon, because the tooltip functionality was updated but not the anchor in the Icon\n // Issue https://github.com/Leaflet/Leaflet/issues/7302 - Leaflet v1.7.1\n const defaultIcon = new L.Icon.Default();\n defaultIcon.options.tooltipAnchor = [0, 0];\n this.options.markerStyle.icon = defaultIcon;\n\n // save the map\n this._map = map;\n\n // define all possible shapes that can be drawn\n this.shapes = [\n 'Marker',\n 'CircleMarker',\n 'Line',\n 'Polygon',\n 'Rectangle',\n 'Circle',\n 'Cut',\n 'Text',\n ];\n\n // initiate drawing class for our shapes\n this.shapes.forEach((shape) => {\n this[shape] = new L.PM.Draw[shape](this._map);\n });\n\n // TODO: Remove this with the next major release\n this.Marker.setOptions({ continueDrawing: true });\n this.CircleMarker.setOptions({ continueDrawing: true });\n },\n setPathOptions(options, mergeOptions = false) {\n if (!mergeOptions) {\n this.options.pathOptions = options;\n } else {\n this.options.pathOptions = merge(this.options.pathOptions, options);\n }\n },\n getShapes() {\n // if somebody wants to know what shapes are available\n return this.shapes;\n },\n getShape() {\n // return the shape of the current drawing layer\n return this._shape;\n },\n enable(shape, options) {\n if (!shape) {\n throw new Error(\n `Error: Please pass a shape as a parameter. Possible shapes are: ${this.getShapes().join(\n ','\n )}`\n );\n }\n\n // disable drawing for all shapes\n this.disable();\n\n // enable draw for a shape\n this[shape].enable(options);\n },\n disable() {\n // there can only be one drawing mode active at a time on a map\n // so it doesn't matter which one should be disabled.\n // just disable all of them\n this.shapes.forEach((shape) => {\n this[shape].disable();\n });\n },\n addControls() {\n // add control buttons for our shapes\n this.shapes.forEach((shape) => {\n this[shape].addButton();\n });\n },\n getActiveShape() {\n // returns the active shape\n let enabledShape;\n this.shapes.forEach((shape) => {\n if (this[shape]._enabled) {\n enabledShape = shape;\n }\n });\n return enabledShape;\n },\n _setGlobalDrawMode() {\n // extended to all PM.Draw shapes\n if (this._shape === 'Cut') {\n this._fireGlobalCutModeToggled();\n } else {\n this._fireGlobalDrawModeToggled();\n }\n\n const layers = [];\n this._map.eachLayer((layer) => {\n if (\n layer instanceof L.Polyline ||\n layer instanceof L.Marker ||\n layer instanceof L.Circle ||\n layer instanceof L.CircleMarker ||\n layer instanceof L.ImageOverlay\n ) {\n // filter out everything that's leaflet-geoman specific temporary stuff\n if (!layer._pmTempLayer) {\n layers.push(layer);\n }\n }\n });\n\n if (this._enabled) {\n layers.forEach((layer) => {\n L.PM.Utils.disablePopup(layer);\n });\n } else {\n layers.forEach((layer) => {\n L.PM.Utils.enablePopup(layer);\n });\n }\n },\n\n createNewDrawInstance(name, jsClass) {\n const instance = this._getShapeFromBtnName(jsClass);\n if (this[name]) {\n throw new TypeError('Draw Type already exists');\n }\n if (!L.PM.Draw[instance]) {\n throw new TypeError(`There is no class L.PM.Draw.${instance}`);\n }\n\n this[name] = new L.PM.Draw[instance](this._map);\n this[name].toolbarButtonName = name;\n this[name]._shape = name;\n this.shapes.push(name);\n\n // needed when extended / copied from a custom instance\n if (this[jsClass]) {\n this[name].setOptions(this[jsClass].options);\n }\n // Re-init the options, so it is not referenced with the default Draw class\n this[name].setOptions(this[name].options);\n\n return this[name];\n },\n _getShapeFromBtnName(name) {\n const shapeMapping = {\n drawMarker: 'Marker',\n drawCircle: 'Circle',\n drawPolygon: 'Polygon',\n drawPolyline: 'Line',\n drawRectangle: 'Rectangle',\n drawCircleMarker: 'CircleMarker',\n editMode: 'Edit',\n dragMode: 'Drag',\n cutPolygon: 'Cut',\n removalMode: 'Removal',\n rotateMode: 'Rotate',\n drawText: 'Text',\n };\n\n if (shapeMapping[name]) {\n return shapeMapping[name];\n }\n return this[name] ? this[name]._shape : name;\n },\n _finishLayer(layer) {\n if (layer.pm) {\n // add the pm options from drawing to the new layer (edit)\n layer.pm.setOptions(this.options);\n // set the shape (can be a custom shape)\n layer.pm._shape = this._shape;\n // apply the map to the new created layer in the pm object\n layer.pm._map = this._map;\n }\n this._addDrawnLayerProp(layer);\n },\n _addDrawnLayerProp(layer) {\n layer._drawnByGeoman = true;\n },\n _setPane(layer, type) {\n if (type === 'layerPane') {\n layer.options.pane =\n (this._map.pm.globalOptions.panes &&\n this._map.pm.globalOptions.panes.layerPane) ||\n 'overlayPane';\n } else if (type === 'vertexPane') {\n layer.options.pane =\n (this._map.pm.globalOptions.panes &&\n this._map.pm.globalOptions.panes.vertexPane) ||\n 'markerPane';\n } else if (type === 'markerPane') {\n layer.options.pane =\n (this._map.pm.globalOptions.panes &&\n this._map.pm.globalOptions.panes.markerPane) ||\n 'markerPane';\n }\n },\n _isFirstLayer() {\n const map = this._map || this._layer._map;\n return map.pm.getGeomanLayers().length === 0;\n },\n});\n\nexport default Draw;\n","import { hasValues, prioritiseSort } from '../helpers';\n\nconst SnapMixin = {\n _initSnappableMarkers() {\n this.options.snapDistance = this.options.snapDistance || 30;\n this.options.snapSegment =\n this.options.snapSegment === undefined ? true : this.options.snapSegment;\n\n this._assignEvents(this._markers);\n\n this._layer.off('pm:dragstart', this._unsnap, this);\n this._layer.on('pm:dragstart', this._unsnap, this);\n },\n _disableSnapping() {\n this._layer.off('pm:dragstart', this._unsnap, this);\n },\n _assignEvents(markerArr) {\n // loop through marker array and assign events to the markers\n markerArr.forEach((marker) => {\n // if the marker is another array (Multipolygon stuff), recursively do this again\n if (Array.isArray(marker)) {\n this._assignEvents(marker);\n return;\n }\n\n // add handleSnapping event on drag\n marker.off('drag', this._handleSnapping, this);\n marker.on('drag', this._handleSnapping, this);\n\n // cleanup event on dragend\n marker.off('dragend', this._cleanupSnapping, this);\n marker.on('dragend', this._cleanupSnapping, this);\n });\n },\n _cleanupSnapping(e) {\n if (e) {\n // reset snap flag of the dragged helper-marker\n const marker = e.target;\n marker._snapped = false;\n }\n // delete it, we need to refresh this with each start of a drag because\n // meanwhile, new layers could've been added to the map\n delete this._snapList;\n\n if (this.throttledList) {\n this._map.off('layeradd', this.throttledList, this);\n this.throttledList = undefined;\n }\n\n // remove map event\n this._map.off('layerremove', this._handleSnapLayerRemoval, this);\n\n if (this.debugIndicatorLines) {\n this.debugIndicatorLines.forEach((line) => {\n line.remove();\n });\n }\n },\n _handleThrottleSnapping() {\n // we check if the throttledList is existing, else the function is deleted but the `layeradd` event calls it.\n // this made problems when layer was removed and added to the map in the `pm:create` event\n if (this.throttledList) {\n this._createSnapList();\n }\n },\n _handleSnapping(e) {\n const marker = e.target;\n marker._snapped = false;\n\n if (!this.throttledList) {\n this.throttledList = L.Util.throttle(\n this._handleThrottleSnapping,\n 100,\n this\n );\n }\n\n // if snapping is disabled via holding ALT during drag, stop right here\n // we need to check for the altKey on the move event, because keydown event is to slow ...\n if (e?.originalEvent?.altKey || this._map?.pm?.Keyboard.isAltKeyPressed()) {\n return false;\n }\n\n // create a list of layers that the marker could snap to\n // this isn't inside a movestart/dragstart callback because middlemarkers are initialized\n // after dragstart/movestart so it wouldn't fire for them\n if (this._snapList === undefined) {\n this._createSnapList();\n\n // re-create the snaplist again when a layer is added during draw\n this._map.off('layeradd', this.throttledList, this);\n this._map.on('layeradd', this.throttledList, this);\n }\n\n // if there are no layers to snap to, stop here\n if (this._snapList.length <= 0) {\n return false;\n }\n\n // get the closest layer, it's closest latlng, segment and the distance\n const closestLayer = this._calcClosestLayer(\n marker.getLatLng(),\n this._snapList\n );\n\n // if no layers found. Can happen when circle is the only visible layer on the map and the hidden snapping-border circle layer is also on the map\n if (Object.keys(closestLayer).length === 0) {\n return false;\n }\n\n const isMarker =\n closestLayer.layer instanceof L.Marker ||\n closestLayer.layer instanceof L.CircleMarker ||\n !this.options.snapSegment;\n\n // find the final latlng that we want to snap to\n let snapLatLng;\n if (!isMarker) {\n snapLatLng = this._checkPrioritiySnapping(closestLayer);\n } else {\n snapLatLng = closestLayer.latlng;\n }\n\n // minimal distance before marker snaps (in pixels)\n const minDistance = this.options.snapDistance;\n\n // event info for pm:snap and pm:unsnap\n const eventInfo = {\n marker,\n shape: this._shape,\n snapLatLng,\n segment: closestLayer.segment,\n layer: this._layer,\n workingLayer: this._layer,\n layerInteractedWith: closestLayer.layer, // for lack of a better property name\n distance: closestLayer.distance,\n };\n\n this._fireSnapDrag(eventInfo.marker, eventInfo);\n this._fireSnapDrag(this._layer, eventInfo);\n\n if (closestLayer.distance < minDistance) {\n // snap the marker\n marker._orgLatLng = marker.getLatLng();\n // TODO: if the origin marker has a altitude is applied to the snapped layer too, do we want this?\n marker.setLatLng(snapLatLng);\n\n marker._snapped = true;\n marker._snapInfo = eventInfo;\n\n const triggerSnap = () => {\n this._snapLatLng = snapLatLng;\n this._fireSnap(marker, eventInfo);\n this._fireSnap(this._layer, eventInfo);\n };\n\n // check if the snapping position differs from the last snap\n // Thanks Max & car2go Team\n const a = this._snapLatLng || {};\n const b = snapLatLng || {};\n\n if (a.lat !== b.lat || a.lng !== b.lng) {\n triggerSnap();\n }\n } else if (this._snapLatLng) {\n // no more snapping\n\n // if it was previously snapped...\n // ...unsnap\n this._unsnap(eventInfo);\n\n marker._snapped = false;\n marker._snapInfo = undefined;\n\n // and fire unsnap event\n this._fireUnsnap(eventInfo.marker, eventInfo);\n this._fireUnsnap(this._layer, eventInfo);\n }\n\n return true;\n },\n _createSnapList() {\n let layers = [];\n const debugIndicatorLines = [];\n const map = this._map;\n\n map.off('layerremove', this._handleSnapLayerRemoval, this);\n map.on('layerremove', this._handleSnapLayerRemoval, this);\n\n // find all layers that are or inherit from Polylines... and markers that are not\n // temporary markers of polygon-edits\n map.eachLayer((layer) => {\n if (\n (layer instanceof L.Polyline ||\n layer instanceof L.Marker ||\n layer instanceof L.CircleMarker ||\n layer instanceof L.ImageOverlay) &&\n layer.options.snapIgnore !== true\n ) {\n // if snapIgnore === false the layer will be always snappable\n if (\n layer.options.snapIgnore === undefined &&\n ((!L.PM.optIn && layer.options.pmIgnore === true) || // if optIn is not set and pmIgnore is true, the layer will be ignored\n (L.PM.optIn && layer.options.pmIgnore !== false)) // if optIn is true and pmIgnore is not false, the layer will be ignored\n ) {\n return;\n }\n\n // adds a hidden polygon which matches the border of the circle\n if (\n (layer instanceof L.Circle || layer instanceof L.CircleMarker) &&\n layer.pm &&\n layer.pm._hiddenPolyCircle\n ) {\n layers.push(layer.pm._hiddenPolyCircle);\n } else if (layer instanceof L.ImageOverlay) {\n layer = L.rectangle(layer.getBounds());\n }\n layers.push(layer);\n\n // this is for debugging\n const debugLine = L.polyline([], { color: 'red', pmIgnore: true });\n debugLine._pmTempLayer = true;\n debugIndicatorLines.push(debugLine);\n if (layer instanceof L.Circle || layer instanceof L.CircleMarker) {\n debugIndicatorLines.push(debugLine);\n }\n\n // uncomment 👇 this line to show helper lines for debugging\n // debugLine.addTo(map);\n }\n });\n\n // ...except myself\n layers = layers.filter((layer) => this._layer !== layer);\n\n // also remove everything that has no coordinates yet\n layers = layers.filter(\n (layer) => layer._latlng || (layer._latlngs && hasValues(layer._latlngs))\n );\n\n // finally remove everything that's leaflet-geoman specific temporary stuff\n layers = layers.filter((layer) => !layer._pmTempLayer);\n\n // save snaplist from layers and the other snap layers added from other classes/scripts\n if (this._otherSnapLayers) {\n this._otherSnapLayers.forEach(() => {\n // this is for debugging\n const debugLine = L.polyline([], { color: 'red', pmIgnore: true });\n debugLine._pmTempLayer = true;\n debugIndicatorLines.push(debugLine);\n });\n this._snapList = layers.concat(this._otherSnapLayers);\n } else {\n this._snapList = layers;\n }\n\n this.debugIndicatorLines = debugIndicatorLines;\n },\n _handleSnapLayerRemoval({ layer }) {\n if (!layer._leaflet_id) {\n return;\n }\n // find the layers index in snaplist\n const index = this._snapList.findIndex(\n (e) => e._leaflet_id === layer._leaflet_id\n );\n if (index > -1) {\n // remove it from the snaplist\n this._snapList.splice(index, 1);\n }\n },\n _calcClosestLayer(latlng, layers) {\n return this._calcClosestLayers(latlng, layers, 1)[0];\n },\n _calcClosestLayers(latlng, layers, amount = 1) {\n // the closest polygon to our dragged marker latlng\n let closestLayers = [];\n let closestLayer = {};\n\n // loop through the layers\n layers.forEach((layer, index) => {\n // For Circles and CircleMarkers to prevent that they snap to the own borders.\n if (layer._parentCopy && layer._parentCopy === this._layer) {\n return;\n }\n // find the closest latlng, segment and the distance of this layer to the dragged marker latlng\n const results = this._calcLayerDistances(latlng, layer);\n results.distance = Math.floor(results.distance);\n\n if (this.debugIndicatorLines) {\n if (!this.debugIndicatorLines[index]) {\n const debugLine = L.polyline([], { color: 'red', pmIgnore: true });\n debugLine._pmTempLayer = true;\n this.debugIndicatorLines[index] = debugLine;\n }\n\n // show indicator lines, it's for debugging\n this.debugIndicatorLines[index].setLatLngs([latlng, results.latlng]);\n }\n\n // save the info if it doesn't exist or if the distance is smaller than the previous one\n if (\n amount === 1 &&\n (closestLayer.distance === undefined ||\n results.distance - 5 <= closestLayer.distance)\n ) {\n // if the layer is less then 5 pixels away, we treat it as same distance and sort it based on priority\n if (results.distance + 5 < closestLayer.distance) {\n closestLayers = [];\n }\n closestLayer = results;\n closestLayer.layer = layer;\n closestLayers.push(closestLayer);\n } else if (amount !== 1) {\n closestLayer = {};\n closestLayer = results;\n closestLayer.layer = layer;\n closestLayers.push(closestLayer);\n }\n });\n if (amount !== 1) {\n // sort the layers by distance\n closestLayers = closestLayers.sort((a, b) => a.distance - b.distance);\n }\n\n if (amount === -1) {\n amount = closestLayers.length;\n }\n\n // return the closest layer and it's data\n // if there is no closest layer, return an empty object\n const result = this._getClosestLayerByPriority(closestLayers, amount);\n if (L.Util.isArray(result)) {\n return result;\n }\n return [result];\n },\n _calcLayerDistances(latlng, layer) {\n const map = this._map;\n\n // is this a marker?\n const isMarker =\n layer instanceof L.Marker || layer instanceof L.CircleMarker;\n\n // is it a polygon?\n const isPolygon = layer instanceof L.Polygon;\n\n // the point P which we want to snap (probpably the marker that is dragged)\n const P = latlng;\n\n // the coords of the layer\n\n if (isMarker) {\n // return the info for the marker, no more calculations needed\n const latlngs = layer.getLatLng();\n return {\n latlng: { ...latlngs },\n distance: this._getDistance(map, latlngs, P),\n };\n }\n\n return this._calcLatLngDistances(P, layer.getLatLngs(), map, isPolygon);\n },\n _calcLatLngDistances(latlng, latlngs, map, closedShape = false) {\n // the closest coord of the layer\n let closestCoord;\n\n // the shortest distance from latlng to closestCoord\n let shortestDistance;\n\n // the closest segment (line between two points) of the layer\n let closestSegment;\n\n const loopThroughCoords = (coords) => {\n coords.forEach((coord, index) => {\n if (Array.isArray(coord)) {\n loopThroughCoords(coord);\n return;\n }\n\n if (this.options.snapSegment) {\n // take this coord (A)...\n const A = coord;\n let nextIndex;\n\n // and the next coord (B) as points\n if (closedShape) {\n nextIndex = index + 1 === coords.length ? 0 : index + 1;\n } else {\n nextIndex = index + 1 === coords.length ? undefined : index + 1;\n }\n\n const B = coords[nextIndex];\n if (B) {\n // calc the distance between latlng and AB-segment\n const distance = this._getDistanceToSegment(map, latlng, A, B);\n\n // is the distance shorter than the previous one? Save it and the segment\n if (shortestDistance === undefined || distance < shortestDistance) {\n shortestDistance = distance;\n closestSegment = [A, B];\n }\n }\n } else {\n // Only snap on the coords\n const distancePoint = this._getDistance(map, latlng, coord);\n\n if (\n shortestDistance === undefined ||\n distancePoint < shortestDistance\n ) {\n shortestDistance = distancePoint;\n closestCoord = coord;\n }\n }\n });\n };\n\n loopThroughCoords(latlngs);\n\n if (this.options.snapSegment) {\n // now, take the closest segment (closestSegment) and calc the closest point to latlng on it.\n const C = this._getClosestPointOnSegment(\n map,\n latlng,\n closestSegment[0],\n closestSegment[1]\n );\n\n // return the latlng of that sucker\n return {\n latlng: { ...C },\n segment: closestSegment,\n distance: shortestDistance,\n };\n }\n // Only snap on the coords\n // return the closest coord\n return {\n latlng: closestCoord,\n distance: shortestDistance,\n };\n },\n _getClosestLayerByPriority(layers, amount = 1) {\n // sort the layers by creation, so it is snapping to the oldest layer from the same shape\n layers = layers.sort((a, b) => a._leaflet_id - b._leaflet_id);\n\n const shapes = [\n 'Marker',\n 'CircleMarker',\n 'Circle',\n 'Line',\n 'Polygon',\n 'Rectangle',\n ];\n const order = this._map.pm.globalOptions.snappingOrder || [];\n\n let lastIndex = 0;\n const prioOrder = {};\n // merge user-preferred priority with default priority\n order.concat(shapes).forEach((shape) => {\n if (!prioOrder[shape]) {\n lastIndex += 1;\n prioOrder[shape] = lastIndex;\n }\n });\n\n // sort layers by priority\n layers.sort(prioritiseSort('instanceofShape', prioOrder));\n if (amount === 1) {\n return layers[0] || {};\n }\n return layers.slice(0, amount);\n },\n // we got the point we want to snap to (C), but we need to check if a coord of the polygon\n // receives priority over C as the snapping point. Let's check this here\n _checkPrioritiySnapping(closestLayer) {\n const map = this._map;\n\n // A and B are the points of the closest segment to P (the marker position we want to snap)\n const A = closestLayer.segment[0];\n const B = closestLayer.segment[1];\n\n // C is the point we would snap to on the segment.\n // The closest point on the closest segment of the closest polygon to P. That's right.\n const C = closestLayer.latlng;\n\n // distances from A to C and B to C to check which one is closer to C\n const distanceAC = this._getDistance(map, A, C);\n const distanceBC = this._getDistance(map, B, C);\n\n // closest latlng of A and B to C\n let closestVertexLatLng = distanceAC < distanceBC ? A : B;\n\n // distance between closestVertexLatLng and C\n let shortestDistance = distanceAC < distanceBC ? distanceAC : distanceBC;\n\n // snap to middle (M) of segment if option is enabled\n if (this.options.snapMiddle) {\n const M = L.PM.Utils.calcMiddleLatLng(map, A, B);\n const distanceMC = this._getDistance(map, M, C);\n\n if (distanceMC < distanceAC && distanceMC < distanceBC) {\n // M is the nearest vertex\n closestVertexLatLng = M;\n shortestDistance = distanceMC;\n }\n }\n\n // the distance that needs to be undercut to trigger priority\n const priorityDistance = this.options.snapDistance;\n\n // the latlng we ultemately want to snap to\n let snapLatlng;\n\n // if C is closer to the closestVertexLatLng (A, B or M) than the snapDistance,\n // the closestVertexLatLng has priority over C as the snapping point.\n if (shortestDistance < priorityDistance) {\n snapLatlng = closestVertexLatLng;\n } else {\n snapLatlng = C;\n }\n\n // return the copy of snapping point\n return { ...snapLatlng };\n },\n _unsnap() {\n // delete the last snap\n delete this._snapLatLng;\n },\n _getClosestPointOnSegment(map, latlng, latlngA, latlngB) {\n let maxzoom = map.getMaxZoom();\n if (maxzoom === Infinity) {\n maxzoom = map.getZoom();\n }\n const P = map.project(latlng, maxzoom);\n const A = map.project(latlngA, maxzoom);\n const B = map.project(latlngB, maxzoom);\n const closest = L.LineUtil.closestPointOnSegment(P, A, B);\n return map.unproject(closest, maxzoom);\n },\n _getDistanceToSegment(map, latlng, latlngA, latlngB) {\n const P = map.latLngToLayerPoint(latlng);\n const A = map.latLngToLayerPoint(latlngA);\n const B = map.latLngToLayerPoint(latlngB);\n return L.LineUtil.pointToSegmentDistance(P, A, B);\n },\n _getDistance(map, latlngA, latlngB) {\n return map\n .latLngToLayerPoint(latlngA)\n .distanceTo(map.latLngToLayerPoint(latlngB));\n },\n};\n\nexport default SnapMixin;\n","import Draw from './L.PM.Draw';\nimport { getTranslation } from '../helpers';\n\nDraw.Marker = Draw.extend({\n initialize(map) {\n this._map = map;\n this._shape = 'Marker';\n this.toolbarButtonName = 'drawMarker';\n },\n enable(options) {\n // TODO: Think about if these options could be passed globally for all\n // instances of L.PM.Draw. So a dev could set drawing style one time as some kind of config\n L.Util.setOptions(this, options);\n\n // change enabled state\n this._enabled = true;\n\n // change map cursor\n this._map.getContainer().classList.add('geoman-draw-cursor');\n\n // create a marker on click on the map\n this._map.on('click', this._createMarker, this);\n\n // toggle the draw button of the Toolbar in case drawing mode got enabled without the button\n this._map.pm.Toolbar.toggleButton(this.toolbarButtonName, true);\n\n // this is the hintmarker on the mouse cursor\n this._hintMarker = L.marker(\n this._map.getCenter(),\n this.options.markerStyle\n );\n this._setPane(this._hintMarker, 'markerPane');\n this._hintMarker._pmTempLayer = true;\n this._hintMarker.addTo(this._map);\n\n // add tooltip to hintmarker\n if (this.options.tooltips) {\n this._hintMarker\n .bindTooltip(getTranslation('tooltips.placeMarker'), {\n permanent: true,\n offset: L.point(0, 10),\n direction: 'bottom',\n\n opacity: 0.8,\n })\n .openTooltip();\n }\n\n // this is just to keep the snappable mixin happy\n this._layer = this._hintMarker;\n\n // sync hint marker with mouse cursor\n this._map.on('mousemove', this._syncHintMarker, this);\n\n // enable edit mode for existing markers\n if (this.options.markerEditable) {\n this._map.eachLayer((layer) => {\n if (this.isRelevantMarker(layer)) {\n layer.pm.enable();\n }\n });\n }\n\n // fire drawstart event\n this._fireDrawStart();\n this._setGlobalDrawMode();\n },\n disable() {\n // cancel, if drawing mode isn't even enabled\n if (!this._enabled) {\n return;\n }\n\n // change enabled state\n this._enabled = false;\n\n // reset cursor\n this._map.getContainer().classList.remove('geoman-draw-cursor');\n\n // undbind click event, don't create a marker on click anymore\n this._map.off('click', this._createMarker, this);\n\n // remove hint marker\n this._hintMarker.remove();\n\n // remove event listener to sync hint marker\n this._map.off('mousemove', this._syncHintMarker, this);\n\n // disable dragging and removing for all markers\n this._map.eachLayer((layer) => {\n if (this.isRelevantMarker(layer)) {\n layer.pm.disable();\n }\n });\n\n // toggle the draw button of the Toolbar in case drawing mode got disabled without the button\n this._map.pm.Toolbar.toggleButton(this.toolbarButtonName, false);\n\n // cleanup snapping\n if (this.options.snappable) {\n this._cleanupSnapping();\n }\n\n // fire drawend event\n this._fireDrawEnd();\n this._setGlobalDrawMode();\n },\n enabled() {\n return this._enabled;\n },\n toggle(options) {\n if (this.enabled()) {\n this.disable();\n } else {\n this.enable(options);\n }\n },\n isRelevantMarker(layer) {\n return (\n layer instanceof L.Marker &&\n layer.pm &&\n !layer._pmTempLayer &&\n !layer.pm._initTextMarker\n );\n },\n _syncHintMarker(e) {\n // move the cursor marker\n this._hintMarker.setLatLng(e.latlng);\n\n // if snapping is enabled, do it\n if (this.options.snappable) {\n const fakeDragEvent = e;\n fakeDragEvent.target = this._hintMarker;\n this._handleSnapping(fakeDragEvent);\n }\n\n this._fireChange(this._hintMarker.getLatLng(), 'Draw');\n },\n _createMarker(e) {\n if (!e.latlng) {\n return;\n }\n\n // If snap finish is required but the last marker wasn't snapped, do not finish the shape!\n if (\n this.options.requireSnapToFinish &&\n !this._hintMarker._snapped &&\n !this._isFirstLayer()\n ) {\n return;\n }\n\n // assign the coordinate of the click to the hintMarker, that's necessary for\n // mobile where the marker can't follow a cursor\n if (!this._hintMarker._snapped) {\n this._hintMarker.setLatLng(e.latlng);\n }\n\n // get coordinate for new vertex by hintMarker (cursor marker)\n const latlng = this._hintMarker.getLatLng();\n\n // create marker\n const marker = new L.Marker(latlng, this.options.markerStyle);\n this._setPane(marker, 'markerPane');\n this._finishLayer(marker);\n\n if (!marker.pm) {\n // if pm is not create we don't apply dragging to the marker (draggable is applied to the marker, when it is added to the map )\n marker.options.draggable = false;\n }\n // add marker to the map\n marker.addTo(this._map.pm._getContainingLayer());\n\n if (marker.pm && this.options.markerEditable) {\n // enable editing for the marker\n marker.pm.enable();\n } else if (marker.dragging) {\n marker.dragging.disable();\n }\n\n // fire the pm:create event and pass shape and marker\n this._fireCreate(marker);\n\n this._cleanupSnapping();\n\n if (!this.options.continueDrawing) {\n this.disable();\n }\n },\n setStyle() {\n if (this.options.markerStyle?.icon) {\n this._hintMarker?.setIcon(this.options.markerStyle.icon);\n }\n },\n});\n","/**\n * @module helpers\n */\n/**\n * Earth Radius used with the Harvesine formula and approximates using a spherical (non-ellipsoid) Earth.\n *\n * @memberof helpers\n * @type {number}\n */\nexport var earthRadius = 6371008.8;\n/**\n * Unit of measurement factors using a spherical (non-ellipsoid) earth radius.\n *\n * @memberof helpers\n * @type {Object}\n */\nexport var factors = {\n centimeters: earthRadius * 100,\n centimetres: earthRadius * 100,\n degrees: earthRadius / 111325,\n feet: earthRadius * 3.28084,\n inches: earthRadius * 39.37,\n kilometers: earthRadius / 1000,\n kilometres: earthRadius / 1000,\n meters: earthRadius,\n metres: earthRadius,\n miles: earthRadius / 1609.344,\n millimeters: earthRadius * 1000,\n millimetres: earthRadius * 1000,\n nauticalmiles: earthRadius / 1852,\n radians: 1,\n yards: earthRadius * 1.0936,\n};\n/**\n * Units of measurement factors based on 1 meter.\n *\n * @memberof helpers\n * @type {Object}\n */\nexport var unitsFactors = {\n centimeters: 100,\n centimetres: 100,\n degrees: 1 / 111325,\n feet: 3.28084,\n inches: 39.37,\n kilometers: 1 / 1000,\n kilometres: 1 / 1000,\n meters: 1,\n metres: 1,\n miles: 1 / 1609.344,\n millimeters: 1000,\n millimetres: 1000,\n nauticalmiles: 1 / 1852,\n radians: 1 / earthRadius,\n yards: 1.0936133,\n};\n/**\n * Area of measurement factors based on 1 square meter.\n *\n * @memberof helpers\n * @type {Object}\n */\nexport var areaFactors = {\n acres: 0.000247105,\n centimeters: 10000,\n centimetres: 10000,\n feet: 10.763910417,\n hectares: 0.0001,\n inches: 1550.003100006,\n kilometers: 0.000001,\n kilometres: 0.000001,\n meters: 1,\n metres: 1,\n miles: 3.86e-7,\n millimeters: 1000000,\n millimetres: 1000000,\n yards: 1.195990046,\n};\n/**\n * Wraps a GeoJSON {@link Geometry} in a GeoJSON {@link Feature}.\n *\n * @name feature\n * @param {Geometry} geometry input geometry\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a GeoJSON Feature\n * @example\n * var geometry = {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 50]\n * };\n *\n * var feature = turf.feature(geometry);\n *\n * //=feature\n */\nexport function feature(geom, properties, options) {\n if (options === void 0) { options = {}; }\n var feat = { type: \"Feature\" };\n if (options.id === 0 || options.id) {\n feat.id = options.id;\n }\n if (options.bbox) {\n feat.bbox = options.bbox;\n }\n feat.properties = properties || {};\n feat.geometry = geom;\n return feat;\n}\n/**\n * Creates a GeoJSON {@link Geometry} from a Geometry string type & coordinates.\n * For GeometryCollection type use `helpers.geometryCollection`\n *\n * @name geometry\n * @param {string} type Geometry Type\n * @param {Array} coordinates Coordinates\n * @param {Object} [options={}] Optional Parameters\n * @returns {Geometry} a GeoJSON Geometry\n * @example\n * var type = \"Point\";\n * var coordinates = [110, 50];\n * var geometry = turf.geometry(type, coordinates);\n * // => geometry\n */\nexport function geometry(type, coordinates, _options) {\n if (_options === void 0) { _options = {}; }\n switch (type) {\n case \"Point\":\n return point(coordinates).geometry;\n case \"LineString\":\n return lineString(coordinates).geometry;\n case \"Polygon\":\n return polygon(coordinates).geometry;\n case \"MultiPoint\":\n return multiPoint(coordinates).geometry;\n case \"MultiLineString\":\n return multiLineString(coordinates).geometry;\n case \"MultiPolygon\":\n return multiPolygon(coordinates).geometry;\n default:\n throw new Error(type + \" is invalid\");\n }\n}\n/**\n * Creates a {@link Point} {@link Feature} from a Position.\n *\n * @name point\n * @param {Array} coordinates longitude, latitude position (each in decimal degrees)\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a Point feature\n * @example\n * var point = turf.point([-75.343, 39.984]);\n *\n * //=point\n */\nexport function point(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n if (!coordinates) {\n throw new Error(\"coordinates is required\");\n }\n if (!Array.isArray(coordinates)) {\n throw new Error(\"coordinates must be an Array\");\n }\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be at least 2 numbers long\");\n }\n if (!isNumber(coordinates[0]) || !isNumber(coordinates[1])) {\n throw new Error(\"coordinates must contain numbers\");\n }\n var geom = {\n type: \"Point\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\n/**\n * Creates a {@link Point} {@link FeatureCollection} from an Array of Point coordinates.\n *\n * @name points\n * @param {Array>} coordinates an array of Points\n * @param {Object} [properties={}] Translate these properties to each Feature\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north]\n * associated with the FeatureCollection\n * @param {string|number} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection} Point Feature\n * @example\n * var points = turf.points([\n * [-75, 39],\n * [-80, 45],\n * [-78, 50]\n * ]);\n *\n * //=points\n */\nexport function points(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n return featureCollection(coordinates.map(function (coords) {\n return point(coords, properties);\n }), options);\n}\n/**\n * Creates a {@link Polygon} {@link Feature} from an Array of LinearRings.\n *\n * @name polygon\n * @param {Array>>} coordinates an array of LinearRings\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} Polygon Feature\n * @example\n * var polygon = turf.polygon([[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]], { name: 'poly1' });\n *\n * //=polygon\n */\nexport function polygon(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n for (var _i = 0, coordinates_1 = coordinates; _i < coordinates_1.length; _i++) {\n var ring = coordinates_1[_i];\n if (ring.length < 4) {\n throw new Error(\"Each LinearRing of a Polygon must have 4 or more Positions.\");\n }\n for (var j = 0; j < ring[ring.length - 1].length; j++) {\n // Check if first point of Polygon contains two numbers\n if (ring[ring.length - 1][j] !== ring[0][j]) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n }\n }\n var geom = {\n type: \"Polygon\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\n/**\n * Creates a {@link Polygon} {@link FeatureCollection} from an Array of Polygon coordinates.\n *\n * @name polygons\n * @param {Array>>>} coordinates an array of Polygon coordinates\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection} Polygon FeatureCollection\n * @example\n * var polygons = turf.polygons([\n * [[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]],\n * [[[-15, 42], [-14, 46], [-12, 41], [-17, 44], [-15, 42]]],\n * ]);\n *\n * //=polygons\n */\nexport function polygons(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n return featureCollection(coordinates.map(function (coords) {\n return polygon(coords, properties);\n }), options);\n}\n/**\n * Creates a {@link LineString} {@link Feature} from an Array of Positions.\n *\n * @name lineString\n * @param {Array>} coordinates an array of Positions\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} LineString Feature\n * @example\n * var linestring1 = turf.lineString([[-24, 63], [-23, 60], [-25, 65], [-20, 69]], {name: 'line 1'});\n * var linestring2 = turf.lineString([[-14, 43], [-13, 40], [-15, 45], [-10, 49]], {name: 'line 2'});\n *\n * //=linestring1\n * //=linestring2\n */\nexport function lineString(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be an array of two or more positions\");\n }\n var geom = {\n type: \"LineString\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\n/**\n * Creates a {@link LineString} {@link FeatureCollection} from an Array of LineString coordinates.\n *\n * @name lineStrings\n * @param {Array>>} coordinates an array of LinearRings\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north]\n * associated with the FeatureCollection\n * @param {string|number} [options.id] Identifier associated with the FeatureCollection\n * @returns {FeatureCollection} LineString FeatureCollection\n * @example\n * var linestrings = turf.lineStrings([\n * [[-24, 63], [-23, 60], [-25, 65], [-20, 69]],\n * [[-14, 43], [-13, 40], [-15, 45], [-10, 49]]\n * ]);\n *\n * //=linestrings\n */\nexport function lineStrings(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n return featureCollection(coordinates.map(function (coords) {\n return lineString(coords, properties);\n }), options);\n}\n/**\n * Takes one or more {@link Feature|Features} and creates a {@link FeatureCollection}.\n *\n * @name featureCollection\n * @param {Feature[]} features input features\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {FeatureCollection} FeatureCollection of Features\n * @example\n * var locationA = turf.point([-75.343, 39.984], {name: 'Location A'});\n * var locationB = turf.point([-75.833, 39.284], {name: 'Location B'});\n * var locationC = turf.point([-75.534, 39.123], {name: 'Location C'});\n *\n * var collection = turf.featureCollection([\n * locationA,\n * locationB,\n * locationC\n * ]);\n *\n * //=collection\n */\nexport function featureCollection(features, options) {\n if (options === void 0) { options = {}; }\n var fc = { type: \"FeatureCollection\" };\n if (options.id) {\n fc.id = options.id;\n }\n if (options.bbox) {\n fc.bbox = options.bbox;\n }\n fc.features = features;\n return fc;\n}\n/**\n * Creates a {@link Feature} based on a\n * coordinate array. Properties can be added optionally.\n *\n * @name multiLineString\n * @param {Array>>} coordinates an array of LineStrings\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a MultiLineString feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiLine = turf.multiLineString([[[0,0],[10,10]]]);\n *\n * //=multiLine\n */\nexport function multiLineString(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n var geom = {\n type: \"MultiLineString\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\n/**\n * Creates a {@link Feature} based on a\n * coordinate array. Properties can be added optionally.\n *\n * @name multiPoint\n * @param {Array>} coordinates an array of Positions\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a MultiPoint feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiPt = turf.multiPoint([[0,0],[10,10]]);\n *\n * //=multiPt\n */\nexport function multiPoint(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n var geom = {\n type: \"MultiPoint\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\n/**\n * Creates a {@link Feature} based on a\n * coordinate array. Properties can be added optionally.\n *\n * @name multiPolygon\n * @param {Array>>>} coordinates an array of Polygons\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a multipolygon feature\n * @throws {Error} if no coordinates are passed\n * @example\n * var multiPoly = turf.multiPolygon([[[[0,0],[0,10],[10,10],[10,0],[0,0]]]]);\n *\n * //=multiPoly\n *\n */\nexport function multiPolygon(coordinates, properties, options) {\n if (options === void 0) { options = {}; }\n var geom = {\n type: \"MultiPolygon\",\n coordinates: coordinates,\n };\n return feature(geom, properties, options);\n}\n/**\n * Creates a {@link Feature} based on a\n * coordinate array. Properties can be added optionally.\n *\n * @name geometryCollection\n * @param {Array} geometries an array of GeoJSON Geometries\n * @param {Object} [properties={}] an Object of key-value pairs to add as properties\n * @param {Object} [options={}] Optional Parameters\n * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature\n * @param {string|number} [options.id] Identifier associated with the Feature\n * @returns {Feature} a GeoJSON GeometryCollection Feature\n * @example\n * var pt = turf.geometry(\"Point\", [100, 0]);\n * var line = turf.geometry(\"LineString\", [[101, 0], [102, 1]]);\n * var collection = turf.geometryCollection([pt, line]);\n *\n * // => collection\n */\nexport function geometryCollection(geometries, properties, options) {\n if (options === void 0) { options = {}; }\n var geom = {\n type: \"GeometryCollection\",\n geometries: geometries,\n };\n return feature(geom, properties, options);\n}\n/**\n * Round number to precision\n *\n * @param {number} num Number\n * @param {number} [precision=0] Precision\n * @returns {number} rounded number\n * @example\n * turf.round(120.4321)\n * //=120\n *\n * turf.round(120.4321, 2)\n * //=120.43\n */\nexport function round(num, precision) {\n if (precision === void 0) { precision = 0; }\n if (precision && !(precision >= 0)) {\n throw new Error(\"precision must be a positive number\");\n }\n var multiplier = Math.pow(10, precision || 0);\n return Math.round(num * multiplier) / multiplier;\n}\n/**\n * Convert a distance measurement (assuming a spherical Earth) from radians to a more friendly unit.\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet\n *\n * @name radiansToLength\n * @param {number} radians in radians across the sphere\n * @param {string} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} distance\n */\nexport function radiansToLength(radians, units) {\n if (units === void 0) { units = \"kilometers\"; }\n var factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return radians * factor;\n}\n/**\n * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into radians\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet\n *\n * @name lengthToRadians\n * @param {number} distance in real units\n * @param {string} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} radians\n */\nexport function lengthToRadians(distance, units) {\n if (units === void 0) { units = \"kilometers\"; }\n var factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return distance / factor;\n}\n/**\n * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into degrees\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, centimeters, kilometres, feet\n *\n * @name lengthToDegrees\n * @param {number} distance in real units\n * @param {string} [units=\"kilometers\"] can be degrees, radians, miles, inches, yards, metres,\n * meters, kilometres, kilometers.\n * @returns {number} degrees\n */\nexport function lengthToDegrees(distance, units) {\n return radiansToDegrees(lengthToRadians(distance, units));\n}\n/**\n * Converts any bearing angle from the north line direction (positive clockwise)\n * and returns an angle between 0-360 degrees (positive clockwise), 0 being the north line\n *\n * @name bearingToAzimuth\n * @param {number} bearing angle, between -180 and +180 degrees\n * @returns {number} angle between 0 and 360 degrees\n */\nexport function bearingToAzimuth(bearing) {\n var angle = bearing % 360;\n if (angle < 0) {\n angle += 360;\n }\n return angle;\n}\n/**\n * Converts an angle in radians to degrees\n *\n * @name radiansToDegrees\n * @param {number} radians angle in radians\n * @returns {number} degrees between 0 and 360 degrees\n */\nexport function radiansToDegrees(radians) {\n var degrees = radians % (2 * Math.PI);\n return (degrees * 180) / Math.PI;\n}\n/**\n * Converts an angle in degrees to radians\n *\n * @name degreesToRadians\n * @param {number} degrees angle between 0 and 360 degrees\n * @returns {number} angle in radians\n */\nexport function degreesToRadians(degrees) {\n var radians = degrees % 360;\n return (radians * Math.PI) / 180;\n}\n/**\n * Converts a length to the requested unit.\n * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet\n *\n * @param {number} length to be converted\n * @param {Units} [originalUnit=\"kilometers\"] of the length\n * @param {Units} [finalUnit=\"kilometers\"] returned unit\n * @returns {number} the converted length\n */\nexport function convertLength(length, originalUnit, finalUnit) {\n if (originalUnit === void 0) { originalUnit = \"kilometers\"; }\n if (finalUnit === void 0) { finalUnit = \"kilometers\"; }\n if (!(length >= 0)) {\n throw new Error(\"length must be a positive number\");\n }\n return radiansToLength(lengthToRadians(length, originalUnit), finalUnit);\n}\n/**\n * Converts a area to the requested unit.\n * Valid units: kilometers, kilometres, meters, metres, centimetres, millimeters, acres, miles, yards, feet, inches, hectares\n * @param {number} area to be converted\n * @param {Units} [originalUnit=\"meters\"] of the distance\n * @param {Units} [finalUnit=\"kilometers\"] returned unit\n * @returns {number} the converted area\n */\nexport function convertArea(area, originalUnit, finalUnit) {\n if (originalUnit === void 0) { originalUnit = \"meters\"; }\n if (finalUnit === void 0) { finalUnit = \"kilometers\"; }\n if (!(area >= 0)) {\n throw new Error(\"area must be a positive number\");\n }\n var startFactor = areaFactors[originalUnit];\n if (!startFactor) {\n throw new Error(\"invalid original units\");\n }\n var finalFactor = areaFactors[finalUnit];\n if (!finalFactor) {\n throw new Error(\"invalid final units\");\n }\n return (area / startFactor) * finalFactor;\n}\n/**\n * isNumber\n *\n * @param {*} num Number to validate\n * @returns {boolean} true/false\n * @example\n * turf.isNumber(123)\n * //=true\n * turf.isNumber('foo')\n * //=false\n */\nexport function isNumber(num) {\n return !isNaN(num) && num !== null && !Array.isArray(num);\n}\n/**\n * isObject\n *\n * @param {*} input variable to validate\n * @returns {boolean} true/false\n * @example\n * turf.isObject({elevation: 10})\n * //=true\n * turf.isObject('foo')\n * //=false\n */\nexport function isObject(input) {\n return !!input && input.constructor === Object;\n}\n/**\n * Validate BBox\n *\n * @private\n * @param {Array} bbox BBox to validate\n * @returns {void}\n * @throws Error if BBox is not valid\n * @example\n * validateBBox([-180, -40, 110, 50])\n * //=OK\n * validateBBox([-180, -40])\n * //=Error\n * validateBBox('Foo')\n * //=Error\n * validateBBox(5)\n * //=Error\n * validateBBox(null)\n * //=Error\n * validateBBox(undefined)\n * //=Error\n */\nexport function validateBBox(bbox) {\n if (!bbox) {\n throw new Error(\"bbox is required\");\n }\n if (!Array.isArray(bbox)) {\n throw new Error(\"bbox must be an Array\");\n }\n if (bbox.length !== 4 && bbox.length !== 6) {\n throw new Error(\"bbox must be an Array of 4 or 6 numbers\");\n }\n bbox.forEach(function (num) {\n if (!isNumber(num)) {\n throw new Error(\"bbox must only contain numbers\");\n }\n });\n}\n/**\n * Validate Id\n *\n * @private\n * @param {string|number} id Id to validate\n * @returns {void}\n * @throws Error if Id is not valid\n * @example\n * validateId([-180, -40, 110, 50])\n * //=Error\n * validateId([-180, -40])\n * //=Error\n * validateId('Foo')\n * //=OK\n * validateId(5)\n * //=OK\n * validateId(null)\n * //=Error\n * validateId(undefined)\n * //=Error\n */\nexport function validateId(id) {\n if (!id) {\n throw new Error(\"id is required\");\n }\n if ([\"string\", \"number\"].indexOf(typeof id) === -1) {\n throw new Error(\"id must be a number or a string\");\n }\n}\n","import { point } from \"@turf/helpers\";\n/**\n * Takes a {@link LineString|linestring}, {@link MultiLineString|multi-linestring},\n * {@link MultiPolygon|multi-polygon} or {@link Polygon|polygon} and\n * returns {@link Point|points} at all self-intersections.\n *\n * @name kinks\n * @param {Feature} featureIn input feature\n * @returns {FeatureCollection} self-intersections\n * @example\n * var poly = turf.polygon([[\n * [-12.034835, 8.901183],\n * [-12.060413, 8.899826],\n * [-12.03638, 8.873199],\n * [-12.059383, 8.871418],\n * [-12.034835, 8.901183]\n * ]]);\n *\n * var kinks = turf.kinks(poly);\n *\n * //addToMap\n * var addToMap = [poly, kinks]\n */\nexport default function kinks(featureIn) {\n var coordinates;\n var feature;\n var results = {\n type: \"FeatureCollection\",\n features: [],\n };\n if (featureIn.type === \"Feature\") {\n feature = featureIn.geometry;\n }\n else {\n feature = featureIn;\n }\n if (feature.type === \"LineString\") {\n coordinates = [feature.coordinates];\n }\n else if (feature.type === \"MultiLineString\") {\n coordinates = feature.coordinates;\n }\n else if (feature.type === \"MultiPolygon\") {\n coordinates = [].concat.apply([], feature.coordinates);\n }\n else if (feature.type === \"Polygon\") {\n coordinates = feature.coordinates;\n }\n else {\n throw new Error(\"Input must be a LineString, MultiLineString, \" +\n \"Polygon, or MultiPolygon Feature or Geometry\");\n }\n coordinates.forEach(function (line1) {\n coordinates.forEach(function (line2) {\n for (var i = 0; i < line1.length - 1; i++) {\n // start iteration at i, intersections for k < i have already\n // been checked in previous outer loop iterations\n for (var k = i; k < line2.length - 1; k++) {\n if (line1 === line2) {\n // segments are adjacent and always share a vertex, not a kink\n if (Math.abs(i - k) === 1) {\n continue;\n }\n // first and last segment in a closed lineString or ring always share a vertex, not a kink\n if (\n // segments are first and last segment of lineString\n i === 0 &&\n k === line1.length - 2 &&\n // lineString is closed\n line1[i][0] === line1[line1.length - 1][0] &&\n line1[i][1] === line1[line1.length - 1][1]) {\n continue;\n }\n }\n var intersection = lineIntersects(line1[i][0], line1[i][1], line1[i + 1][0], line1[i + 1][1], line2[k][0], line2[k][1], line2[k + 1][0], line2[k + 1][1]);\n if (intersection) {\n results.features.push(point([intersection[0], intersection[1]]));\n }\n }\n }\n });\n });\n return results;\n}\n// modified from http://jsfiddle.net/justin_c_rounds/Gd2S2/light/\nfunction lineIntersects(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) {\n // if the lines intersect, the result contains the x and y of the\n // intersection (treating the lines as infinite) and booleans for whether\n // line segment 1 or line segment 2 contain the point\n var denominator;\n var a;\n var b;\n var numerator1;\n var numerator2;\n var result = {\n x: null,\n y: null,\n onLine1: false,\n onLine2: false,\n };\n denominator =\n (line2EndY - line2StartY) * (line1EndX - line1StartX) -\n (line2EndX - line2StartX) * (line1EndY - line1StartY);\n if (denominator === 0) {\n if (result.x !== null && result.y !== null) {\n return result;\n }\n else {\n return false;\n }\n }\n a = line1StartY - line2StartY;\n b = line1StartX - line2StartX;\n numerator1 = (line2EndX - line2StartX) * a - (line2EndY - line2StartY) * b;\n numerator2 = (line1EndX - line1StartX) * a - (line1EndY - line1StartY) * b;\n a = numerator1 / denominator;\n b = numerator2 / denominator;\n // if we cast these lines infinitely in both directions, they intersect here:\n result.x = line1StartX + a * (line1EndX - line1StartX);\n result.y = line1StartY + a * (line1EndY - line1StartY);\n // if line1 is a segment and line2 is infinite, they intersect if:\n if (a >= 0 && a <= 1) {\n result.onLine1 = true;\n }\n // if line2 is a segment and line1 is infinite, they intersect if:\n if (b >= 0 && b <= 1) {\n result.onLine2 = true;\n }\n // if line1 and line2 are segments, they intersect if both of the above are true\n if (result.onLine1 && result.onLine2) {\n return [result.x, result.y];\n }\n else {\n return false;\n }\n}\n","import { isNumber, } from \"@turf/helpers\";\n/**\n * Unwrap a coordinate from a Point Feature, Geometry or a single coordinate.\n *\n * @name getCoord\n * @param {Array|Geometry|Feature} coord GeoJSON Point or an Array of numbers\n * @returns {Array} coordinates\n * @example\n * var pt = turf.point([10, 10]);\n *\n * var coord = turf.getCoord(pt);\n * //= [10, 10]\n */\nexport function getCoord(coord) {\n if (!coord) {\n throw new Error(\"coord is required\");\n }\n if (!Array.isArray(coord)) {\n if (coord.type === \"Feature\" &&\n coord.geometry !== null &&\n coord.geometry.type === \"Point\") {\n return coord.geometry.coordinates;\n }\n if (coord.type === \"Point\") {\n return coord.coordinates;\n }\n }\n if (Array.isArray(coord) &&\n coord.length >= 2 &&\n !Array.isArray(coord[0]) &&\n !Array.isArray(coord[1])) {\n return coord;\n }\n throw new Error(\"coord must be GeoJSON Point or an Array of numbers\");\n}\n/**\n * Unwrap coordinates from a Feature, Geometry Object or an Array\n *\n * @name getCoords\n * @param {Array|Geometry|Feature} coords Feature, Geometry Object or an Array\n * @returns {Array} coordinates\n * @example\n * var poly = turf.polygon([[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]);\n *\n * var coords = turf.getCoords(poly);\n * //= [[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]\n */\nexport function getCoords(coords) {\n if (Array.isArray(coords)) {\n return coords;\n }\n // Feature\n if (coords.type === \"Feature\") {\n if (coords.geometry !== null) {\n return coords.geometry.coordinates;\n }\n }\n else {\n // Geometry\n if (coords.coordinates) {\n return coords.coordinates;\n }\n }\n throw new Error(\"coords must be GeoJSON Feature, Geometry Object or an Array\");\n}\n/**\n * Checks if coordinates contains a number\n *\n * @name containsNumber\n * @param {Array} coordinates GeoJSON Coordinates\n * @returns {boolean} true if Array contains a number\n */\nexport function containsNumber(coordinates) {\n if (coordinates.length > 1 &&\n isNumber(coordinates[0]) &&\n isNumber(coordinates[1])) {\n return true;\n }\n if (Array.isArray(coordinates[0]) && coordinates[0].length) {\n return containsNumber(coordinates[0]);\n }\n throw new Error(\"coordinates must only contain numbers\");\n}\n/**\n * Enforce expectations about types of GeoJSON objects for Turf.\n *\n * @name geojsonType\n * @param {GeoJSON} value any GeoJSON object\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} if value is not the expected type.\n */\nexport function geojsonType(value, type, name) {\n if (!type || !name) {\n throw new Error(\"type and name required\");\n }\n if (!value || value.type !== type) {\n throw new Error(\"Invalid input to \" +\n name +\n \": must be a \" +\n type +\n \", given \" +\n value.type);\n }\n}\n/**\n * Enforce expectations about types of {@link Feature} inputs for Turf.\n * Internally this uses {@link geojsonType} to judge geometry types.\n *\n * @name featureOf\n * @param {Feature} feature a feature with an expected geometry type\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} error if value is not the expected type.\n */\nexport function featureOf(feature, type, name) {\n if (!feature) {\n throw new Error(\"No feature passed\");\n }\n if (!name) {\n throw new Error(\".featureOf() requires a name\");\n }\n if (!feature || feature.type !== \"Feature\" || !feature.geometry) {\n throw new Error(\"Invalid input to \" + name + \", Feature with geometry required\");\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error(\"Invalid input to \" +\n name +\n \": must be a \" +\n type +\n \", given \" +\n feature.geometry.type);\n }\n}\n/**\n * Enforce expectations about types of {@link FeatureCollection} inputs for Turf.\n * Internally this uses {@link geojsonType} to judge geometry types.\n *\n * @name collectionOf\n * @param {FeatureCollection} featureCollection a FeatureCollection for which features will be judged\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} if value is not the expected type.\n */\nexport function collectionOf(featureCollection, type, name) {\n if (!featureCollection) {\n throw new Error(\"No featureCollection passed\");\n }\n if (!name) {\n throw new Error(\".collectionOf() requires a name\");\n }\n if (!featureCollection || featureCollection.type !== \"FeatureCollection\") {\n throw new Error(\"Invalid input to \" + name + \", FeatureCollection required\");\n }\n for (var _i = 0, _a = featureCollection.features; _i < _a.length; _i++) {\n var feature = _a[_i];\n if (!feature || feature.type !== \"Feature\" || !feature.geometry) {\n throw new Error(\"Invalid input to \" + name + \", Feature with geometry required\");\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error(\"Invalid input to \" +\n name +\n \": must be a \" +\n type +\n \", given \" +\n feature.geometry.type);\n }\n }\n}\n/**\n * Get Geometry from Feature or Geometry Object\n *\n * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object\n * @returns {Geometry|null} GeoJSON Geometry Object\n * @throws {Error} if geojson is not a Feature or Geometry Object\n * @example\n * var point = {\n * \"type\": \"Feature\",\n * \"properties\": {},\n * \"geometry\": {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 40]\n * }\n * }\n * var geom = turf.getGeom(point)\n * //={\"type\": \"Point\", \"coordinates\": [110, 40]}\n */\nexport function getGeom(geojson) {\n if (geojson.type === \"Feature\") {\n return geojson.geometry;\n }\n return geojson;\n}\n/**\n * Get GeoJSON object's type, Geometry type is prioritize.\n *\n * @param {GeoJSON} geojson GeoJSON object\n * @param {string} [name=\"geojson\"] name of the variable to display in error message (unused)\n * @returns {string} GeoJSON type\n * @example\n * var point = {\n * \"type\": \"Feature\",\n * \"properties\": {},\n * \"geometry\": {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 40]\n * }\n * }\n * var geom = turf.getType(point)\n * //=\"Point\"\n */\nexport function getType(geojson, _name) {\n if (geojson.type === \"FeatureCollection\") {\n return \"FeatureCollection\";\n }\n if (geojson.type === \"GeometryCollection\") {\n return \"GeometryCollection\";\n }\n if (geojson.type === \"Feature\" && geojson.geometry !== null) {\n return geojson.geometry.type;\n }\n return geojson.type;\n}\n","import { feature, lineString, isObject, point } from '@turf/helpers';\n\n/**\n * Callback for coordEach\n *\n * @callback coordEachCallback\n * @param {Array} currentCoord The current coordinate being processed.\n * @param {number} coordIndex The current index of the coordinate being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n * @param {number} geometryIndex The current index of the Geometry being processed.\n */\n\n/**\n * Iterate over coordinates in any GeoJSON object, similar to Array.forEach()\n *\n * @name coordEach\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (currentCoord, coordIndex, featureIndex, multiFeatureIndex)\n * @param {boolean} [excludeWrapCoord=false] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration.\n * @returns {void}\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {\"foo\": \"bar\"}),\n * turf.point([36, 53], {\"hello\": \"world\"})\n * ]);\n *\n * turf.coordEach(features, function (currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {\n * //=currentCoord\n * //=coordIndex\n * //=featureIndex\n * //=multiFeatureIndex\n * //=geometryIndex\n * });\n */\nfunction coordEach(geojson, callback, excludeWrapCoord) {\n // Handles null Geometry -- Skips this GeoJSON\n if (geojson === null) return;\n var j,\n k,\n l,\n geometry,\n stopG,\n coords,\n geometryMaybeCollection,\n wrapShrink = 0,\n coordIndex = 0,\n isGeometryCollection,\n type = geojson.type,\n isFeatureCollection = type === \"FeatureCollection\",\n isFeature = type === \"Feature\",\n stop = isFeatureCollection ? geojson.features.length : 1;\n\n // This logic may look a little weird. The reason why it is that way\n // is because it's trying to be fast. GeoJSON supports multiple kinds\n // of objects at its root: FeatureCollection, Features, Geometries.\n // This function has the responsibility of handling all of them, and that\n // means that some of the `for` loops you see below actually just don't apply\n // to certain inputs. For instance, if you give this just a\n // Point geometry, then both loops are short-circuited and all we do\n // is gradually rename the input until it's called 'geometry'.\n //\n // This also aims to allocate as few resources as possible: just a\n // few numbers and booleans, rather than any temporary arrays as would\n // be required with the normalization approach.\n for (var featureIndex = 0; featureIndex < stop; featureIndex++) {\n geometryMaybeCollection = isFeatureCollection\n ? geojson.features[featureIndex].geometry\n : isFeature\n ? geojson.geometry\n : geojson;\n isGeometryCollection = geometryMaybeCollection\n ? geometryMaybeCollection.type === \"GeometryCollection\"\n : false;\n stopG = isGeometryCollection\n ? geometryMaybeCollection.geometries.length\n : 1;\n\n for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {\n var multiFeatureIndex = 0;\n var geometryIndex = 0;\n geometry = isGeometryCollection\n ? geometryMaybeCollection.geometries[geomIndex]\n : geometryMaybeCollection;\n\n // Handles null Geometry -- Skips this geometry\n if (geometry === null) continue;\n coords = geometry.coordinates;\n var geomType = geometry.type;\n\n wrapShrink =\n excludeWrapCoord &&\n (geomType === \"Polygon\" || geomType === \"MultiPolygon\")\n ? 1\n : 0;\n\n switch (geomType) {\n case null:\n break;\n case \"Point\":\n if (\n callback(\n coords,\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n multiFeatureIndex++;\n break;\n case \"LineString\":\n case \"MultiPoint\":\n for (j = 0; j < coords.length; j++) {\n if (\n callback(\n coords[j],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n if (geomType === \"MultiPoint\") multiFeatureIndex++;\n }\n if (geomType === \"LineString\") multiFeatureIndex++;\n break;\n case \"Polygon\":\n case \"MultiLineString\":\n for (j = 0; j < coords.length; j++) {\n for (k = 0; k < coords[j].length - wrapShrink; k++) {\n if (\n callback(\n coords[j][k],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n }\n if (geomType === \"MultiLineString\") multiFeatureIndex++;\n if (geomType === \"Polygon\") geometryIndex++;\n }\n if (geomType === \"Polygon\") multiFeatureIndex++;\n break;\n case \"MultiPolygon\":\n for (j = 0; j < coords.length; j++) {\n geometryIndex = 0;\n for (k = 0; k < coords[j].length; k++) {\n for (l = 0; l < coords[j][k].length - wrapShrink; l++) {\n if (\n callback(\n coords[j][k][l],\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n coordIndex++;\n }\n geometryIndex++;\n }\n multiFeatureIndex++;\n }\n break;\n case \"GeometryCollection\":\n for (j = 0; j < geometry.geometries.length; j++)\n if (\n coordEach(geometry.geometries[j], callback, excludeWrapCoord) ===\n false\n )\n return false;\n break;\n default:\n throw new Error(\"Unknown Geometry Type\");\n }\n }\n }\n}\n\n/**\n * Callback for coordReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback coordReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Array} currentCoord The current coordinate being processed.\n * @param {number} coordIndex The current index of the coordinate being processed.\n * Starts at index 0, if an initialValue is provided, and at index 1 otherwise.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n * @param {number} geometryIndex The current index of the Geometry being processed.\n */\n\n/**\n * Reduce coordinates in any GeoJSON object, similar to Array.reduce()\n *\n * @name coordReduce\n * @param {FeatureCollection|Geometry|Feature} geojson any GeoJSON object\n * @param {Function} callback a method that takes (previousValue, currentCoord, coordIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @param {boolean} [excludeWrapCoord=false] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration.\n * @returns {*} The value that results from the reduction.\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {\"foo\": \"bar\"}),\n * turf.point([36, 53], {\"hello\": \"world\"})\n * ]);\n *\n * turf.coordReduce(features, function (previousValue, currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {\n * //=previousValue\n * //=currentCoord\n * //=coordIndex\n * //=featureIndex\n * //=multiFeatureIndex\n * //=geometryIndex\n * return currentCoord;\n * });\n */\nfunction coordReduce(geojson, callback, initialValue, excludeWrapCoord) {\n var previousValue = initialValue;\n coordEach(\n geojson,\n function (\n currentCoord,\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) {\n if (coordIndex === 0 && initialValue === undefined)\n previousValue = currentCoord;\n else\n previousValue = callback(\n previousValue,\n currentCoord,\n coordIndex,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n );\n },\n excludeWrapCoord\n );\n return previousValue;\n}\n\n/**\n * Callback for propEach\n *\n * @callback propEachCallback\n * @param {Object} currentProperties The current Properties being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n */\n\n/**\n * Iterate over properties in any GeoJSON object, similar to Array.forEach()\n *\n * @name propEach\n * @param {FeatureCollection|Feature} geojson any GeoJSON object\n * @param {Function} callback a method that takes (currentProperties, featureIndex)\n * @returns {void}\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * turf.propEach(features, function (currentProperties, featureIndex) {\n * //=currentProperties\n * //=featureIndex\n * });\n */\nfunction propEach(geojson, callback) {\n var i;\n switch (geojson.type) {\n case \"FeatureCollection\":\n for (i = 0; i < geojson.features.length; i++) {\n if (callback(geojson.features[i].properties, i) === false) break;\n }\n break;\n case \"Feature\":\n callback(geojson.properties, 0);\n break;\n }\n}\n\n/**\n * Callback for propReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback propReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {*} currentProperties The current Properties being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n */\n\n/**\n * Reduce properties in any GeoJSON object into a single value,\n * similar to how Array.reduce works. However, in this case we lazily run\n * the reduction, so an array of all properties is unnecessary.\n *\n * @name propReduce\n * @param {FeatureCollection|Feature} geojson any GeoJSON object\n * @param {Function} callback a method that takes (previousValue, currentProperties, featureIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * turf.propReduce(features, function (previousValue, currentProperties, featureIndex) {\n * //=previousValue\n * //=currentProperties\n * //=featureIndex\n * return currentProperties\n * });\n */\nfunction propReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n propEach(geojson, function (currentProperties, featureIndex) {\n if (featureIndex === 0 && initialValue === undefined)\n previousValue = currentProperties;\n else\n previousValue = callback(previousValue, currentProperties, featureIndex);\n });\n return previousValue;\n}\n\n/**\n * Callback for featureEach\n *\n * @callback featureEachCallback\n * @param {Feature} currentFeature The current Feature being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n */\n\n/**\n * Iterate over features in any GeoJSON object, similar to\n * Array.forEach.\n *\n * @name featureEach\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (currentFeature, featureIndex)\n * @returns {void}\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * turf.featureEach(features, function (currentFeature, featureIndex) {\n * //=currentFeature\n * //=featureIndex\n * });\n */\nfunction featureEach(geojson, callback) {\n if (geojson.type === \"Feature\") {\n callback(geojson, 0);\n } else if (geojson.type === \"FeatureCollection\") {\n for (var i = 0; i < geojson.features.length; i++) {\n if (callback(geojson.features[i], i) === false) break;\n }\n }\n}\n\n/**\n * Callback for featureReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback featureReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Feature} currentFeature The current Feature being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n */\n\n/**\n * Reduce features in any GeoJSON object, similar to Array.reduce().\n *\n * @name featureReduce\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (previousValue, currentFeature, featureIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {\"foo\": \"bar\"}),\n * turf.point([36, 53], {\"hello\": \"world\"})\n * ]);\n *\n * turf.featureReduce(features, function (previousValue, currentFeature, featureIndex) {\n * //=previousValue\n * //=currentFeature\n * //=featureIndex\n * return currentFeature\n * });\n */\nfunction featureReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n featureEach(geojson, function (currentFeature, featureIndex) {\n if (featureIndex === 0 && initialValue === undefined)\n previousValue = currentFeature;\n else previousValue = callback(previousValue, currentFeature, featureIndex);\n });\n return previousValue;\n}\n\n/**\n * Get all coordinates from any GeoJSON object.\n *\n * @name coordAll\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @returns {Array>} coordinate position array\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * var coords = turf.coordAll(features);\n * //= [[26, 37], [36, 53]]\n */\nfunction coordAll(geojson) {\n var coords = [];\n coordEach(geojson, function (coord) {\n coords.push(coord);\n });\n return coords;\n}\n\n/**\n * Callback for geomEach\n *\n * @callback geomEachCallback\n * @param {Geometry} currentGeometry The current Geometry being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {Object} featureProperties The current Feature Properties being processed.\n * @param {Array} featureBBox The current Feature BBox being processed.\n * @param {number|string} featureId The current Feature Id being processed.\n */\n\n/**\n * Iterate over each geometry in any GeoJSON object, similar to Array.forEach()\n *\n * @name geomEach\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (currentGeometry, featureIndex, featureProperties, featureBBox, featureId)\n * @returns {void}\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * turf.geomEach(features, function (currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {\n * //=currentGeometry\n * //=featureIndex\n * //=featureProperties\n * //=featureBBox\n * //=featureId\n * });\n */\nfunction geomEach(geojson, callback) {\n var i,\n j,\n g,\n geometry,\n stopG,\n geometryMaybeCollection,\n isGeometryCollection,\n featureProperties,\n featureBBox,\n featureId,\n featureIndex = 0,\n isFeatureCollection = geojson.type === \"FeatureCollection\",\n isFeature = geojson.type === \"Feature\",\n stop = isFeatureCollection ? geojson.features.length : 1;\n\n // This logic may look a little weird. The reason why it is that way\n // is because it's trying to be fast. GeoJSON supports multiple kinds\n // of objects at its root: FeatureCollection, Features, Geometries.\n // This function has the responsibility of handling all of them, and that\n // means that some of the `for` loops you see below actually just don't apply\n // to certain inputs. For instance, if you give this just a\n // Point geometry, then both loops are short-circuited and all we do\n // is gradually rename the input until it's called 'geometry'.\n //\n // This also aims to allocate as few resources as possible: just a\n // few numbers and booleans, rather than any temporary arrays as would\n // be required with the normalization approach.\n for (i = 0; i < stop; i++) {\n geometryMaybeCollection = isFeatureCollection\n ? geojson.features[i].geometry\n : isFeature\n ? geojson.geometry\n : geojson;\n featureProperties = isFeatureCollection\n ? geojson.features[i].properties\n : isFeature\n ? geojson.properties\n : {};\n featureBBox = isFeatureCollection\n ? geojson.features[i].bbox\n : isFeature\n ? geojson.bbox\n : undefined;\n featureId = isFeatureCollection\n ? geojson.features[i].id\n : isFeature\n ? geojson.id\n : undefined;\n isGeometryCollection = geometryMaybeCollection\n ? geometryMaybeCollection.type === \"GeometryCollection\"\n : false;\n stopG = isGeometryCollection\n ? geometryMaybeCollection.geometries.length\n : 1;\n\n for (g = 0; g < stopG; g++) {\n geometry = isGeometryCollection\n ? geometryMaybeCollection.geometries[g]\n : geometryMaybeCollection;\n\n // Handle null Geometry\n if (geometry === null) {\n if (\n callback(\n null,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n continue;\n }\n switch (geometry.type) {\n case \"Point\":\n case \"LineString\":\n case \"MultiPoint\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\": {\n if (\n callback(\n geometry,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n break;\n }\n case \"GeometryCollection\": {\n for (j = 0; j < geometry.geometries.length; j++) {\n if (\n callback(\n geometry.geometries[j],\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) === false\n )\n return false;\n }\n break;\n }\n default:\n throw new Error(\"Unknown Geometry Type\");\n }\n }\n // Only increase `featureIndex` per each feature\n featureIndex++;\n }\n}\n\n/**\n * Callback for geomReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback geomReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Geometry} currentGeometry The current Geometry being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {Object} featureProperties The current Feature Properties being processed.\n * @param {Array} featureBBox The current Feature BBox being processed.\n * @param {number|string} featureId The current Feature Id being processed.\n */\n\n/**\n * Reduce geometry in any GeoJSON object, similar to Array.reduce().\n *\n * @name geomReduce\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.point([36, 53], {hello: 'world'})\n * ]);\n *\n * turf.geomReduce(features, function (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {\n * //=previousValue\n * //=currentGeometry\n * //=featureIndex\n * //=featureProperties\n * //=featureBBox\n * //=featureId\n * return currentGeometry\n * });\n */\nfunction geomReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n geomEach(\n geojson,\n function (\n currentGeometry,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n ) {\n if (featureIndex === 0 && initialValue === undefined)\n previousValue = currentGeometry;\n else\n previousValue = callback(\n previousValue,\n currentGeometry,\n featureIndex,\n featureProperties,\n featureBBox,\n featureId\n );\n }\n );\n return previousValue;\n}\n\n/**\n * Callback for flattenEach\n *\n * @callback flattenEachCallback\n * @param {Feature} currentFeature The current flattened feature being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n */\n\n/**\n * Iterate over flattened features in any GeoJSON object, similar to\n * Array.forEach.\n *\n * @name flattenEach\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (currentFeature, featureIndex, multiFeatureIndex)\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.multiPoint([[40, 30], [36, 53]], {hello: 'world'})\n * ]);\n *\n * turf.flattenEach(features, function (currentFeature, featureIndex, multiFeatureIndex) {\n * //=currentFeature\n * //=featureIndex\n * //=multiFeatureIndex\n * });\n */\nfunction flattenEach(geojson, callback) {\n geomEach(geojson, function (geometry, featureIndex, properties, bbox, id) {\n // Callback for single geometry\n var type = geometry === null ? null : geometry.type;\n switch (type) {\n case null:\n case \"Point\":\n case \"LineString\":\n case \"Polygon\":\n if (\n callback(\n feature(geometry, properties, { bbox: bbox, id: id }),\n featureIndex,\n 0\n ) === false\n )\n return false;\n return;\n }\n\n var geomType;\n\n // Callback for multi-geometry\n switch (type) {\n case \"MultiPoint\":\n geomType = \"Point\";\n break;\n case \"MultiLineString\":\n geomType = \"LineString\";\n break;\n case \"MultiPolygon\":\n geomType = \"Polygon\";\n break;\n }\n\n for (\n var multiFeatureIndex = 0;\n multiFeatureIndex < geometry.coordinates.length;\n multiFeatureIndex++\n ) {\n var coordinate = geometry.coordinates[multiFeatureIndex];\n var geom = {\n type: geomType,\n coordinates: coordinate,\n };\n if (\n callback(feature(geom, properties), featureIndex, multiFeatureIndex) ===\n false\n )\n return false;\n }\n });\n}\n\n/**\n * Callback for flattenReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback flattenReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Feature} currentFeature The current Feature being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n */\n\n/**\n * Reduce flattened features in any GeoJSON object, similar to Array.reduce().\n *\n * @name flattenReduce\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object\n * @param {Function} callback a method that takes (previousValue, currentFeature, featureIndex, multiFeatureIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var features = turf.featureCollection([\n * turf.point([26, 37], {foo: 'bar'}),\n * turf.multiPoint([[40, 30], [36, 53]], {hello: 'world'})\n * ]);\n *\n * turf.flattenReduce(features, function (previousValue, currentFeature, featureIndex, multiFeatureIndex) {\n * //=previousValue\n * //=currentFeature\n * //=featureIndex\n * //=multiFeatureIndex\n * return currentFeature\n * });\n */\nfunction flattenReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n flattenEach(\n geojson,\n function (currentFeature, featureIndex, multiFeatureIndex) {\n if (\n featureIndex === 0 &&\n multiFeatureIndex === 0 &&\n initialValue === undefined\n )\n previousValue = currentFeature;\n else\n previousValue = callback(\n previousValue,\n currentFeature,\n featureIndex,\n multiFeatureIndex\n );\n }\n );\n return previousValue;\n}\n\n/**\n * Callback for segmentEach\n *\n * @callback segmentEachCallback\n * @param {Feature} currentSegment The current Segment being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n * @param {number} geometryIndex The current index of the Geometry being processed.\n * @param {number} segmentIndex The current index of the Segment being processed.\n * @returns {void}\n */\n\n/**\n * Iterate over 2-vertex line segment in any GeoJSON object, similar to Array.forEach()\n * (Multi)Point geometries do not contain segments therefore they are ignored during this operation.\n *\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON\n * @param {Function} callback a method that takes (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex)\n * @returns {void}\n * @example\n * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]);\n *\n * // Iterate over GeoJSON by 2-vertex segments\n * turf.segmentEach(polygon, function (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {\n * //=currentSegment\n * //=featureIndex\n * //=multiFeatureIndex\n * //=geometryIndex\n * //=segmentIndex\n * });\n *\n * // Calculate the total number of segments\n * var total = 0;\n * turf.segmentEach(polygon, function () {\n * total++;\n * });\n */\nfunction segmentEach(geojson, callback) {\n flattenEach(geojson, function (feature, featureIndex, multiFeatureIndex) {\n var segmentIndex = 0;\n\n // Exclude null Geometries\n if (!feature.geometry) return;\n // (Multi)Point geometries do not contain segments therefore they are ignored during this operation.\n var type = feature.geometry.type;\n if (type === \"Point\" || type === \"MultiPoint\") return;\n\n // Generate 2-vertex line segments\n var previousCoords;\n var previousFeatureIndex = 0;\n var previousMultiIndex = 0;\n var prevGeomIndex = 0;\n if (\n coordEach(\n feature,\n function (\n currentCoord,\n coordIndex,\n featureIndexCoord,\n multiPartIndexCoord,\n geometryIndex\n ) {\n // Simulating a meta.coordReduce() since `reduce` operations cannot be stopped by returning `false`\n if (\n previousCoords === undefined ||\n featureIndex > previousFeatureIndex ||\n multiPartIndexCoord > previousMultiIndex ||\n geometryIndex > prevGeomIndex\n ) {\n previousCoords = currentCoord;\n previousFeatureIndex = featureIndex;\n previousMultiIndex = multiPartIndexCoord;\n prevGeomIndex = geometryIndex;\n segmentIndex = 0;\n return;\n }\n var currentSegment = lineString(\n [previousCoords, currentCoord],\n feature.properties\n );\n if (\n callback(\n currentSegment,\n featureIndex,\n multiFeatureIndex,\n geometryIndex,\n segmentIndex\n ) === false\n )\n return false;\n segmentIndex++;\n previousCoords = currentCoord;\n }\n ) === false\n )\n return false;\n });\n}\n\n/**\n * Callback for segmentReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback segmentReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Feature} currentSegment The current Segment being processed.\n * @param {number} featureIndex The current index of the Feature being processed.\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.\n * @param {number} geometryIndex The current index of the Geometry being processed.\n * @param {number} segmentIndex The current index of the Segment being processed.\n */\n\n/**\n * Reduce 2-vertex line segment in any GeoJSON object, similar to Array.reduce()\n * (Multi)Point geometries do not contain segments therefore they are ignored during this operation.\n *\n * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON\n * @param {Function} callback a method that takes (previousValue, currentSegment, currentIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {void}\n * @example\n * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]);\n *\n * // Iterate over GeoJSON by 2-vertex segments\n * turf.segmentReduce(polygon, function (previousSegment, currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {\n * //= previousSegment\n * //= currentSegment\n * //= featureIndex\n * //= multiFeatureIndex\n * //= geometryIndex\n * //= segmentIndex\n * return currentSegment\n * });\n *\n * // Calculate the total number of segments\n * var initialValue = 0\n * var total = turf.segmentReduce(polygon, function (previousValue) {\n * previousValue++;\n * return previousValue;\n * }, initialValue);\n */\nfunction segmentReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n var started = false;\n segmentEach(\n geojson,\n function (\n currentSegment,\n featureIndex,\n multiFeatureIndex,\n geometryIndex,\n segmentIndex\n ) {\n if (started === false && initialValue === undefined)\n previousValue = currentSegment;\n else\n previousValue = callback(\n previousValue,\n currentSegment,\n featureIndex,\n multiFeatureIndex,\n geometryIndex,\n segmentIndex\n );\n started = true;\n }\n );\n return previousValue;\n}\n\n/**\n * Callback for lineEach\n *\n * @callback lineEachCallback\n * @param {Feature} currentLine The current LineString|LinearRing being processed\n * @param {number} featureIndex The current index of the Feature being processed\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed\n * @param {number} geometryIndex The current index of the Geometry being processed\n */\n\n/**\n * Iterate over line or ring coordinates in LineString, Polygon, MultiLineString, MultiPolygon Features or Geometries,\n * similar to Array.forEach.\n *\n * @name lineEach\n * @param {Geometry|Feature} geojson object\n * @param {Function} callback a method that takes (currentLine, featureIndex, multiFeatureIndex, geometryIndex)\n * @example\n * var multiLine = turf.multiLineString([\n * [[26, 37], [35, 45]],\n * [[36, 53], [38, 50], [41, 55]]\n * ]);\n *\n * turf.lineEach(multiLine, function (currentLine, featureIndex, multiFeatureIndex, geometryIndex) {\n * //=currentLine\n * //=featureIndex\n * //=multiFeatureIndex\n * //=geometryIndex\n * });\n */\nfunction lineEach(geojson, callback) {\n // validation\n if (!geojson) throw new Error(\"geojson is required\");\n\n flattenEach(geojson, function (feature, featureIndex, multiFeatureIndex) {\n if (feature.geometry === null) return;\n var type = feature.geometry.type;\n var coords = feature.geometry.coordinates;\n switch (type) {\n case \"LineString\":\n if (callback(feature, featureIndex, multiFeatureIndex, 0, 0) === false)\n return false;\n break;\n case \"Polygon\":\n for (\n var geometryIndex = 0;\n geometryIndex < coords.length;\n geometryIndex++\n ) {\n if (\n callback(\n lineString(coords[geometryIndex], feature.properties),\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n ) === false\n )\n return false;\n }\n break;\n }\n });\n}\n\n/**\n * Callback for lineReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback lineReduceCallback\n * @param {*} previousValue The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {Feature} currentLine The current LineString|LinearRing being processed.\n * @param {number} featureIndex The current index of the Feature being processed\n * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed\n * @param {number} geometryIndex The current index of the Geometry being processed\n */\n\n/**\n * Reduce features in any GeoJSON object, similar to Array.reduce().\n *\n * @name lineReduce\n * @param {Geometry|Feature} geojson object\n * @param {Function} callback a method that takes (previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var multiPoly = turf.multiPolygon([\n * turf.polygon([[[12,48],[2,41],[24,38],[12,48]], [[9,44],[13,41],[13,45],[9,44]]]),\n * turf.polygon([[[5, 5], [0, 0], [2, 2], [4, 4], [5, 5]]])\n * ]);\n *\n * turf.lineReduce(multiPoly, function (previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex) {\n * //=previousValue\n * //=currentLine\n * //=featureIndex\n * //=multiFeatureIndex\n * //=geometryIndex\n * return currentLine\n * });\n */\nfunction lineReduce(geojson, callback, initialValue) {\n var previousValue = initialValue;\n lineEach(\n geojson,\n function (currentLine, featureIndex, multiFeatureIndex, geometryIndex) {\n if (featureIndex === 0 && initialValue === undefined)\n previousValue = currentLine;\n else\n previousValue = callback(\n previousValue,\n currentLine,\n featureIndex,\n multiFeatureIndex,\n geometryIndex\n );\n }\n );\n return previousValue;\n}\n\n/**\n * Finds a particular 2-vertex LineString Segment from a GeoJSON using `@turf/meta` indexes.\n *\n * Negative indexes are permitted.\n * Point & MultiPoint will always return null.\n *\n * @param {FeatureCollection|Feature|Geometry} geojson Any GeoJSON Feature or Geometry\n * @param {Object} [options={}] Optional parameters\n * @param {number} [options.featureIndex=0] Feature Index\n * @param {number} [options.multiFeatureIndex=0] Multi-Feature Index\n * @param {number} [options.geometryIndex=0] Geometry Index\n * @param {number} [options.segmentIndex=0] Segment Index\n * @param {Object} [options.properties={}] Translate Properties to output LineString\n * @param {BBox} [options.bbox={}] Translate BBox to output LineString\n * @param {number|string} [options.id={}] Translate Id to output LineString\n * @returns {Feature} 2-vertex GeoJSON Feature LineString\n * @example\n * var multiLine = turf.multiLineString([\n * [[10, 10], [50, 30], [30, 40]],\n * [[-10, -10], [-50, -30], [-30, -40]]\n * ]);\n *\n * // First Segment (defaults are 0)\n * turf.findSegment(multiLine);\n * // => Feature>\n *\n * // First Segment of 2nd Multi Feature\n * turf.findSegment(multiLine, {multiFeatureIndex: 1});\n * // => Feature>\n *\n * // Last Segment of Last Multi Feature\n * turf.findSegment(multiLine, {multiFeatureIndex: -1, segmentIndex: -1});\n * // => Feature>\n */\nfunction findSegment(geojson, options) {\n // Optional Parameters\n options = options || {};\n if (!isObject(options)) throw new Error(\"options is invalid\");\n var featureIndex = options.featureIndex || 0;\n var multiFeatureIndex = options.multiFeatureIndex || 0;\n var geometryIndex = options.geometryIndex || 0;\n var segmentIndex = options.segmentIndex || 0;\n\n // Find FeatureIndex\n var properties = options.properties;\n var geometry;\n\n switch (geojson.type) {\n case \"FeatureCollection\":\n if (featureIndex < 0)\n featureIndex = geojson.features.length + featureIndex;\n properties = properties || geojson.features[featureIndex].properties;\n geometry = geojson.features[featureIndex].geometry;\n break;\n case \"Feature\":\n properties = properties || geojson.properties;\n geometry = geojson.geometry;\n break;\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\":\n geometry = geojson;\n break;\n default:\n throw new Error(\"geojson is invalid\");\n }\n\n // Find SegmentIndex\n if (geometry === null) return null;\n var coords = geometry.coordinates;\n switch (geometry.type) {\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n if (segmentIndex < 0) segmentIndex = coords.length + segmentIndex - 1;\n return lineString(\n [coords[segmentIndex], coords[segmentIndex + 1]],\n properties,\n options\n );\n case \"Polygon\":\n if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex;\n if (segmentIndex < 0)\n segmentIndex = coords[geometryIndex].length + segmentIndex - 1;\n return lineString(\n [\n coords[geometryIndex][segmentIndex],\n coords[geometryIndex][segmentIndex + 1],\n ],\n properties,\n options\n );\n case \"MultiLineString\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (segmentIndex < 0)\n segmentIndex = coords[multiFeatureIndex].length + segmentIndex - 1;\n return lineString(\n [\n coords[multiFeatureIndex][segmentIndex],\n coords[multiFeatureIndex][segmentIndex + 1],\n ],\n properties,\n options\n );\n case \"MultiPolygon\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (geometryIndex < 0)\n geometryIndex = coords[multiFeatureIndex].length + geometryIndex;\n if (segmentIndex < 0)\n segmentIndex =\n coords[multiFeatureIndex][geometryIndex].length - segmentIndex - 1;\n return lineString(\n [\n coords[multiFeatureIndex][geometryIndex][segmentIndex],\n coords[multiFeatureIndex][geometryIndex][segmentIndex + 1],\n ],\n properties,\n options\n );\n }\n throw new Error(\"geojson is invalid\");\n}\n\n/**\n * Finds a particular Point from a GeoJSON using `@turf/meta` indexes.\n *\n * Negative indexes are permitted.\n *\n * @param {FeatureCollection|Feature|Geometry} geojson Any GeoJSON Feature or Geometry\n * @param {Object} [options={}] Optional parameters\n * @param {number} [options.featureIndex=0] Feature Index\n * @param {number} [options.multiFeatureIndex=0] Multi-Feature Index\n * @param {number} [options.geometryIndex=0] Geometry Index\n * @param {number} [options.coordIndex=0] Coord Index\n * @param {Object} [options.properties={}] Translate Properties to output Point\n * @param {BBox} [options.bbox={}] Translate BBox to output Point\n * @param {number|string} [options.id={}] Translate Id to output Point\n * @returns {Feature} 2-vertex GeoJSON Feature Point\n * @example\n * var multiLine = turf.multiLineString([\n * [[10, 10], [50, 30], [30, 40]],\n * [[-10, -10], [-50, -30], [-30, -40]]\n * ]);\n *\n * // First Segment (defaults are 0)\n * turf.findPoint(multiLine);\n * // => Feature>\n *\n * // First Segment of the 2nd Multi-Feature\n * turf.findPoint(multiLine, {multiFeatureIndex: 1});\n * // => Feature>\n *\n * // Last Segment of last Multi-Feature\n * turf.findPoint(multiLine, {multiFeatureIndex: -1, coordIndex: -1});\n * // => Feature>\n */\nfunction findPoint(geojson, options) {\n // Optional Parameters\n options = options || {};\n if (!isObject(options)) throw new Error(\"options is invalid\");\n var featureIndex = options.featureIndex || 0;\n var multiFeatureIndex = options.multiFeatureIndex || 0;\n var geometryIndex = options.geometryIndex || 0;\n var coordIndex = options.coordIndex || 0;\n\n // Find FeatureIndex\n var properties = options.properties;\n var geometry;\n\n switch (geojson.type) {\n case \"FeatureCollection\":\n if (featureIndex < 0)\n featureIndex = geojson.features.length + featureIndex;\n properties = properties || geojson.features[featureIndex].properties;\n geometry = geojson.features[featureIndex].geometry;\n break;\n case \"Feature\":\n properties = properties || geojson.properties;\n geometry = geojson.geometry;\n break;\n case \"Point\":\n case \"MultiPoint\":\n return null;\n case \"LineString\":\n case \"Polygon\":\n case \"MultiLineString\":\n case \"MultiPolygon\":\n geometry = geojson;\n break;\n default:\n throw new Error(\"geojson is invalid\");\n }\n\n // Find Coord Index\n if (geometry === null) return null;\n var coords = geometry.coordinates;\n switch (geometry.type) {\n case \"Point\":\n return point(coords, properties, options);\n case \"MultiPoint\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n return point(coords[multiFeatureIndex], properties, options);\n case \"LineString\":\n if (coordIndex < 0) coordIndex = coords.length + coordIndex;\n return point(coords[coordIndex], properties, options);\n case \"Polygon\":\n if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex;\n if (coordIndex < 0)\n coordIndex = coords[geometryIndex].length + coordIndex;\n return point(coords[geometryIndex][coordIndex], properties, options);\n case \"MultiLineString\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (coordIndex < 0)\n coordIndex = coords[multiFeatureIndex].length + coordIndex;\n return point(coords[multiFeatureIndex][coordIndex], properties, options);\n case \"MultiPolygon\":\n if (multiFeatureIndex < 0)\n multiFeatureIndex = coords.length + multiFeatureIndex;\n if (geometryIndex < 0)\n geometryIndex = coords[multiFeatureIndex].length + geometryIndex;\n if (coordIndex < 0)\n coordIndex =\n coords[multiFeatureIndex][geometryIndex].length - coordIndex;\n return point(\n coords[multiFeatureIndex][geometryIndex][coordIndex],\n properties,\n options\n );\n }\n throw new Error(\"geojson is invalid\");\n}\n\nexport { coordAll, coordEach, coordReduce, featureEach, featureReduce, findPoint, findSegment, flattenEach, flattenReduce, geomEach, geomReduce, lineEach, lineReduce, propEach, propReduce, segmentEach, segmentReduce };\n","import kinks from '@turf/kinks';\nimport Draw from './L.PM.Draw';\n\nimport { getTranslation } from '../helpers';\n\nDraw.Line = Draw.extend({\n initialize(map) {\n this._map = map;\n this._shape = 'Line';\n this.toolbarButtonName = 'drawPolyline';\n this._doesSelfIntersect = false;\n },\n enable(options) {\n L.Util.setOptions(this, options);\n\n // enable draw mode\n this._enabled = true;\n\n this._markers = [];\n\n // create a new layergroup\n this._layerGroup = new L.FeatureGroup();\n this._layerGroup._pmTempLayer = true;\n this._layerGroup.addTo(this._map);\n\n // this is the polyLine that'll make up the polygon\n this._layer = L.polyline([], {\n ...this.options.templineStyle,\n pmIgnore: false,\n });\n this._setPane(this._layer, 'layerPane');\n this._layer._pmTempLayer = true;\n this._layerGroup.addLayer(this._layer);\n\n // this is the hintline from the mouse cursor to the last marker\n this._hintline = L.polyline([], this.options.hintlineStyle);\n this._setPane(this._hintline, 'layerPane');\n this._hintline._pmTempLayer = true;\n this._layerGroup.addLayer(this._hintline);\n\n // this is the hintmarker on the mouse cursor\n this._hintMarker = L.marker(this._map.getCenter(), {\n interactive: false, // always vertex marker below will be triggered from the click event -> _finishShape #911\n zIndexOffset: 100,\n icon: L.divIcon({ className: 'marker-icon cursor-marker' }),\n });\n this._setPane(this._hintMarker, 'vertexPane');\n this._hintMarker._pmTempLayer = true;\n this._layerGroup.addLayer(this._hintMarker);\n\n // show the hintmarker if the option is set\n if (this.options.cursorMarker) {\n L.DomUtil.addClass(this._hintMarker._icon, 'visible');\n }\n\n // add tooltip to hintmarker\n if (this.options.tooltips) {\n this._hintMarker\n .bindTooltip(getTranslation('tooltips.firstVertex'), {\n permanent: true,\n offset: L.point(0, 10),\n direction: 'bottom',\n\n opacity: 0.8,\n })\n .openTooltip();\n }\n\n // change map cursor\n this._map.getContainer().classList.add('geoman-draw-cursor');\n\n // create a polygon-point on click\n this._map.on('click', this._createVertex, this);\n\n // finish on layer event\n // #http://leafletjs.com/reference.html#interactive-layer-click\n if (this.options.finishOn && this.options.finishOn !== 'snap') {\n this._map.on(this.options.finishOn, this._finishShape, this);\n }\n\n // prevent zoom on double click if finishOn is === dblclick\n if (this.options.finishOn === 'dblclick') {\n this.tempMapDoubleClickZoomState = this._map.doubleClickZoom._enabled;\n\n if (this.tempMapDoubleClickZoomState) {\n this._map.doubleClickZoom.disable();\n }\n }\n\n // sync hint marker with mouse cursor\n this._map.on('mousemove', this._syncHintMarker, this);\n\n // sync the hintline with hint marker\n this._hintMarker.on('move', this._syncHintLine, this);\n\n // toggle the draw button of the Toolbar in case drawing mode got enabled without the button\n this._map.pm.Toolbar.toggleButton(this.toolbarButtonName, true);\n\n // an array used in the snapping mixin.\n // TODO: think about moving this somewhere else?\n this._otherSnapLayers = [];\n\n // make sure intersection is not set while start drawing\n this.isRed = false;\n\n // fire drawstart event\n this._fireDrawStart();\n this._setGlobalDrawMode();\n },\n disable() {\n // disable draw mode\n\n // cancel, if drawing mode isn't even enabled\n if (!this._enabled) {\n return;\n }\n\n this._enabled = false;\n\n // reset cursor\n this._map.getContainer().classList.remove('geoman-draw-cursor');\n\n // unbind listeners\n this._map.off('click', this._createVertex, this);\n this._map.off('mousemove', this._syncHintMarker, this);\n if (this.options.finishOn && this.options.finishOn !== 'snap') {\n this._map.off(this.options.finishOn, this._finishShape, this);\n }\n\n if (this.tempMapDoubleClickZoomState) {\n this._map.doubleClickZoom.enable();\n }\n\n // remove layer\n this._map.removeLayer(this._layerGroup);\n\n // toggle the draw button of the Toolbar in case drawing mode got disabled without the button\n this._map.pm.Toolbar.toggleButton(this.toolbarButtonName, false);\n\n // cleanup snapping\n if (this.options.snappable) {\n this._cleanupSnapping();\n }\n\n // fire drawend event\n this._fireDrawEnd();\n this._setGlobalDrawMode();\n },\n enabled() {\n return this._enabled;\n },\n toggle(options) {\n if (this.enabled()) {\n this.disable();\n } else {\n this.enable(options);\n }\n },\n _syncHintLine() {\n const polyPoints = this._layer.getLatLngs();\n\n if (polyPoints.length > 0) {\n const lastPolygonPoint = polyPoints[polyPoints.length - 1];\n\n // set coords for hintline from marker to last vertex of drawin polyline\n this._hintline.setLatLngs([\n lastPolygonPoint,\n this._hintMarker.getLatLng(),\n ]);\n }\n },\n _syncHintMarker(e) {\n // move the cursor marker\n this._hintMarker.setLatLng(e.latlng);\n\n // if snapping is enabled, do it\n if (this.options.snappable) {\n const fakeDragEvent = e;\n fakeDragEvent.target = this._hintMarker;\n this._handleSnapping(fakeDragEvent);\n }\n\n // if self-intersection is forbidden, handle it\n if (!this.options.allowSelfIntersection) {\n this._handleSelfIntersection(true, this._hintMarker.getLatLng());\n }\n const latlngs = this._layer._defaultShape().slice();\n latlngs.push(this._hintMarker.getLatLng());\n this._change(latlngs);\n },\n hasSelfIntersection() {\n // check for self intersection of the layer and return true/false\n const selfIntersection = kinks(this._layer.toGeoJSON(15));\n return selfIntersection.features.length > 0;\n },\n _handleSelfIntersection(addVertex, latlng) {\n // ok we need to check the self intersection here\n // problem: during draw, the marker on the cursor is not yet part\n // of the layer. So we need to clone the layer, add the\n // potential new vertex (cursor markers latlngs) and check the self\n // intersection on the clone. Phew... - let's do it 💪\n\n // clone layer (polyline is enough, even when it's a polygon)\n const clone = L.polyline(this._layer.getLatLngs());\n\n if (addVertex) {\n // get vertex from param or from hintmarker\n if (!latlng) {\n latlng = this._hintMarker.getLatLng();\n }\n\n // add the vertex\n clone.addLatLng(latlng);\n }\n\n // check the self intersection\n const selfIntersection = kinks(clone.toGeoJSON(15));\n this._doesSelfIntersect = selfIntersection.features.length > 0;\n\n // change the style based on self intersection\n if (this._doesSelfIntersect) {\n if (!this.isRed) {\n this.isRed = true;\n this._hintline.setStyle({\n color: '#f00000ff',\n });\n // fire intersect event\n this._fireIntersect(selfIntersection, this._map, 'Draw');\n }\n } else if (!this._hintline.isEmpty()) {\n this.isRed = false;\n this._hintline.setStyle(this.options.hintlineStyle);\n }\n },\n _createVertex(e) {\n // don't create a vertex if we have a selfIntersection and it is not allowed\n if (!this.options.allowSelfIntersection) {\n this._handleSelfIntersection(true, e.latlng);\n\n if (this._doesSelfIntersect) {\n return;\n }\n }\n\n // assign the coordinate of the click to the hintMarker, that's necessary for\n // mobile where the marker can't follow a cursor\n if (!this._hintMarker._snapped) {\n this._hintMarker.setLatLng(e.latlng);\n }\n\n // get coordinate for new vertex by hintMarker (cursor marker)\n const latlng = this._hintMarker.getLatLng();\n\n // check if the first and this vertex have the same latlng\n // or the last vertex and the hintMarker have the same latlng (dbl-click)\n const latlngs = this._layer.getLatLngs();\n\n const lastLatLng = latlngs[latlngs.length - 1];\n if (\n latlng.equals(latlngs[0]) ||\n (latlngs.length > 0 && latlng.equals(lastLatLng))\n ) {\n // yes? finish the polygon\n this._finishShape();\n\n // \"why?\", you ask? Because this happens when we snap the last vertex to the first one\n // and then click without hitting the last marker. Click happens on the map\n // in 99% of cases it's because the user wants to finish the polygon. So...\n return;\n }\n\n this._layer._latlngInfo = this._layer._latlngInfo || [];\n this._layer._latlngInfo.push({\n latlng,\n snapInfo: this._hintMarker._snapInfo,\n });\n\n this._layer.addLatLng(latlng);\n const newMarker = this._createMarker(latlng);\n this._setTooltipText();\n\n this._setHintLineAfterNewVertex(latlng);\n\n this._fireVertexAdded(newMarker, undefined, latlng, 'Draw');\n this._change(this._layer.getLatLngs());\n // check if we should finish on snap\n if (this.options.finishOn === 'snap' && this._hintMarker._snapped) {\n this._finishShape(e);\n }\n },\n _setHintLineAfterNewVertex(hintMarkerLatLng) {\n // make the new drawn line (with another style) visible\n this._hintline.setLatLngs([hintMarkerLatLng, hintMarkerLatLng]);\n },\n _removeLastVertex() {\n const markers = this._markers;\n\n // if all markers are gone, cancel drawing\n if (markers.length <= 1) {\n this.disable();\n return;\n }\n\n // remove last coords\n let coords = this._layer.getLatLngs();\n\n const removedMarker = markers[markers.length - 1];\n\n // the index path to the marker inside the multidimensional marker array\n const { indexPath } = L.PM.Utils.findDeepMarkerIndex(\n markers,\n removedMarker\n );\n\n // remove last marker from array\n markers.pop();\n\n // remove that marker\n this._layerGroup.removeLayer(removedMarker);\n\n const markerPrevious = markers[markers.length - 1];\n\n // no need for findDeepMarkerIndex because the coords are always flat (Polyline) no matter if Line or Polygon\n const indexMarkerPrev = coords.indexOf(markerPrevious.getLatLng());\n\n // +1 don't cut out the previous marker\n coords = coords.slice(0, indexMarkerPrev + 1);\n\n // update layer with new coords\n this._layer.setLatLngs(coords);\n this._layer._latlngInfo.pop();\n\n // sync the hintline again\n this._syncHintLine();\n this._setTooltipText();\n\n this._fireVertexRemoved(removedMarker, indexPath, 'Draw');\n this._change(this._layer.getLatLngs());\n },\n _finishShape() {\n // if self intersection is not allowed, do not finish the shape!\n if (!this.options.allowSelfIntersection) {\n this._handleSelfIntersection(false);\n\n if (this._doesSelfIntersect) {\n return;\n }\n }\n\n // If snap finish is required but the last marker wasn't snapped, do not finish the shape!\n if (\n this.options.requireSnapToFinish &&\n !this._hintMarker._snapped &&\n !this._isFirstLayer()\n ) {\n return;\n }\n\n // get coordinates\n const coords = this._layer.getLatLngs();\n\n // if there is only one coords, don't finish the shape!\n if (coords.length <= 1) {\n return;\n }\n\n // create the leaflet shape and add it to the map\n const polylineLayer = L.polyline(coords, this.options.pathOptions);\n this._setPane(polylineLayer, 'layerPane');\n this._finishLayer(polylineLayer);\n polylineLayer.addTo(this._map.pm._getContainingLayer());\n\n // fire the pm:create event and pass shape and layer\n this._fireCreate(polylineLayer);\n\n if (this.options.snappable) {\n this._cleanupSnapping();\n }\n\n // disable drawing\n this.disable();\n if (this.options.continueDrawing) {\n this.enable();\n }\n },\n _createMarker(latlng) {\n // create the new marker\n const marker = new L.Marker(latlng, {\n draggable: false,\n icon: L.divIcon({ className: 'marker-icon' }),\n });\n this._setPane(marker, 'vertexPane');\n marker._pmTempLayer = true;\n\n // add it to the map\n this._layerGroup.addLayer(marker);\n this._markers.push(marker);\n\n // a click on any marker finishes this shape\n marker.on('click', this._finishShape, this);\n\n return marker;\n },\n _setTooltipText() {\n const { length } = this._layer.getLatLngs().flat();\n let text = '';\n\n // handle tooltip text\n if (length <= 1) {\n text = getTranslation('tooltips.continueLine');\n } else {\n text = getTranslation('tooltips.finishLine');\n }\n this._hintMarker.setTooltipContent(text);\n },\n _change(latlngs) {\n this._fireChange(latlngs, 'Draw');\n },\n setStyle() {\n this._layer?.setStyle(this.options.templineStyle);\n this._hintline?.setStyle(this.options.hintlineStyle);\n },\n});\n","import Draw from './L.PM.Draw';\nimport { getTranslation } from '../helpers';\n\nDraw.Polygon = Draw.Line.extend({\n initialize(map) {\n this._map = map;\n this._shape = 'Polygon';\n this.toolbarButtonName = 'drawPolygon';\n },\n enable(options) {\n L.PM.Draw.Line.prototype.enable.call(this, options);\n // Overwrite the shape \"Line\" of this._layer\n this._layer.pm._shape = 'Polygon';\n },\n _createMarker(latlng) {\n // create the new marker\n const marker = new L.Marker(latlng, {\n draggable: false,\n icon: L.divIcon({ className: 'marker-icon' }),\n });\n this._setPane(marker, 'vertexPane');\n\n // mark this marker as temporary\n marker._pmTempLayer = true;\n\n // add it to the map\n this._layerGroup.addLayer(marker);\n this._markers.push(marker);\n\n // if the first marker gets clicked again, finish this shape\n if (this._layer.getLatLngs().flat().length === 1) {\n marker.on('click', this._finishShape, this);\n\n // add the first vertex to \"other snapping layers\" so the polygon is easier to finish\n this._tempSnapLayerIndex = this._otherSnapLayers.push(marker) - 1;\n\n if (this.options.snappable) {\n this._cleanupSnapping();\n }\n } else {\n // add a click event w/ no handler to the marker\n // event won't bubble so prevents creation of identical markers in same polygon\n // fixes issue where double click during poly creation when allowSelfIntersection: false caused it to break\n marker.on('click', () => 1);\n }\n\n return marker;\n },\n _setTooltipText() {\n const { length } = this._layer.getLatLngs().flat();\n let text = '';\n\n // handle tooltip text\n if (length <= 2) {\n text = getTranslation('tooltips.continueLine');\n } else {\n text = getTranslation('tooltips.finishPoly');\n }\n this._hintMarker.setTooltipContent(text);\n },\n _finishShape() {\n // if self intersection is not allowed, do not finish the shape!\n if (!this.options.allowSelfIntersection) {\n // Check if polygon intersects when is completed and the line between the last and the first point is drawn\n this._handleSelfIntersection(true, this._layer.getLatLngs()[0]);\n\n if (this._doesSelfIntersect) {\n return;\n }\n }\n\n // If snap finish is required but the last marker wasn't snapped, do not finish the shape!\n if (\n this.options.requireSnapToFinish &&\n !this._hintMarker._snapped &&\n !this._isFirstLayer()\n ) {\n return;\n }\n\n // get coordinates\n const coords = this._layer.getLatLngs();\n\n // only finish the shape if there are 3 or more vertices\n if (coords.length <= 2) {\n return;\n }\n\n const polygonLayer = L.polygon(coords, this.options.pathOptions);\n this._setPane(polygonLayer, 'layerPane');\n this._finishLayer(polygonLayer);\n polygonLayer.addTo(this._map.pm._getContainingLayer());\n\n // fire the pm:create event and pass shape and layer\n this._fireCreate(polygonLayer);\n\n // clean up snapping states\n this._cleanupSnapping();\n\n // remove the first vertex from \"other snapping layers\"\n this._otherSnapLayers.splice(this._tempSnapLayerIndex, 1);\n delete this._tempSnapLayerIndex;\n\n // disable drawing\n this.disable();\n if (this.options.continueDrawing) {\n this.enable();\n }\n },\n});\n","import Draw from './L.PM.Draw';\nimport { fixLatOffset, getTranslation } from '../helpers';\n\nDraw.Rectangle = Draw.extend({\n initialize(map) {\n this._map = map;\n this._shape = 'Rectangle';\n this.toolbarButtonName = 'drawRectangle';\n },\n enable(options) {\n // TODO: Think about if these options could be passed globally for all\n // instances of L.PM.Draw. So a dev could set drawing style one time as some kind of config\n L.Util.setOptions(this, options);\n\n // enable draw mode\n this._enabled = true;\n\n // create a new layergroup\n this._layerGroup = new L.FeatureGroup();\n this._layerGroup._pmTempLayer = true;\n this._layerGroup.addTo(this._map);\n\n // the rectangle we want to draw\n this._layer = L.rectangle(\n [\n [0, 0],\n [0, 0],\n ],\n this.options.pathOptions\n );\n this._setPane(this._layer, 'layerPane');\n this._layer._pmTempLayer = true;\n\n // this is the marker at the origin of the rectangle\n // this needs to be present, for tracking purposes, but we'll make it invisible if a user doesn't want to see it!\n this._startMarker = L.marker(this._map.getCenter(), {\n icon: L.divIcon({ className: 'marker-icon rect-start-marker' }),\n draggable: false,\n zIndexOffset: -100,\n opacity: this.options.cursorMarker ? 1 : 0,\n });\n this._setPane(this._startMarker, 'vertexPane');\n this._startMarker._pmTempLayer = true;\n this._layerGroup.addLayer(this._startMarker);\n\n // this is the hintmarker on the mouse cursor\n this._hintMarker = L.marker(this._map.getCenter(), {\n zIndexOffset: 150,\n icon: L.divIcon({ className: 'marker-icon cursor-marker' }),\n });\n this._setPane(this._hintMarker, 'vertexPane');\n this._hintMarker._pmTempLayer = true;\n this._layerGroup.addLayer(this._hintMarker);\n\n // show the hintmarker if the option is set\n if (this.options.cursorMarker) {\n L.DomUtil.addClass(this._hintMarker._icon, 'visible');\n }\n\n // add tooltip to hintmarker\n if (this.options.tooltips) {\n this._hintMarker\n .bindTooltip(getTranslation('tooltips.firstVertex'), {\n permanent: true,\n offset: L.point(0, 10),\n direction: 'bottom',\n\n opacity: 0.8,\n })\n .openTooltip();\n }\n\n if (this.options.cursorMarker) {\n // Add two more matching style markers, if cursor marker is rendered\n this._styleMarkers = [];\n for (let i = 0; i < 2; i += 1) {\n const styleMarker = L.marker(this._map.getCenter(), {\n icon: L.divIcon({\n className: 'marker-icon rect-style-marker',\n }),\n draggable: false,\n zIndexOffset: 100,\n });\n this._setPane(styleMarker, 'vertexPane');\n styleMarker._pmTempLayer = true;\n this._layerGroup.addLayer(styleMarker);\n\n this._styleMarkers.push(styleMarker);\n }\n }\n\n // change map cursor\n this._map.getContainer().classList.add('geoman-draw-cursor');\n\n // create a polygon-point on click\n this._map.on('click', this._placeStartingMarkers, this);\n\n // sync hint marker with mouse cursor\n this._map.on('mousemove', this._syncHintMarker, this);\n\n // toggle the draw button of the Toolbar in case drawing mode got enabled without the button\n this._map.pm.Toolbar.toggleButton(this.toolbarButtonName, true);\n\n // an array used in the snapping mixin.\n // TODO: think about moving this somewhere else?\n this._otherSnapLayers = [];\n\n // fire drawstart event\n this._fireDrawStart();\n this._setGlobalDrawMode();\n },\n disable() {\n // disable drawing mode\n\n // cancel, if drawing mode isn't event enabled\n if (!this._enabled) {\n return;\n }\n\n this._enabled = false;\n\n // reset cursor\n this._map.getContainer().classList.remove('geoman-draw-cursor');\n\n // unbind listeners\n this._map.off('click', this._finishShape, this);\n this._map.off('click', this._placeStartingMarkers, this);\n this._map.off('mousemove', this._syncHintMarker, this);\n\n // remove helping layers\n this._map.removeLayer(this._layerGroup);\n\n // toggle the draw button of the Toolbar in case drawing mode got disabled without the button\n this._map.pm.Toolbar.toggleButton(this.toolbarButtonName, false);\n\n // cleanup snapping\n if (this.options.snappable) {\n this._cleanupSnapping();\n }\n // fire drawend event\n this._fireDrawEnd();\n this._setGlobalDrawMode();\n },\n enabled() {\n return this._enabled;\n },\n toggle(options) {\n if (this.enabled()) {\n this.disable();\n } else {\n this.enable(options);\n }\n },\n _placeStartingMarkers(e) {\n // assign the coordinate of the click to the hintMarker, that's necessary for\n // mobile where the marker can't follow a cursor\n if (!this._hintMarker._snapped) {\n this._hintMarker.setLatLng(e.latlng);\n }\n\n // get coordinate for new vertex by hintMarker (cursor marker)\n const latlng = this._hintMarker.getLatLng();\n\n // show and place start marker\n L.DomUtil.addClass(this._startMarker._icon, 'visible');\n this._startMarker.setLatLng(latlng);\n\n // if we have the other two visibilty markers, show and place them now\n if (this.options.cursorMarker && this._styleMarkers) {\n this._styleMarkers.forEach((styleMarker) => {\n L.DomUtil.addClass(styleMarker._icon, 'visible');\n styleMarker.setLatLng(latlng);\n });\n }\n\n this._map.off('click', this._placeStartingMarkers, this);\n this._map.on('click', this._finishShape, this);\n\n // change tooltip text\n this._hintMarker.setTooltipContent(getTranslation('tooltips.finishRect'));\n\n this._setRectangleOrigin();\n },\n _setRectangleOrigin() {\n const latlng = this._startMarker.getLatLng();\n\n if (latlng) {\n // show it first\n this._layerGroup.addLayer(this._layer);\n\n this._layer.setLatLngs([latlng, latlng]);\n\n this._hintMarker.on('move', this._syncRectangleSize, this);\n }\n },\n _syncHintMarker(e) {\n // move the cursor marker\n this._hintMarker.setLatLng(e.latlng);\n\n // if snapping is enabled, do it\n if (this.options.snappable) {\n const fakeDragEvent = e;\n fakeDragEvent.target = this._hintMarker;\n this._handleSnapping(fakeDragEvent);\n }\n\n const latlngs =\n this._layerGroup && this._layerGroup.hasLayer(this._layer)\n ? this._layer.getLatLngs()\n : [this._hintMarker.getLatLng()];\n this._fireChange(latlngs, 'Draw');\n },\n _syncRectangleSize() {\n const A = fixLatOffset(this._startMarker.getLatLng(), this._map);\n const B = fixLatOffset(this._hintMarker.getLatLng(), this._map);\n\n // Create a (maybe rotated) box using corners A & B (A = Starting Position, B = Current Mouse Position)\n const corners = L.PM.Utils._getRotatedRectangle(\n A,\n B,\n this.options.rectangleAngle || 0,\n this._map\n );\n this._layer.setLatLngs(corners);\n\n // Add matching style markers, if cursor marker is shown\n if (this.options.cursorMarker && this._styleMarkers) {\n const unmarkedCorners = [];\n\n // Find two corners not currently occupied by starting marker and hint marker\n corners.forEach((corner) => {\n // the default equals margin is 1.0e-9 but in other crs projections the latlng equality can be slightly different after `_getRotatedRectangle`, so we make the precession a little bit lower\n if (!corner.equals(A, 1.0e-8) && !corner.equals(B, 1.0e-8)) {\n unmarkedCorners.push(corner);\n }\n });\n\n // Reposition style markers\n unmarkedCorners.forEach((unmarkedCorner, index) => {\n try {\n this._styleMarkers[index].setLatLng(unmarkedCorner);\n } catch (e) {\n // ignore error - should be fixed with the next mousemove\n }\n });\n }\n },\n _findCorners() {\n const latlngs = this._layer.getLatLngs()[0];\n return L.PM.Utils._getRotatedRectangle(\n latlngs[0],\n latlngs[2],\n this.options.rectangleAngle || 0,\n this._map\n );\n },\n _finishShape(e) {\n // assign the coordinate of the click to the hintMarker, that's necessary for\n // mobile where the marker can't follow a cursor\n if (!this._hintMarker._snapped) {\n this._hintMarker.setLatLng(e.latlng);\n }\n\n // get coordinate for new vertex by hintMarker (cursor marker)\n const B = this._hintMarker.getLatLng();\n // get already placed corner from the startmarker\n const A = this._startMarker.getLatLng();\n\n // If snap finish is required but the last marker wasn't snapped, do not finish the shape!\n if (\n this.options.requireSnapToFinish &&\n !this._hintMarker._snapped &&\n !this._isFirstLayer()\n ) {\n return;\n }\n\n if (A.equals(B)) {\n // rectangle has only one point\n return;\n }\n\n // create the final rectangle layer, based on opposite corners A & B\n const rectangleLayer = L.rectangle([A, B], this.options.pathOptions);\n\n // rectangle can only initialized with bounds (not working with rotation) so we update the latlngs\n if (this.options.rectangleAngle) {\n const corners = L.PM.Utils._getRotatedRectangle(\n A,\n B,\n this.options.rectangleAngle || 0,\n this._map\n );\n rectangleLayer.setLatLngs(corners);\n if (rectangleLayer.pm) {\n rectangleLayer.pm._setAngle(this.options.rectangleAngle || 0);\n }\n }\n\n this._setPane(rectangleLayer, 'layerPane');\n this._finishLayer(rectangleLayer);\n rectangleLayer.addTo(this._map.pm._getContainingLayer());\n\n // fire the pm:create event and pass shape and layer\n this._fireCreate(rectangleLayer);\n\n // disable drawing\n this.disable();\n if (this.options.continueDrawing) {\n this.enable();\n }\n },\n setStyle() {\n this._layer?.setStyle(this.options.pathOptions);\n },\n});\n","import Draw from './L.PM.Draw';\nimport { destinationOnLine, getTranslation } from '../helpers';\n\nDraw.CircleMarker = Draw.extend({\n initialize(map) {\n this._map = map;\n this._shape = 'CircleMarker';\n this.toolbarButtonName = 'drawCircleMarker';\n // with _layerIsDragging we check if a circlemarker is currently dragged and disable marker creation\n this._layerIsDragging = false;\n this._BaseCircleClass = L.CircleMarker;\n this._minRadiusOption = 'minRadiusCircleMarker';\n this._maxRadiusOption = 'maxRadiusCircleMarker';\n this._editableOption = 'resizeableCircleMarker';\n this._defaultRadius = 10;\n },\n enable(options) {\n // TODO: Think about if these options could be passed globally for all\n // instances of L.PM.Draw. So a dev could set drawing style one time as some kind of config\n L.Util.setOptions(this, options);\n // TODO: remove with next major release\n if (this.options.editable) {\n this.options.resizeableCircleMarker = this.options.editable;\n delete this.options.editable;\n }\n\n // change enabled state\n this._enabled = true;\n\n // toggle the draw button of the Toolbar in case drawing mode got enabled without the button\n this._map.pm.Toolbar.toggleButton(this.toolbarButtonName, true);\n\n // change map cursor\n this._map.getContainer().classList.add('geoman-draw-cursor');\n\n // Draw the CircleMarker like a Circle\n if (this.options[this._editableOption]) {\n // we need to set the radius to 0 without overwriting the CircleMarker style\n const templineStyle = {};\n L.extend(templineStyle, this.options.templineStyle);\n templineStyle.radius = 0;\n\n // create a new layergroup\n this._layerGroup = new L.FeatureGroup();\n this._layerGroup._pmTempLayer = true;\n this._layerGroup.addTo(this._map);\n\n // this is the circle we want to draw\n this._layer = new this._BaseCircleClass(\n this._map.getCenter(),\n templineStyle\n );\n this._setPane(this._layer, 'layerPane');\n this._layer._pmTempLayer = true;\n\n // this is the marker in the center of the circle\n this._centerMarker = L.marker(this._map.getCenter(), {\n icon: L.divIcon({ className: 'marker-icon' }),\n draggable: false,\n zIndexOffset: 100,\n });\n this._setPane(this._centerMarker, 'vertexPane');\n this._centerMarker._pmTempLayer = true;\n\n // this is the hintmarker on the mouse cursor\n this._hintMarker = L.marker(this._map.getCenter(), {\n zIndexOffset: 110,\n icon: L.divIcon({ className: 'marker-icon cursor-marker' }),\n });\n this._setPane(this._hintMarker, 'vertexPane');\n this._hintMarker._pmTempLayer = true;\n this._layerGroup.addLayer(this._hintMarker);\n\n // show the hintmarker if the option is set\n if (this.options.cursorMarker) {\n L.DomUtil.addClass(this._hintMarker._icon, 'visible');\n }\n\n // add tooltip to hintmarker\n if (this.options.tooltips) {\n this._hintMarker\n .bindTooltip(getTranslation('tooltips.startCircle'), {\n permanent: true,\n offset: L.point(0, 10),\n direction: 'bottom',\n\n opacity: 0.8,\n })\n .openTooltip();\n }\n\n // this is the hintline from the hint marker to the center marker\n this._hintline = L.polyline([], this.options.hintlineStyle);\n this._setPane(this._hintline, 'layerPane');\n this._hintline._pmTempLayer = true;\n this._layerGroup.addLayer(this._hintline);\n // create a polygon-point on click\n this._map.on('click', this._placeCenterMarker, this);\n } else {\n // create a marker on click on the map\n this._map.on('click', this._createMarker, this);\n\n // this is the hintmarker on the mouse cursor\n this._hintMarker = new this._BaseCircleClass(this._map.getCenter(), {\n radius: this._defaultRadius,\n ...this.options.templineStyle,\n });\n this._setPane(this._hintMarker, 'layerPane');\n this._hintMarker._pmTempLayer = true;\n this._hintMarker.addTo(this._map);\n // this is just to keep the snappable mixin happy\n this._layer = this._hintMarker;\n\n // add tooltip to hintmarker\n if (this.options.tooltips) {\n this._hintMarker\n .bindTooltip(getTranslation('tooltips.placeCircleMarker'), {\n permanent: true,\n offset: L.point(0, 10),\n direction: 'bottom',\n\n opacity: 0.8,\n })\n .openTooltip();\n }\n }\n\n // sync hint marker with mouse cursor\n this._map.on('mousemove', this._syncHintMarker, this);\n\n this._extendingEnable();\n\n // an array used in the snapping mixin.\n // TODO: think about moving this somewhere else?\n this._otherSnapLayers = [];\n\n // fire drawstart event\n this._fireDrawStart();\n this._setGlobalDrawMode();\n },\n _extendingEnable() {\n if (!this.options[this._editableOption] && this.options.markerEditable) {\n // enable edit mode for existing markers\n this._map.eachLayer((layer) => {\n if (this.isRelevantMarker(layer)) {\n layer.pm.enable();\n }\n });\n }\n\n this._layer.bringToBack();\n },\n disable() {\n // cancel, if drawing mode isn't even enabled\n if (!this._enabled) {\n return;\n }\n // change enabled state\n this._enabled = false;\n\n // reset cursor\n this._map.getContainer().classList.remove('geoman-draw-cursor');\n\n // disable when drawing like a Circle\n if (this.options[this._editableOption]) {\n // unbind listeners\n this._map.off('click', this._finishShape, this);\n this._map.off('click', this._placeCenterMarker, this);\n\n // remove helping layers\n this._map.removeLayer(this._layerGroup);\n } else {\n // undbind click event, don't create a marker on click anymore\n this._map.off('click', this._createMarker, this);\n\n this._extendingDisable();\n\n // remove hint marker\n this._hintMarker.remove();\n }\n\n // remove event listener to sync hint marker\n this._map.off('mousemove', this._syncHintMarker, this);\n\n // toggle the draw button of the Toolbar in case drawing mode got disabled without the button\n this._map.pm.Toolbar.toggleButton(this.toolbarButtonName, false);\n\n // cleanup snapping\n if (this.options.snappable) {\n this._cleanupSnapping();\n }\n\n // fire drawend event\n this._fireDrawEnd();\n this._setGlobalDrawMode();\n },\n _extendingDisable() {\n // disable dragging and removing for all markers\n this._map.eachLayer((layer) => {\n if (this.isRelevantMarker(layer)) {\n layer.pm.disable();\n }\n });\n },\n enabled() {\n return this._enabled;\n },\n toggle(options) {\n if (this.enabled()) {\n this.disable();\n } else {\n this.enable(options);\n }\n },\n _placeCenterMarker(e) {\n this._layerGroup.addLayer(this._layer);\n this._layerGroup.addLayer(this._centerMarker);\n // assign the coordinate of the click to the hintMarker, that's necessary for\n // mobile where the marker can't follow a cursor\n if (!this._hintMarker._snapped) {\n this._hintMarker.setLatLng(e.latlng);\n }\n\n // get coordinate for new vertex by hintMarker (cursor marker)\n const latlng = this._hintMarker.getLatLng();\n this._layerGroup.addLayer(this._layer);\n\n this._centerMarker.setLatLng(latlng);\n\n this._map.off('click', this._placeCenterMarker, this);\n this._map.on('click', this._finishShape, this);\n\n this._placeCircleCenter();\n },\n _placeCircleCenter() {\n const latlng = this._centerMarker.getLatLng();\n\n if (latlng) {\n this._layer.setLatLng(latlng);\n\n // sync the hintline with hint marker\n this._hintMarker.on('move', this._syncHintLine, this);\n this._hintMarker.on('move', this._syncCircleRadius, this);\n\n this._hintMarker.setTooltipContent(\n getTranslation('tooltips.finishCircle')\n );\n\n this._fireCenterPlaced();\n this._fireChange(this._layer.getLatLng(), 'Draw');\n }\n },\n _syncHintLine() {\n const latlng = this._centerMarker.getLatLng();\n const secondLatLng = this._getNewDestinationOfHintMarker();\n // set coords for hintline from marker to last vertex of drawin polyline\n this._hintline.setLatLngs([latlng, secondLatLng]);\n },\n _syncCircleRadius() {\n const A = this._centerMarker.getLatLng();\n const B = this._hintMarker.getLatLng();\n\n const distance = this._distanceCalculation(A, B);\n\n if (\n this.options[this._minRadiusOption] &&\n distance < this.options[this._minRadiusOption]\n ) {\n this._layer.setRadius(this.options[this._minRadiusOption]);\n } else if (\n this.options[this._maxRadiusOption] &&\n distance > this.options[this._maxRadiusOption]\n ) {\n this._layer.setRadius(this.options[this._maxRadiusOption]);\n } else {\n this._layer.setRadius(distance);\n }\n },\n _syncHintMarker(e) {\n // move the cursor marker\n this._hintMarker.setLatLng(e.latlng);\n // calculate the new latlng of marker if radius is out of min/max\n this._hintMarker.setLatLng(this._getNewDestinationOfHintMarker());\n\n // if snapping is enabled, do it\n if (this.options.snappable) {\n const fakeDragEvent = e;\n fakeDragEvent.target = this._hintMarker;\n this._handleSnapping(fakeDragEvent);\n }\n\n this._handleHintMarkerSnapping();\n\n const latlng =\n this._layerGroup && this._layerGroup.hasLayer(this._centerMarker)\n ? this._centerMarker.getLatLng()\n : this._hintMarker.getLatLng();\n this._fireChange(latlng, 'Draw');\n },\n isRelevantMarker(layer) {\n return (\n layer instanceof L.CircleMarker &&\n !(layer instanceof L.Circle) &&\n layer.pm &&\n !layer._pmTempLayer\n );\n },\n _createMarker(e) {\n // If snap finish is required but the last marker wasn't snapped, do not finish the shape!\n if (\n this.options.requireSnapToFinish &&\n !this._hintMarker._snapped &&\n !this._isFirstLayer()\n ) {\n return;\n }\n\n // with _layerIsDragging we check if a circlemarker is currently dragged\n if (!e.latlng || this._layerIsDragging) {\n return;\n }\n\n // assign the coordinate of the click to the hintMarker, that's necessary for\n // mobile where the marker can't follow a cursor\n if (!this._hintMarker._snapped) {\n this._hintMarker.setLatLng(e.latlng);\n }\n\n // get coordinate for new vertex by hintMarker (cursor marker)\n const latlng = this._hintMarker.getLatLng();\n\n // create marker\n const marker = new this._BaseCircleClass(latlng, {\n radius: this._defaultRadius,\n ...this.options.pathOptions,\n });\n this._setPane(marker, 'layerPane');\n this._finishLayer(marker);\n // add marker to the map\n marker.addTo(this._map.pm._getContainingLayer());\n\n this._extendingCreateMarker(marker);\n\n // fire the pm:create event and pass shape and marker\n this._fireCreate(marker);\n\n this._cleanupSnapping();\n\n if (!this.options.continueDrawing) {\n this.disable();\n }\n },\n _extendingCreateMarker(marker) {\n if (marker.pm && this.options.markerEditable) {\n // enable editing for the marker\n marker.pm.enable();\n }\n },\n _finishShape(e) {\n // If snap finish is required but the last marker wasn't snapped, do not finish the shape!\n if (\n this.options.requireSnapToFinish &&\n !this._hintMarker._snapped &&\n !this._isFirstLayer()\n ) {\n return;\n }\n\n // assign the coordinate of the click to the hintMarker, that's necessary for\n // mobile where the marker can't follow a cursor\n if (!this._hintMarker._snapped) {\n this._hintMarker.setLatLng(e.latlng);\n }\n\n const center = this._centerMarker.getLatLng();\n let radius = this._defaultRadius;\n if (this.options[this._editableOption]) {\n // calc the radius\n const latlng = this._hintMarker.getLatLng();\n radius = this._distanceCalculation(center, latlng);\n if (\n this.options[this._minRadiusOption] &&\n radius < this.options[this._minRadiusOption]\n ) {\n radius = this.options[this._minRadiusOption];\n } else if (\n this.options[this._maxRadiusOption] &&\n radius > this.options[this._maxRadiusOption]\n ) {\n radius = this.options[this._maxRadiusOption];\n }\n }\n\n const options = { ...this.options.pathOptions, radius };\n\n // create the final circle layer\n const circleLayer = new this._BaseCircleClass(center, options);\n this._setPane(circleLayer, 'layerPane');\n this._finishLayer(circleLayer);\n circleLayer.addTo(this._map.pm._getContainingLayer());\n\n if (circleLayer.pm) {\n // create polygon around the circle border\n circleLayer.pm._updateHiddenPolyCircle();\n }\n\n // fire the pm:create event and pass shape and layer\n this._fireCreate(circleLayer);\n\n // disable drawing\n this.disable();\n if (this.options.continueDrawing) {\n this.enable();\n }\n },\n _getNewDestinationOfHintMarker() {\n let secondLatLng = this._hintMarker.getLatLng();\n if (this.options[this._editableOption]) {\n if (!this._layerGroup.hasLayer(this._centerMarker)) {\n return secondLatLng;\n }\n\n const latlng = this._centerMarker.getLatLng();\n\n const distance = this._distanceCalculation(latlng, secondLatLng);\n\n if (\n this.options[this._minRadiusOption] &&\n distance < this.options[this._minRadiusOption]\n ) {\n secondLatLng = destinationOnLine(\n this._map,\n latlng,\n secondLatLng,\n this._getMinDistanceInMeter()\n );\n } else if (\n this.options[this._maxRadiusOption] &&\n distance > this.options[this._maxRadiusOption]\n ) {\n secondLatLng = destinationOnLine(\n this._map,\n latlng,\n secondLatLng,\n this._getMaxDistanceInMeter()\n );\n }\n }\n return secondLatLng;\n },\n _getMinDistanceInMeter() {\n return L.PM.Utils.pxRadiusToMeterRadius(\n this.options[this._minRadiusOption],\n this._map,\n this._centerMarker.getLatLng()\n );\n },\n _getMaxDistanceInMeter() {\n return L.PM.Utils.pxRadiusToMeterRadius(\n this.options[this._maxRadiusOption],\n this._map,\n this._centerMarker.getLatLng()\n );\n },\n _handleHintMarkerSnapping() {\n if (this.options[this._editableOption]) {\n if (this._hintMarker._snapped) {\n const latlng = this._centerMarker.getLatLng();\n const secondLatLng = this._hintMarker.getLatLng();\n const distance = this._distanceCalculation(latlng, secondLatLng);\n\n if (!this._layerGroup.hasLayer(this._centerMarker)) {\n // do nothing\n } else if (\n this.options[this._minRadiusOption] &&\n distance < this.options[this._minRadiusOption]\n ) {\n this._hintMarker.setLatLng(this._hintMarker._orgLatLng);\n } else if (\n this.options[this._maxRadiusOption] &&\n distance > this.options[this._maxRadiusOption]\n ) {\n this._hintMarker.setLatLng(this._hintMarker._orgLatLng);\n }\n }\n // calculate the new latlng of marker if the snapped latlng radius is out of min/max\n this._hintMarker.setLatLng(this._getNewDestinationOfHintMarker());\n }\n },\n setStyle() {\n const templineStyle = {};\n L.extend(templineStyle, this.options.templineStyle);\n if (this.options[this._editableOption]) {\n templineStyle.radius = 0;\n }\n this._layer?.setStyle(templineStyle);\n this._hintline?.setStyle(this.options.hintlineStyle);\n },\n _distanceCalculation(A, B) {\n return this._map.project(A).distanceTo(this._map.project(B));\n },\n});\n","import Draw from './L.PM.Draw';\n\nDraw.Circle = Draw.CircleMarker.extend({\n initialize(map) {\n this._map = map;\n this._shape = 'Circle';\n this.toolbarButtonName = 'drawCircle';\n this._BaseCircleClass = L.Circle;\n this._minRadiusOption = 'minRadiusCircle';\n this._maxRadiusOption = 'maxRadiusCircle';\n this._editableOption = 'resizableCircle';\n this._defaultRadius = 100;\n },\n _extendingEnable() {},\n _extendingDisable() {},\n _extendingCreateMarker() {},\n isRelevantMarker() {},\n _getMinDistanceInMeter() {\n return this.options[this._minRadiusOption];\n },\n _getMaxDistanceInMeter() {\n return this.options[this._maxRadiusOption];\n },\n _distanceCalculation(A, B) {\n return this._map.distance(A, B);\n },\n});\n","import { featureCollection, lineString, } from \"@turf/helpers\";\nimport { getCoords } from \"@turf/invariant\";\nimport { flattenEach } from \"@turf/meta\";\n/**\n * Creates a {@link FeatureCollection} of 2-vertex {@link LineString} segments from a\n * {@link LineString|(Multi)LineString} or {@link Polygon|(Multi)Polygon}.\n *\n * @name lineSegment\n * @param {GeoJSON} geojson GeoJSON Polygon or LineString\n * @returns {FeatureCollection} 2-vertex line segments\n * @example\n * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]);\n * var segments = turf.lineSegment(polygon);\n *\n * //addToMap\n * var addToMap = [polygon, segments]\n */\nfunction lineSegment(geojson) {\n if (!geojson) {\n throw new Error(\"geojson is required\");\n }\n var results = [];\n flattenEach(geojson, function (feature) {\n lineSegmentFeature(feature, results);\n });\n return featureCollection(results);\n}\n/**\n * Line Segment\n *\n * @private\n * @param {Feature} geojson Line or polygon feature\n * @param {Array} results push to results\n * @returns {void}\n */\nfunction lineSegmentFeature(geojson, results) {\n var coords = [];\n var geometry = geojson.geometry;\n if (geometry !== null) {\n switch (geometry.type) {\n case \"Polygon\":\n coords = getCoords(geometry);\n break;\n case \"LineString\":\n coords = [getCoords(geometry)];\n }\n coords.forEach(function (coord) {\n var segments = createSegments(coord, geojson.properties);\n segments.forEach(function (segment) {\n segment.id = results.length;\n results.push(segment);\n });\n });\n }\n}\n/**\n * Create Segments from LineString coordinates\n *\n * @private\n * @param {Array>} coords LineString coordinates\n * @param {*} properties GeoJSON properties\n * @returns {Array>} line segments\n */\nfunction createSegments(coords, properties) {\n var segments = [];\n coords.reduce(function (previousCoords, currentCoords) {\n var segment = lineString([previousCoords, currentCoords], properties);\n segment.bbox = bbox(previousCoords, currentCoords);\n segments.push(segment);\n return currentCoords;\n });\n return segments;\n}\n/**\n * Create BBox between two coordinates (faster than @turf/bbox)\n *\n * @private\n * @param {Array} coords1 Point coordinate\n * @param {Array} coords2 Point coordinate\n * @returns {BBox} [west, south, east, north]\n */\nfunction bbox(coords1, coords2) {\n var x1 = coords1[0];\n var y1 = coords1[1];\n var x2 = coords2[0];\n var y2 = coords2[1];\n var west = x1 < x2 ? x1 : x2;\n var south = y1 < y2 ? y1 : y2;\n var east = x1 > x2 ? x1 : x2;\n var north = y1 > y2 ? y1 : y2;\n return [west, south, east, north];\n}\nexport default lineSegment;\n","import { feature, featureCollection, point, } from \"@turf/helpers\";\nimport { getCoords } from \"@turf/invariant\";\nimport lineSegment from \"@turf/line-segment\";\nimport { featureEach } from \"@turf/meta\";\nimport rbush from \"geojson-rbush\";\n/**\n * Takes any LineString or Polygon GeoJSON and returns the intersecting point(s).\n *\n * @name lineIntersect\n * @param {GeoJSON} line1 any LineString or Polygon\n * @param {GeoJSON} line2 any LineString or Polygon\n * @returns {FeatureCollection} point(s) that intersect both\n * @example\n * var line1 = turf.lineString([[126, -11], [129, -21]]);\n * var line2 = turf.lineString([[123, -18], [131, -14]]);\n * var intersects = turf.lineIntersect(line1, line2);\n *\n * //addToMap\n * var addToMap = [line1, line2, intersects]\n */\nfunction lineIntersect(line1, line2) {\n var unique = {};\n var results = [];\n // First, normalize geometries to features\n // Then, handle simple 2-vertex segments\n if (line1.type === \"LineString\") {\n line1 = feature(line1);\n }\n if (line2.type === \"LineString\") {\n line2 = feature(line2);\n }\n if (line1.type === \"Feature\" &&\n line2.type === \"Feature\" &&\n line1.geometry !== null &&\n line2.geometry !== null &&\n line1.geometry.type === \"LineString\" &&\n line2.geometry.type === \"LineString\" &&\n line1.geometry.coordinates.length === 2 &&\n line2.geometry.coordinates.length === 2) {\n var intersect = intersects(line1, line2);\n if (intersect) {\n results.push(intersect);\n }\n return featureCollection(results);\n }\n // Handles complex GeoJSON Geometries\n var tree = rbush();\n tree.load(lineSegment(line2));\n featureEach(lineSegment(line1), function (segment) {\n featureEach(tree.search(segment), function (match) {\n var intersect = intersects(segment, match);\n if (intersect) {\n // prevent duplicate points https://github.com/Turfjs/turf/issues/688\n var key = getCoords(intersect).join(\",\");\n if (!unique[key]) {\n unique[key] = true;\n results.push(intersect);\n }\n }\n });\n });\n return featureCollection(results);\n}\n/**\n * Find a point that intersects LineStrings with two coordinates each\n *\n * @private\n * @param {Feature} line1 GeoJSON LineString (Must only contain 2 coordinates)\n * @param {Feature} line2 GeoJSON LineString (Must only contain 2 coordinates)\n * @returns {Feature} intersecting GeoJSON Point\n */\nfunction intersects(line1, line2) {\n var coords1 = getCoords(line1);\n var coords2 = getCoords(line2);\n if (coords1.length !== 2) {\n throw new Error(\" line1 must only contain 2 coordinates\");\n }\n if (coords2.length !== 2) {\n throw new Error(\" line2 must only contain 2 coordinates\");\n }\n var x1 = coords1[0][0];\n var y1 = coords1[0][1];\n var x2 = coords1[1][0];\n var y2 = coords1[1][1];\n var x3 = coords2[0][0];\n var y3 = coords2[0][1];\n var x4 = coords2[1][0];\n var y4 = coords2[1][1];\n var denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);\n var numeA = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);\n var numeB = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);\n if (denom === 0) {\n if (numeA === 0 && numeB === 0) {\n return null;\n }\n return null;\n }\n var uA = numeA / denom;\n var uB = numeB / denom;\n if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {\n var x = x1 + uA * (x2 - x1);\n var y = y1 + uA * (y2 - y1);\n return point([x, y]);\n }\n return null;\n}\nexport default lineIntersect;\n","import rbush from 'geojson-rbush';\nimport square from '@turf/square';\nimport bbox from '@turf/bbox';\nimport truncate from '@turf/truncate';\nimport lineSegment from '@turf/line-segment';\nimport lineIntersect from '@turf/line-intersect';\nimport nearestPointOnLine from '@turf/nearest-point-on-line';\nimport { getType, getCoords, getCoord } from '@turf/invariant';\nimport { flattenEach, featureEach, featureReduce } from '@turf/meta';\nimport { featureCollection, lineString } from '@turf/helpers';\n\n/**\n * Split a LineString by another GeoJSON Feature.\n *\n * @name lineSplit\n * @param {Feature} line LineString Feature to split\n * @param {Feature} splitter Feature used to split line\n * @returns {FeatureCollection} Split LineStrings\n * @example\n * var line = turf.lineString([[120, -25], [145, -25]]);\n * var splitter = turf.lineString([[130, -15], [130, -35]]);\n *\n * var split = turf.lineSplit(line, splitter);\n *\n * //addToMap\n * var addToMap = [line, splitter]\n */\nfunction lineSplit(line, splitter) {\n if (!line) throw new Error(\"line is required\");\n if (!splitter) throw new Error(\"splitter is required\");\n\n var lineType = getType(line);\n var splitterType = getType(splitter);\n\n if (lineType !== \"LineString\") throw new Error(\"line must be LineString\");\n if (splitterType === \"FeatureCollection\")\n throw new Error(\"splitter cannot be a FeatureCollection\");\n if (splitterType === \"GeometryCollection\")\n throw new Error(\"splitter cannot be a GeometryCollection\");\n\n // remove excessive decimals from splitter\n // to avoid possible approximation issues in rbush\n var truncatedSplitter = truncate(splitter, { precision: 7 });\n\n switch (splitterType) {\n case \"Point\":\n return splitLineWithPoint(line, truncatedSplitter);\n case \"MultiPoint\":\n return splitLineWithPoints(line, truncatedSplitter);\n case \"LineString\":\n case \"MultiLineString\":\n case \"Polygon\":\n case \"MultiPolygon\":\n return splitLineWithPoints(line, lineIntersect(line, truncatedSplitter));\n }\n}\n\n/**\n * Split LineString with MultiPoint\n *\n * @private\n * @param {Feature} line LineString\n * @param {FeatureCollection} splitter Point\n * @returns {FeatureCollection} split LineStrings\n */\nfunction splitLineWithPoints(line, splitter) {\n var results = [];\n var tree = rbush();\n\n flattenEach(splitter, function (point) {\n // Add index/id to features (needed for filter)\n results.forEach(function (feature, index) {\n feature.id = index;\n });\n // First Point - doesn't need to handle any previous line results\n if (!results.length) {\n results = splitLineWithPoint(line, point).features;\n\n // Add Square BBox to each feature for GeoJSON-RBush\n results.forEach(function (feature) {\n if (!feature.bbox) feature.bbox = square(bbox(feature));\n });\n tree.load(featureCollection(results));\n // Split with remaining points - lines might needed to be split multiple times\n } else {\n // Find all lines that are within the splitter's bbox\n var search = tree.search(point);\n\n if (search.features.length) {\n // RBush might return multiple lines - only process the closest line to splitter\n var closestLine = findClosestFeature(point, search);\n\n // Remove closest line from results since this will be split into two lines\n // This removes any duplicates inside the results & index\n results = results.filter(function (feature) {\n return feature.id !== closestLine.id;\n });\n tree.remove(closestLine);\n\n // Append the two newly split lines into the results\n featureEach(splitLineWithPoint(closestLine, point), function (line) {\n results.push(line);\n tree.insert(line);\n });\n }\n }\n });\n return featureCollection(results);\n}\n\n/**\n * Split LineString with Point\n *\n * @private\n * @param {Feature} line LineString\n * @param {Feature} splitter Point\n * @returns {FeatureCollection} split LineStrings\n */\nfunction splitLineWithPoint(line, splitter) {\n var results = [];\n\n // handle endpoints\n var startPoint = getCoords(line)[0];\n var endPoint = getCoords(line)[line.geometry.coordinates.length - 1];\n if (\n pointsEquals(startPoint, getCoord(splitter)) ||\n pointsEquals(endPoint, getCoord(splitter))\n )\n return featureCollection([line]);\n\n // Create spatial index\n var tree = rbush();\n var segments = lineSegment(line);\n tree.load(segments);\n\n // Find all segments that are within bbox of splitter\n var search = tree.search(splitter);\n\n // Return itself if point is not within spatial index\n if (!search.features.length) return featureCollection([line]);\n\n // RBush might return multiple lines - only process the closest line to splitter\n var closestSegment = findClosestFeature(splitter, search);\n\n // Initial value is the first point of the first segments (beginning of line)\n var initialValue = [startPoint];\n var lastCoords = featureReduce(\n segments,\n function (previous, current, index) {\n var currentCoords = getCoords(current)[1];\n var splitterCoords = getCoord(splitter);\n\n // Location where segment intersects with line\n if (index === closestSegment.id) {\n previous.push(splitterCoords);\n results.push(lineString(previous));\n // Don't duplicate splitter coordinate (Issue #688)\n if (pointsEquals(splitterCoords, currentCoords))\n return [splitterCoords];\n return [splitterCoords, currentCoords];\n\n // Keep iterating over coords until finished or intersection is found\n } else {\n previous.push(currentCoords);\n return previous;\n }\n },\n initialValue\n );\n // Append last line to final split results\n if (lastCoords.length > 1) {\n results.push(lineString(lastCoords));\n }\n return featureCollection(results);\n}\n\n/**\n * Find Closest Feature\n *\n * @private\n * @param {Feature} point Feature must be closest to this point\n * @param {FeatureCollection} lines Collection of Features\n * @returns {Feature} closest LineString\n */\nfunction findClosestFeature(point, lines) {\n if (!lines.features.length) throw new Error(\"lines must contain features\");\n // Filter to one segment that is the closest to the line\n if (lines.features.length === 1) return lines.features[0];\n\n var closestFeature;\n var closestDistance = Infinity;\n featureEach(lines, function (segment) {\n var pt = nearestPointOnLine(segment, point);\n var dist = pt.properties.dist;\n if (dist < closestDistance) {\n closestFeature = segment;\n closestDistance = dist;\n }\n });\n return closestFeature;\n}\n\n/**\n * Compares two points and returns if they are equals\n *\n * @private\n * @param {Array} pt1 point\n * @param {Array} pt2 point\n * @returns {boolean} true if they are equals\n */\nfunction pointsEquals(pt1, pt2) {\n return pt1[0] === pt2[0] && pt1[1] === pt2[1];\n}\n\nexport default lineSplit;\n","import { getCoord } from \"@turf/invariant\";\nimport { radiansToLength, degreesToRadians, } from \"@turf/helpers\";\n//http://en.wikipedia.org/wiki/Haversine_formula\n//http://www.movable-type.co.uk/scripts/latlong.html\n/**\n * Calculates the distance between two {@link Point|points} in degrees, radians, miles, or kilometers.\n * This uses the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula) to account for global curvature.\n *\n * @name distance\n * @param {Coord | Point} from origin point or coordinate\n * @param {Coord | Point} to destination point or coordinate\n * @param {Object} [options={}] Optional parameters\n * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers\n * @returns {number} distance between the two points\n * @example\n * var from = turf.point([-75.343, 39.984]);\n * var to = turf.point([-75.534, 39.123]);\n * var options = {units: 'miles'};\n *\n * var distance = turf.distance(from, to, options);\n *\n * //addToMap\n * var addToMap = [from, to];\n * from.properties.distance = distance;\n * to.properties.distance = distance;\n */\nfunction distance(from, to, options) {\n if (options === void 0) { options = {}; }\n var coordinates1 = getCoord(from);\n var coordinates2 = getCoord(to);\n var dLat = degreesToRadians(coordinates2[1] - coordinates1[1]);\n var dLon = degreesToRadians(coordinates2[0] - coordinates1[0]);\n var lat1 = degreesToRadians(coordinates1[1]);\n var lat2 = degreesToRadians(coordinates2[1]);\n var a = Math.pow(Math.sin(dLat / 2), 2) +\n Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2);\n return radiansToLength(2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)), options.units);\n}\nexport default distance;\n","import distance from '@turf/distance';\n\n/**\n * Takes a bounding box and calculates the minimum square bounding box that\n * would contain the input.\n *\n * @name square\n * @param {BBox} bbox extent in [west, south, east, north] order\n * @returns {BBox} a square surrounding `bbox`\n * @example\n * var bbox = [-20, -20, -15, 0];\n * var squared = turf.square(bbox);\n *\n * //addToMap\n * var addToMap = [turf.bboxPolygon(bbox), turf.bboxPolygon(squared)]\n */\nfunction square(bbox) {\n var west = bbox[0];\n var south = bbox[1];\n var east = bbox[2];\n var north = bbox[3];\n\n var horizontalDistance = distance(bbox.slice(0, 2), [east, south]);\n var verticalDistance = distance(bbox.slice(0, 2), [west, north]);\n if (horizontalDistance >= verticalDistance) {\n var verticalMidpoint = (south + north) / 2;\n return [\n west,\n verticalMidpoint - (east - west) / 2,\n east,\n verticalMidpoint + (east - west) / 2,\n ];\n } else {\n var horizontalMidpoint = (west + east) / 2;\n return [\n horizontalMidpoint - (north - south) / 2,\n south,\n horizontalMidpoint + (north - south) / 2,\n north,\n ];\n }\n}\n\nexport default square;\n","import { coordEach } from \"@turf/meta\";\n/**\n * Takes a set of features, calculates the bbox of all input features, and returns a bounding box.\n *\n * @name bbox\n * @param {GeoJSON} geojson any GeoJSON object\n * @returns {BBox} bbox extent in [minX, minY, maxX, maxY] order\n * @example\n * var line = turf.lineString([[-74, 40], [-78, 42], [-82, 35]]);\n * var bbox = turf.bbox(line);\n * var bboxPolygon = turf.bboxPolygon(bbox);\n *\n * //addToMap\n * var addToMap = [line, bboxPolygon]\n */\nfunction bbox(geojson) {\n var result = [Infinity, Infinity, -Infinity, -Infinity];\n coordEach(geojson, function (coord) {\n if (result[0] > coord[0]) {\n result[0] = coord[0];\n }\n if (result[1] > coord[1]) {\n result[1] = coord[1];\n }\n if (result[2] < coord[0]) {\n result[2] = coord[0];\n }\n if (result[3] < coord[1]) {\n result[3] = coord[1];\n }\n });\n return result;\n}\nbbox[\"default\"] = bbox;\nexport default bbox;\n","import { coordEach } from \"@turf/meta\";\n/**\n * Takes a GeoJSON Feature or FeatureCollection and truncates the precision of the geometry.\n *\n * @name truncate\n * @param {GeoJSON} geojson any GeoJSON Feature, FeatureCollection, Geometry or GeometryCollection.\n * @param {Object} [options={}] Optional parameters\n * @param {number} [options.precision=6] coordinate decimal precision\n * @param {number} [options.coordinates=3] maximum number of coordinates (primarly used to remove z coordinates)\n * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)\n * @returns {GeoJSON} layer with truncated geometry\n * @example\n * var point = turf.point([\n * 70.46923055566859,\n * 58.11088890802906,\n * 1508\n * ]);\n * var options = {precision: 3, coordinates: 2};\n * var truncated = turf.truncate(point, options);\n * //=truncated.geometry.coordinates => [70.469, 58.111]\n *\n * //addToMap\n * var addToMap = [truncated];\n */\nfunction truncate(geojson, options) {\n if (options === void 0) { options = {}; }\n // Optional parameters\n var precision = options.precision;\n var coordinates = options.coordinates;\n var mutate = options.mutate;\n // default params\n precision =\n precision === undefined || precision === null || isNaN(precision)\n ? 6\n : precision;\n coordinates =\n coordinates === undefined || coordinates === null || isNaN(coordinates)\n ? 3\n : coordinates;\n // validation\n if (!geojson)\n throw new Error(\" is required\");\n if (typeof precision !== \"number\")\n throw new Error(\" must be a number\");\n if (typeof coordinates !== \"number\")\n throw new Error(\" must be a number\");\n // prevent input mutation\n if (mutate === false || mutate === undefined)\n geojson = JSON.parse(JSON.stringify(geojson));\n var factor = Math.pow(10, precision);\n // Truncate Coordinates\n coordEach(geojson, function (coords) {\n truncateCoords(coords, factor, coordinates);\n });\n return geojson;\n}\n/**\n * Truncate Coordinates - Mutates coordinates in place\n *\n * @private\n * @param {Array} coords Geometry Coordinates\n * @param {number} factor rounding factor for coordinate decimal precision\n * @param {number} coordinates maximum number of coordinates (primarly used to remove z coordinates)\n * @returns {Array} mutated coordinates\n */\nfunction truncateCoords(coords, factor, coordinates) {\n // Remove extra coordinates (usually elevation coordinates and more)\n if (coords.length > coordinates)\n coords.splice(coordinates, coords.length);\n // Truncate coordinate decimals\n for (var i = 0; i < coords.length; i++) {\n coords[i] = Math.round(coords[i] * factor) / factor;\n }\n return coords;\n}\nexport default truncate;\n","import { degreesToRadians, radiansToDegrees } from \"@turf/helpers\";\nimport { getCoord } from \"@turf/invariant\";\n// http://en.wikipedia.org/wiki/Haversine_formula\n// http://www.movable-type.co.uk/scripts/latlong.html\n/**\n * Takes two {@link Point|points} and finds the geographic bearing between them,\n * i.e. the angle measured in degrees from the north line (0 degrees)\n *\n * @name bearing\n * @param {Coord} start starting Point\n * @param {Coord} end ending Point\n * @param {Object} [options={}] Optional parameters\n * @param {boolean} [options.final=false] calculates the final bearing if true\n * @returns {number} bearing in decimal degrees, between -180 and 180 degrees (positive clockwise)\n * @example\n * var point1 = turf.point([-75.343, 39.984]);\n * var point2 = turf.point([-75.534, 39.123]);\n *\n * var bearing = turf.bearing(point1, point2);\n *\n * //addToMap\n * var addToMap = [point1, point2]\n * point1.properties['marker-color'] = '#f00'\n * point2.properties['marker-color'] = '#0f0'\n * point1.properties.bearing = bearing\n */\nexport default function bearing(start, end, options) {\n if (options === void 0) { options = {}; }\n // Reverse calculation\n if (options.final === true) {\n return calculateFinalBearing(start, end);\n }\n var coordinates1 = getCoord(start);\n var coordinates2 = getCoord(end);\n var lon1 = degreesToRadians(coordinates1[0]);\n var lon2 = degreesToRadians(coordinates2[0]);\n var lat1 = degreesToRadians(coordinates1[1]);\n var lat2 = degreesToRadians(coordinates2[1]);\n var a = Math.sin(lon2 - lon1) * Math.cos(lat2);\n var b = Math.cos(lat1) * Math.sin(lat2) -\n Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);\n return radiansToDegrees(Math.atan2(a, b));\n}\n/**\n * Calculates Final Bearing\n *\n * @private\n * @param {Coord} start starting Point\n * @param {Coord} end ending Point\n * @returns {number} bearing\n */\nfunction calculateFinalBearing(start, end) {\n // Swap start & end\n var bear = bearing(end, start);\n bear = (bear + 180) % 360;\n return bear;\n}\n","// http://en.wikipedia.org/wiki/Haversine_formula\n// http://www.movable-type.co.uk/scripts/latlong.html\nimport { degreesToRadians, lengthToRadians, point, radiansToDegrees, } from \"@turf/helpers\";\nimport { getCoord } from \"@turf/invariant\";\n/**\n * Takes a {@link Point} and calculates the location of a destination point given a distance in\n * degrees, radians, miles, or kilometers; and bearing in degrees.\n * This uses the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula) to account for global curvature.\n *\n * @name destination\n * @param {Coord} origin starting point\n * @param {number} distance distance from the origin point\n * @param {number} bearing ranging from -180 to 180\n * @param {Object} [options={}] Optional parameters\n * @param {string} [options.units='kilometers'] miles, kilometers, degrees, or radians\n * @param {Object} [options.properties={}] Translate properties to Point\n * @returns {Feature} destination point\n * @example\n * var point = turf.point([-75.343, 39.984]);\n * var distance = 50;\n * var bearing = 90;\n * var options = {units: 'miles'};\n *\n * var destination = turf.destination(point, distance, bearing, options);\n *\n * //addToMap\n * var addToMap = [point, destination]\n * destination.properties['marker-color'] = '#f00';\n * point.properties['marker-color'] = '#0f0';\n */\nexport default function destination(origin, distance, bearing, options) {\n if (options === void 0) { options = {}; }\n // Handle input\n var coordinates1 = getCoord(origin);\n var longitude1 = degreesToRadians(coordinates1[0]);\n var latitude1 = degreesToRadians(coordinates1[1]);\n var bearingRad = degreesToRadians(bearing);\n var radians = lengthToRadians(distance, options.units);\n // Main\n var latitude2 = Math.asin(Math.sin(latitude1) * Math.cos(radians) +\n Math.cos(latitude1) * Math.sin(radians) * Math.cos(bearingRad));\n var longitude2 = longitude1 +\n Math.atan2(Math.sin(bearingRad) * Math.sin(radians) * Math.cos(latitude1), Math.cos(radians) - Math.sin(latitude1) * Math.sin(latitude2));\n var lng = radiansToDegrees(longitude2);\n var lat = radiansToDegrees(latitude2);\n return point([lng, lat], options.properties);\n}\n","import bearing from \"@turf/bearing\";\nimport distance from \"@turf/distance\";\nimport destination from \"@turf/destination\";\nimport lineIntersects from \"@turf/line-intersect\";\nimport { flattenEach } from \"@turf/meta\";\nimport { point, lineString, } from \"@turf/helpers\";\nimport { getCoords } from \"@turf/invariant\";\n/**\n * Takes a {@link Point} and a {@link LineString} and calculates the closest Point on the (Multi)LineString.\n *\n * @name nearestPointOnLine\n * @param {Geometry|Feature} lines lines to snap to\n * @param {Geometry|Feature|number[]} pt point to snap from\n * @param {Object} [options={}] Optional parameters\n * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers\n * @returns {Feature} closest point on the `line` to `point`. The properties object will contain three values: `index`: closest point was found on nth line part, `dist`: distance between pt and the closest point, `location`: distance along the line between start and the closest point.\n * @example\n * var line = turf.lineString([\n * [-77.031669, 38.878605],\n * [-77.029609, 38.881946],\n * [-77.020339, 38.884084],\n * [-77.025661, 38.885821],\n * [-77.021884, 38.889563],\n * [-77.019824, 38.892368]\n * ]);\n * var pt = turf.point([-77.037076, 38.884017]);\n *\n * var snapped = turf.nearestPointOnLine(line, pt, {units: 'miles'});\n *\n * //addToMap\n * var addToMap = [line, pt, snapped];\n * snapped.properties['marker-color'] = '#00f';\n */\nfunction nearestPointOnLine(lines, pt, options) {\n if (options === void 0) { options = {}; }\n var closestPt = point([Infinity, Infinity], {\n dist: Infinity,\n });\n var length = 0.0;\n flattenEach(lines, function (line) {\n var coords = getCoords(line);\n for (var i = 0; i < coords.length - 1; i++) {\n //start\n var start = point(coords[i]);\n start.properties.dist = distance(pt, start, options);\n //stop\n var stop_1 = point(coords[i + 1]);\n stop_1.properties.dist = distance(pt, stop_1, options);\n // sectionLength\n var sectionLength = distance(start, stop_1, options);\n //perpendicular\n var heightDistance = Math.max(start.properties.dist, stop_1.properties.dist);\n var direction = bearing(start, stop_1);\n var perpendicularPt1 = destination(pt, heightDistance, direction + 90, options);\n var perpendicularPt2 = destination(pt, heightDistance, direction - 90, options);\n var intersect = lineIntersects(lineString([\n perpendicularPt1.geometry.coordinates,\n perpendicularPt2.geometry.coordinates,\n ]), lineString([start.geometry.coordinates, stop_1.geometry.coordinates]));\n var intersectPt = null;\n if (intersect.features.length > 0) {\n intersectPt = intersect.features[0];\n intersectPt.properties.dist = distance(pt, intersectPt, options);\n intersectPt.properties.location =\n length + distance(start, intersectPt, options);\n }\n if (start.properties.dist < closestPt.properties.dist) {\n closestPt = start;\n closestPt.properties.index = i;\n closestPt.properties.location = length;\n }\n if (stop_1.properties.dist < closestPt.properties.dist) {\n closestPt = stop_1;\n closestPt.properties.index = i + 1;\n closestPt.properties.location = length + sectionLength;\n }\n if (intersectPt &&\n intersectPt.properties.dist < closestPt.properties.dist) {\n closestPt = intersectPt;\n closestPt.properties.index = i;\n }\n // update length\n length += sectionLength;\n }\n });\n return closestPt;\n}\nexport default nearestPointOnLine;\n","import { getCoord, getGeom } from \"@turf/invariant\";\n// http://en.wikipedia.org/wiki/Even%E2%80%93odd_rule\n// modified from: https://github.com/substack/point-in-polygon/blob/master/index.js\n// which was modified from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html\n/**\n * Takes a {@link Point} and a {@link Polygon} or {@link MultiPolygon} and determines if the point\n * resides inside the polygon. The polygon can be convex or concave. The function accounts for holes.\n *\n * @name booleanPointInPolygon\n * @param {Coord} point input point\n * @param {Feature} polygon input polygon or multipolygon\n * @param {Object} [options={}] Optional parameters\n * @param {boolean} [options.ignoreBoundary=false] True if polygon boundary should be ignored when determining if\n * the point is inside the polygon otherwise false.\n * @returns {boolean} `true` if the Point is inside the Polygon; `false` if the Point is not inside the Polygon\n * @example\n * var pt = turf.point([-77, 44]);\n * var poly = turf.polygon([[\n * [-81, 41],\n * [-81, 47],\n * [-72, 47],\n * [-72, 41],\n * [-81, 41]\n * ]]);\n *\n * turf.booleanPointInPolygon(pt, poly);\n * //= true\n */\nexport default function booleanPointInPolygon(point, polygon, options) {\n if (options === void 0) { options = {}; }\n // validation\n if (!point) {\n throw new Error(\"point is required\");\n }\n if (!polygon) {\n throw new Error(\"polygon is required\");\n }\n var pt = getCoord(point);\n var geom = getGeom(polygon);\n var type = geom.type;\n var bbox = polygon.bbox;\n var polys = geom.coordinates;\n // Quick elimination if point is not inside bbox\n if (bbox && inBBox(pt, bbox) === false) {\n return false;\n }\n // normalize to multipolygon\n if (type === \"Polygon\") {\n polys = [polys];\n }\n var insidePoly = false;\n for (var i = 0; i < polys.length && !insidePoly; i++) {\n // check if it is in the outer ring first\n if (inRing(pt, polys[i][0], options.ignoreBoundary)) {\n var inHole = false;\n var k = 1;\n // check for the point in any of the holes\n while (k < polys[i].length && !inHole) {\n if (inRing(pt, polys[i][k], !options.ignoreBoundary)) {\n inHole = true;\n }\n k++;\n }\n if (!inHole) {\n insidePoly = true;\n }\n }\n }\n return insidePoly;\n}\n/**\n * inRing\n *\n * @private\n * @param {Array} pt [x,y]\n * @param {Array>} ring [[x,y], [x,y],..]\n * @param {boolean} ignoreBoundary ignoreBoundary\n * @returns {boolean} inRing\n */\nfunction inRing(pt, ring, ignoreBoundary) {\n var isInside = false;\n if (ring[0][0] === ring[ring.length - 1][0] &&\n ring[0][1] === ring[ring.length - 1][1]) {\n ring = ring.slice(0, ring.length - 1);\n }\n for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n var xi = ring[i][0];\n var yi = ring[i][1];\n var xj = ring[j][0];\n var yj = ring[j][1];\n var onBoundary = pt[1] * (xi - xj) + yi * (xj - pt[0]) + yj * (pt[0] - xi) === 0 &&\n (xi - pt[0]) * (xj - pt[0]) <= 0 &&\n (yi - pt[1]) * (yj - pt[1]) <= 0;\n if (onBoundary) {\n return !ignoreBoundary;\n }\n var intersect = yi > pt[1] !== yj > pt[1] &&\n pt[0] < ((xj - xi) * (pt[1] - yi)) / (yj - yi) + xi;\n if (intersect) {\n isInside = !isInside;\n }\n }\n return isInside;\n}\n/**\n * inBBox\n *\n * @private\n * @param {Position} pt point [x,y]\n * @param {BBox} bbox BBox [west, south, east, north]\n * @returns {boolean} true/false if point is inside BBox\n */\nfunction inBBox(pt, bbox) {\n return (bbox[0] <= pt[0] && bbox[1] <= pt[1] && bbox[2] >= pt[0] && bbox[3] >= pt[1]);\n}\n","import { getCoord, getCoords } from \"@turf/invariant\";\n/**\n * Returns true if a point is on a line. Accepts a optional parameter to ignore the\n * start and end vertices of the linestring.\n *\n * @name booleanPointOnLine\n * @param {Coord} pt GeoJSON Point\n * @param {Feature} line GeoJSON LineString\n * @param {Object} [options={}] Optional parameters\n * @param {boolean} [options.ignoreEndVertices=false] whether to ignore the start and end vertices.\n * @param {number} [options.epsilon] Fractional number to compare with the cross product result. Useful for dealing with floating points such as lng/lat points\n * @returns {boolean} true/false\n * @example\n * var pt = turf.point([0, 0]);\n * var line = turf.lineString([[-1, -1],[1, 1],[1.5, 2.2]]);\n * var isPointOnLine = turf.booleanPointOnLine(pt, line);\n * //=true\n */\nfunction booleanPointOnLine(pt, line, options) {\n if (options === void 0) { options = {}; }\n // Normalize inputs\n var ptCoords = getCoord(pt);\n var lineCoords = getCoords(line);\n // Main\n for (var i = 0; i < lineCoords.length - 1; i++) {\n var ignoreBoundary = false;\n if (options.ignoreEndVertices) {\n if (i === 0) {\n ignoreBoundary = \"start\";\n }\n if (i === lineCoords.length - 2) {\n ignoreBoundary = \"end\";\n }\n if (i === 0 && i + 1 === lineCoords.length - 1) {\n ignoreBoundary = \"both\";\n }\n }\n if (isPointOnLineSegment(lineCoords[i], lineCoords[i + 1], ptCoords, ignoreBoundary, typeof options.epsilon === \"undefined\" ? null : options.epsilon)) {\n return true;\n }\n }\n return false;\n}\n// See http://stackoverflow.com/a/4833823/1979085\n// See https://stackoverflow.com/a/328122/1048847\n/**\n * @private\n * @param {Position} lineSegmentStart coord pair of start of line\n * @param {Position} lineSegmentEnd coord pair of end of line\n * @param {Position} pt coord pair of point to check\n * @param {boolean|string} excludeBoundary whether the point is allowed to fall on the line ends.\n * @param {number} epsilon Fractional number to compare with the cross product result. Useful for dealing with floating points such as lng/lat points\n * If true which end to ignore.\n * @returns {boolean} true/false\n */\nfunction isPointOnLineSegment(lineSegmentStart, lineSegmentEnd, pt, excludeBoundary, epsilon) {\n var x = pt[0];\n var y = pt[1];\n var x1 = lineSegmentStart[0];\n var y1 = lineSegmentStart[1];\n var x2 = lineSegmentEnd[0];\n var y2 = lineSegmentEnd[1];\n var dxc = pt[0] - x1;\n var dyc = pt[1] - y1;\n var dxl = x2 - x1;\n var dyl = y2 - y1;\n var cross = dxc * dyl - dyc * dxl;\n if (epsilon !== null) {\n if (Math.abs(cross) > epsilon) {\n return false;\n }\n }\n else if (cross !== 0) {\n return false;\n }\n if (!excludeBoundary) {\n if (Math.abs(dxl) >= Math.abs(dyl)) {\n return dxl > 0 ? x1 <= x && x <= x2 : x2 <= x && x <= x1;\n }\n return dyl > 0 ? y1 <= y && y <= y2 : y2 <= y && y <= y1;\n }\n else if (excludeBoundary === \"start\") {\n if (Math.abs(dxl) >= Math.abs(dyl)) {\n return dxl > 0 ? x1 < x && x <= x2 : x2 <= x && x < x1;\n }\n return dyl > 0 ? y1 < y && y <= y2 : y2 <= y && y < y1;\n }\n else if (excludeBoundary === \"end\") {\n if (Math.abs(dxl) >= Math.abs(dyl)) {\n return dxl > 0 ? x1 <= x && x < x2 : x2 < x && x <= x1;\n }\n return dyl > 0 ? y1 <= y && y < y2 : y2 < y && y <= y1;\n }\n else if (excludeBoundary === \"both\") {\n if (Math.abs(dxl) >= Math.abs(dyl)) {\n return dxl > 0 ? x1 < x && x < x2 : x2 < x && x < x1;\n }\n return dyl > 0 ? y1 < y && y < y2 : y2 < y && y < y1;\n }\n return false;\n}\nexport default booleanPointOnLine;\n","import calcBbox from \"@turf/bbox\";\nimport booleanPointInPolygon from \"@turf/boolean-point-in-polygon\";\nimport isPointOnLine from \"@turf/boolean-point-on-line\";\nimport { getGeom } from \"@turf/invariant\";\n/**\n * Boolean-contains returns True if the second geometry is completely contained by the first geometry.\n * The interiors of both geometries must intersect and, the interior and boundary of the secondary (geometry b)\n * must not intersect the exterior of the primary (geometry a).\n * Boolean-contains returns the exact opposite result of the `@turf/boolean-within`.\n *\n * @name booleanContains\n * @param {Geometry|Feature} feature1 GeoJSON Feature or Geometry\n * @param {Geometry|Feature} feature2 GeoJSON Feature or Geometry\n * @returns {boolean} true/false\n * @example\n * var line = turf.lineString([[1, 1], [1, 2], [1, 3], [1, 4]]);\n * var point = turf.point([1, 2]);\n *\n * turf.booleanContains(line, point);\n * //=true\n */\nexport default function booleanContains(feature1, feature2) {\n var geom1 = getGeom(feature1);\n var geom2 = getGeom(feature2);\n var type1 = geom1.type;\n var type2 = geom2.type;\n var coords1 = geom1.coordinates;\n var coords2 = geom2.coordinates;\n switch (type1) {\n case \"Point\":\n switch (type2) {\n case \"Point\":\n return compareCoords(coords1, coords2);\n default:\n throw new Error(\"feature2 \" + type2 + \" geometry not supported\");\n }\n case \"MultiPoint\":\n switch (type2) {\n case \"Point\":\n return isPointInMultiPoint(geom1, geom2);\n case \"MultiPoint\":\n return isMultiPointInMultiPoint(geom1, geom2);\n default:\n throw new Error(\"feature2 \" + type2 + \" geometry not supported\");\n }\n case \"LineString\":\n switch (type2) {\n case \"Point\":\n return isPointOnLine(geom2, geom1, { ignoreEndVertices: true });\n case \"LineString\":\n return isLineOnLine(geom1, geom2);\n case \"MultiPoint\":\n return isMultiPointOnLine(geom1, geom2);\n default:\n throw new Error(\"feature2 \" + type2 + \" geometry not supported\");\n }\n case \"Polygon\":\n switch (type2) {\n case \"Point\":\n return booleanPointInPolygon(geom2, geom1, { ignoreBoundary: true });\n case \"LineString\":\n return isLineInPoly(geom1, geom2);\n case \"Polygon\":\n return isPolyInPoly(geom1, geom2);\n case \"MultiPoint\":\n return isMultiPointInPoly(geom1, geom2);\n default:\n throw new Error(\"feature2 \" + type2 + \" geometry not supported\");\n }\n default:\n throw new Error(\"feature1 \" + type1 + \" geometry not supported\");\n }\n}\nexport function isPointInMultiPoint(multiPoint, pt) {\n var i;\n var output = false;\n for (i = 0; i < multiPoint.coordinates.length; i++) {\n if (compareCoords(multiPoint.coordinates[i], pt.coordinates)) {\n output = true;\n break;\n }\n }\n return output;\n}\nexport function isMultiPointInMultiPoint(multiPoint1, multiPoint2) {\n for (var _i = 0, _a = multiPoint2.coordinates; _i < _a.length; _i++) {\n var coord2 = _a[_i];\n var matchFound = false;\n for (var _b = 0, _c = multiPoint1.coordinates; _b < _c.length; _b++) {\n var coord1 = _c[_b];\n if (compareCoords(coord2, coord1)) {\n matchFound = true;\n break;\n }\n }\n if (!matchFound) {\n return false;\n }\n }\n return true;\n}\nexport function isMultiPointOnLine(lineString, multiPoint) {\n var haveFoundInteriorPoint = false;\n for (var _i = 0, _a = multiPoint.coordinates; _i < _a.length; _i++) {\n var coord = _a[_i];\n if (isPointOnLine(coord, lineString, { ignoreEndVertices: true })) {\n haveFoundInteriorPoint = true;\n }\n if (!isPointOnLine(coord, lineString)) {\n return false;\n }\n }\n if (haveFoundInteriorPoint) {\n return true;\n }\n return false;\n}\nexport function isMultiPointInPoly(polygon, multiPoint) {\n for (var _i = 0, _a = multiPoint.coordinates; _i < _a.length; _i++) {\n var coord = _a[_i];\n if (!booleanPointInPolygon(coord, polygon, { ignoreBoundary: true })) {\n return false;\n }\n }\n return true;\n}\nexport function isLineOnLine(lineString1, lineString2) {\n var haveFoundInteriorPoint = false;\n for (var _i = 0, _a = lineString2.coordinates; _i < _a.length; _i++) {\n var coords = _a[_i];\n if (isPointOnLine({ type: \"Point\", coordinates: coords }, lineString1, {\n ignoreEndVertices: true,\n })) {\n haveFoundInteriorPoint = true;\n }\n if (!isPointOnLine({ type: \"Point\", coordinates: coords }, lineString1, {\n ignoreEndVertices: false,\n })) {\n return false;\n }\n }\n return haveFoundInteriorPoint;\n}\nexport function isLineInPoly(polygon, linestring) {\n var output = false;\n var i = 0;\n var polyBbox = calcBbox(polygon);\n var lineBbox = calcBbox(linestring);\n if (!doBBoxOverlap(polyBbox, lineBbox)) {\n return false;\n }\n for (i; i < linestring.coordinates.length - 1; i++) {\n var midPoint = getMidpoint(linestring.coordinates[i], linestring.coordinates[i + 1]);\n if (booleanPointInPolygon({ type: \"Point\", coordinates: midPoint }, polygon, {\n ignoreBoundary: true,\n })) {\n output = true;\n break;\n }\n }\n return output;\n}\n/**\n * Is Polygon2 in Polygon1\n * Only takes into account outer rings\n *\n * @private\n * @param {Geometry|Feature} feature1 Polygon1\n * @param {Geometry|Feature} feature2 Polygon2\n * @returns {boolean} true/false\n */\nexport function isPolyInPoly(feature1, feature2) {\n // Handle Nulls\n if (feature1.type === \"Feature\" && feature1.geometry === null) {\n return false;\n }\n if (feature2.type === \"Feature\" && feature2.geometry === null) {\n return false;\n }\n var poly1Bbox = calcBbox(feature1);\n var poly2Bbox = calcBbox(feature2);\n if (!doBBoxOverlap(poly1Bbox, poly2Bbox)) {\n return false;\n }\n var coords = getGeom(feature2).coordinates;\n for (var _i = 0, coords_1 = coords; _i < coords_1.length; _i++) {\n var ring = coords_1[_i];\n for (var _a = 0, ring_1 = ring; _a < ring_1.length; _a++) {\n var coord = ring_1[_a];\n if (!booleanPointInPolygon(coord, feature1)) {\n return false;\n }\n }\n }\n return true;\n}\nexport function doBBoxOverlap(bbox1, bbox2) {\n if (bbox1[0] > bbox2[0]) {\n return false;\n }\n if (bbox1[2] < bbox2[2]) {\n return false;\n }\n if (bbox1[1] > bbox2[1]) {\n return false;\n }\n if (bbox1[3] < bbox2[3]) {\n return false;\n }\n return true;\n}\n/**\n * compareCoords\n *\n * @private\n * @param {Position} pair1 point [x,y]\n * @param {Position} pair2 point [x,y]\n * @returns {boolean} true/false if coord pairs match\n */\nexport function compareCoords(pair1, pair2) {\n return pair1[0] === pair2[0] && pair1[1] === pair2[1];\n}\nexport function getMidpoint(pair1, pair2) {\n return [(pair1[0] + pair2[0]) / 2, (pair1[1] + pair2[1]) / 2];\n}\n","import lineIntersect from '@turf/line-intersect';\nimport lineSplit from '@turf/line-split';\nimport booleanContains from '@turf/boolean-contains';\nimport get from 'lodash/get';\nimport Draw from './L.PM.Draw';\nimport {\n difference,\n flattenPolyline,\n groupToMultiLineString,\n intersect,\n} from '../helpers/turfHelper';\n\nDraw.Cut = Draw.Polygon.extend({\n initialize(map) {\n this._map = map;\n this._shape = 'Cut';\n this.toolbarButtonName = 'cutPolygon';\n },\n _finishShape() {\n this._editedLayers = [];\n // if self intersection is not allowed, do not finish the shape!\n if (!this.options.allowSelfIntersection) {\n // Check if polygon intersects when is completed and the line between the last and the first point is drawn\n this._handleSelfIntersection(true, this._layer.getLatLngs()[0]);\n\n if (this._doesSelfIntersect) {\n return;\n }\n }\n\n // If snap finish is required but the last marker wasn't snapped, do not finish the shape!\n if (\n this.options.requireSnapToFinish &&\n !this._hintMarker._snapped &&\n !this._isFirstLayer()\n ) {\n return;\n }\n\n // get coordinates\n const coords = this._layer.getLatLngs();\n\n // only finish the shape if there are 3 or more vertices\n if (coords.length <= 2) {\n return;\n }\n\n const polygonLayer = L.polygon(coords, this.options.pathOptions);\n // readout information about the latlngs like snapping points\n polygonLayer._latlngInfos = this._layer._latlngInfo;\n this.cut(polygonLayer);\n\n // clean up snapping states\n this._cleanupSnapping();\n\n // remove the first vertex from \"other snapping layers\"\n this._otherSnapLayers.splice(this._tempSnapLayerIndex, 1);\n delete this._tempSnapLayerIndex;\n\n this._editedLayers.forEach(({ layer, originalLayer }) => {\n // fire pm:cut on the cutted layer\n this._fireCut(originalLayer, layer, originalLayer);\n\n // fire pm:cut on the map\n this._fireCut(this._map, layer, originalLayer);\n\n // fire edit event after cut\n originalLayer.pm._fireEdit();\n });\n this._editedLayers = [];\n\n // disable drawing\n this.disable();\n if (this.options.continueDrawing) {\n this.enable();\n }\n },\n cut(layer) {\n const all = this._map._layers;\n // contains information about snapping points\n const _latlngInfos = layer._latlngInfos || [];\n\n // find all layers that intersect with `layer`, the just drawn cutting layer\n const layers = Object.keys(all)\n // convert object to array\n .map((l) => all[l])\n // only layers handled by leaflet-geoman\n .filter((l) => l.pm)\n .filter((l) => !l._pmTempLayer)\n // filter out everything that ignore leaflet-geoman\n .filter(\n (l) =>\n (!L.PM.optIn && !l.options.pmIgnore) || // if optIn is not set / true and pmIgnore is not set / true (default)\n (L.PM.optIn && l.options.pmIgnore === false) // if optIn is true and pmIgnore is false);\n )\n // only polyline instances\n .filter((l) => l instanceof L.Polyline)\n // exclude the drawn one\n .filter((l) => l !== layer)\n // layer is allowed to cut\n .filter((l) => l.pm.options.allowCutting)\n // filter out everything that ignore leaflet-geoman\n .filter((l) => {\n // TODO: after cutting nothing else can be cutted anymore until a new list is passed, because the layers don't exists anymore. Should we remove the cutted layers from the list?\n if (\n this.options.layersToCut &&\n L.Util.isArray(this.options.layersToCut) &&\n this.options.layersToCut.length > 0\n ) {\n return this.options.layersToCut.indexOf(l) > -1;\n }\n return true;\n })\n // filter out everything that ignore leaflet-geoman\n .filter((l) => !this._layerGroup.hasLayer(l))\n // only layers with intersections\n .filter((l) => {\n try {\n const lineInter =\n !!lineIntersect(layer.toGeoJSON(15), l.toGeoJSON(15)).features\n .length > 0;\n\n if (\n lineInter ||\n (l instanceof L.Polyline && !(l instanceof L.Polygon))\n ) {\n return lineInter;\n }\n return !!intersect(layer.toGeoJSON(15), l.toGeoJSON(15));\n } catch (e) {\n if (l instanceof L.Polygon) {\n /* eslint-disable-next-line no-console */\n console.error(\"You can't cut polygons with self-intersections\");\n }\n return false;\n }\n });\n\n // loop through all layers that intersect with the drawn (cutting) layer\n layers.forEach((l) => {\n let newLayer;\n if (l instanceof L.Polygon) {\n // Also for L.Rectangle\n // easiest way to clone the complete latlngs without reference\n newLayer = L.polygon(l.getLatLngs());\n const coords = newLayer.getLatLngs();\n\n // snapping points added to the layer, so borders are cutted correct\n _latlngInfos.forEach((info) => {\n if (info && info.snapInfo) {\n const { latlng } = info;\n // get closest layer ( == input layer) with the closest segment to the intersection point\n const closest = this._calcClosestLayer(latlng, [newLayer]);\n if (\n closest &&\n closest.segment &&\n closest.distance < this.options.snapDistance\n ) {\n const { segment } = closest;\n if (segment && segment.length === 2) {\n const { indexPath, parentPath, newIndex } =\n L.PM.Utils._getIndexFromSegment(coords, segment);\n // define the coordsRing that is edited\n const coordsRing =\n indexPath.length > 1 ? get(coords, parentPath) : coords;\n coordsRing.splice(newIndex, 0, latlng);\n }\n }\n }\n });\n } else {\n // L.Polyline\n newLayer = l;\n }\n\n // find layer difference\n const diff = this._cutLayer(layer, newLayer);\n\n // the resulting layer after the cut\n let resultLayer = L.geoJSON(diff, l.options);\n if (resultLayer.getLayers().length === 1) {\n [resultLayer] = resultLayer.getLayers(); // prevent that a unnecessary layergroup is created\n }\n this._setPane(resultLayer, 'layerPane');\n const resultingLayer = resultLayer.addTo(\n this._map.pm._getContainingLayer()\n );\n // give the new layer the original options\n resultingLayer.pm.enable(l.pm.options);\n resultingLayer.pm.disable();\n\n // add templayer prop so pm:remove isn't fired\n l._pmTempLayer = true;\n layer._pmTempLayer = true;\n\n // remove old layer and cutting layer\n l.remove();\n l.removeFrom(this._map.pm._getContainingLayer());\n layer.remove();\n layer.removeFrom(this._map.pm._getContainingLayer());\n\n // Remove it only if it is a layergroup. It can be only not a layergroup if a layer exists\n if (resultingLayer.getLayers && resultingLayer.getLayers().length === 0) {\n this._map.pm.removeLayer({ target: resultingLayer });\n }\n\n if (resultingLayer instanceof L.LayerGroup) {\n resultingLayer.eachLayer((_layer) => {\n this._addDrawnLayerProp(_layer);\n });\n this._addDrawnLayerProp(resultingLayer);\n } else {\n this._addDrawnLayerProp(resultingLayer);\n }\n\n if (\n this.options.layersToCut &&\n L.Util.isArray(this.options.layersToCut) &&\n this.options.layersToCut.length > 0\n ) {\n const idx = this.options.layersToCut.indexOf(l);\n if (idx > -1) {\n this.options.layersToCut.splice(idx, 1);\n }\n }\n\n this._editedLayers.push({\n layer: resultingLayer,\n originalLayer: l,\n });\n });\n },\n _cutLayer(layer, l) {\n const fg = L.geoJSON();\n let diff;\n // cut\n if (l instanceof L.Polygon) {\n // find layer difference\n diff = difference(l.toGeoJSON(15), layer.toGeoJSON(15));\n } else {\n const features = flattenPolyline(l);\n\n features.forEach((feature) => {\n // get splitted line to look which line part is coverd by the cut polygon\n const lineDiff = lineSplit(feature, layer.toGeoJSON(15));\n\n let group;\n if (lineDiff && lineDiff.features.length > 0) {\n group = L.geoJSON(lineDiff);\n } else {\n group = L.geoJSON(feature);\n }\n\n group.getLayers().forEach((lay) => {\n // add only parts to the map, they are not covered by the cut polygon\n if (!booleanContains(layer.toGeoJSON(15), lay.toGeoJSON(15))) {\n lay.addTo(fg);\n }\n });\n });\n\n if (features.length > 1) {\n diff = groupToMultiLineString(fg);\n } else {\n diff = fg.toGeoJSON(15);\n }\n }\n return diff;\n },\n _change: L.Util.falseFn,\n});\n","export default (x) => {\n return () => {\n return x;\n };\n};\n","import constant from \"./constant.js\";\nexport default (eps) => {\n const almostEqual = eps ? (a, b) => b.minus(a).abs().isLessThanOrEqualTo(eps)\n : constant(false);\n return (a, b) => {\n if (almostEqual(a, b))\n return 0;\n return a.comparedTo(b);\n };\n};\n","import constant from \"./constant.js\";\nexport default function (eps) {\n const almostCollinear = eps ? (area2, ax, ay, cx, cy) => area2.exponentiatedBy(2).isLessThanOrEqualTo(cx.minus(ax).exponentiatedBy(2).plus(cy.minus(ay).exponentiatedBy(2))\n .times(eps))\n : constant(false);\n return (a, b, c) => {\n const ax = a.x, ay = a.y, cx = c.x, cy = c.y;\n const area2 = ay.minus(cy).times(b.x.minus(cx)).minus(ax.minus(cx).times(b.y.minus(cy)));\n if (almostCollinear(area2, ax, ay, cx, cy))\n return 0;\n return area2.comparedTo(0);\n };\n}\n","/*\r\n * bignumber.js v9.1.2\r\n * A JavaScript library for arbitrary-precision arithmetic.\r\n * https://github.com/MikeMcl/bignumber.js\r\n * Copyright (c) 2022 Michael Mclaughlin \r\n * MIT Licensed.\r\n *\r\n * BigNumber.prototype methods | BigNumber methods\r\n * |\r\n * absoluteValue abs | clone\r\n * comparedTo | config set\r\n * decimalPlaces dp | DECIMAL_PLACES\r\n * dividedBy div | ROUNDING_MODE\r\n * dividedToIntegerBy idiv | EXPONENTIAL_AT\r\n * exponentiatedBy pow | RANGE\r\n * integerValue | CRYPTO\r\n * isEqualTo eq | MODULO_MODE\r\n * isFinite | POW_PRECISION\r\n * isGreaterThan gt | FORMAT\r\n * isGreaterThanOrEqualTo gte | ALPHABET\r\n * isInteger | isBigNumber\r\n * isLessThan lt | maximum max\r\n * isLessThanOrEqualTo lte | minimum min\r\n * isNaN | random\r\n * isNegative | sum\r\n * isPositive |\r\n * isZero |\r\n * minus |\r\n * modulo mod |\r\n * multipliedBy times |\r\n * negated |\r\n * plus |\r\n * precision sd |\r\n * shiftedBy |\r\n * squareRoot sqrt |\r\n * toExponential |\r\n * toFixed |\r\n * toFormat |\r\n * toFraction |\r\n * toJSON |\r\n * toNumber |\r\n * toPrecision |\r\n * toString |\r\n * valueOf |\r\n *\r\n */\r\n\r\n\r\nvar\r\n isNumeric = /^-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?$/i,\r\n mathceil = Math.ceil,\r\n mathfloor = Math.floor,\r\n\r\n bignumberError = '[BigNumber Error] ',\r\n tooManyDigits = bignumberError + 'Number primitive has more than 15 significant digits: ',\r\n\r\n BASE = 1e14,\r\n LOG_BASE = 14,\r\n MAX_SAFE_INTEGER = 0x1fffffffffffff, // 2^53 - 1\r\n // MAX_INT32 = 0x7fffffff, // 2^31 - 1\r\n POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13],\r\n SQRT_BASE = 1e7,\r\n\r\n // EDITABLE\r\n // The limit on the value of DECIMAL_PLACES, TO_EXP_NEG, TO_EXP_POS, MIN_EXP, MAX_EXP, and\r\n // the arguments to toExponential, toFixed, toFormat, and toPrecision.\r\n MAX = 1E9; // 0 to MAX_INT32\r\n\r\n\r\n/*\r\n * Create and return a BigNumber constructor.\r\n */\r\nfunction clone(configObject) {\r\n var div, convertBase, parseNumeric,\r\n P = BigNumber.prototype = { constructor: BigNumber, toString: null, valueOf: null },\r\n ONE = new BigNumber(1),\r\n\r\n\r\n //----------------------------- EDITABLE CONFIG DEFAULTS -------------------------------\r\n\r\n\r\n // The default values below must be integers within the inclusive ranges stated.\r\n // The values can also be changed at run-time using BigNumber.set.\r\n\r\n // The maximum number of decimal places for operations involving division.\r\n DECIMAL_PLACES = 20, // 0 to MAX\r\n\r\n // The rounding mode used when rounding to the above decimal places, and when using\r\n // toExponential, toFixed, toFormat and toPrecision, and round (default value).\r\n // UP 0 Away from zero.\r\n // DOWN 1 Towards zero.\r\n // CEIL 2 Towards +Infinity.\r\n // FLOOR 3 Towards -Infinity.\r\n // HALF_UP 4 Towards nearest neighbour. If equidistant, up.\r\n // HALF_DOWN 5 Towards nearest neighbour. If equidistant, down.\r\n // HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour.\r\n // HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity.\r\n // HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity.\r\n ROUNDING_MODE = 4, // 0 to 8\r\n\r\n // EXPONENTIAL_AT : [TO_EXP_NEG , TO_EXP_POS]\r\n\r\n // The exponent value at and beneath which toString returns exponential notation.\r\n // Number type: -7\r\n TO_EXP_NEG = -7, // 0 to -MAX\r\n\r\n // The exponent value at and above which toString returns exponential notation.\r\n // Number type: 21\r\n TO_EXP_POS = 21, // 0 to MAX\r\n\r\n // RANGE : [MIN_EXP, MAX_EXP]\r\n\r\n // The minimum exponent value, beneath which underflow to zero occurs.\r\n // Number type: -324 (5e-324)\r\n MIN_EXP = -1e7, // -1 to -MAX\r\n\r\n // The maximum exponent value, above which overflow to Infinity occurs.\r\n // Number type: 308 (1.7976931348623157e+308)\r\n // For MAX_EXP > 1e7, e.g. new BigNumber('1e100000000').plus(1) may be slow.\r\n MAX_EXP = 1e7, // 1 to MAX\r\n\r\n // Whether to use cryptographically-secure random number generation, if available.\r\n CRYPTO = false, // true or false\r\n\r\n // The modulo mode used when calculating the modulus: a mod n.\r\n // The quotient (q = a / n) is calculated according to the corresponding rounding mode.\r\n // The remainder (r) is calculated as: r = a - n * q.\r\n //\r\n // UP 0 The remainder is positive if the dividend is negative, else is negative.\r\n // DOWN 1 The remainder has the same sign as the dividend.\r\n // This modulo mode is commonly known as 'truncated division' and is\r\n // equivalent to (a % n) in JavaScript.\r\n // FLOOR 3 The remainder has the same sign as the divisor (Python %).\r\n // HALF_EVEN 6 This modulo mode implements the IEEE 754 remainder function.\r\n // EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)).\r\n // The remainder is always positive.\r\n //\r\n // The truncated division, floored division, Euclidian division and IEEE 754 remainder\r\n // modes are commonly used for the modulus operation.\r\n // Although the other rounding modes can also be used, they may not give useful results.\r\n MODULO_MODE = 1, // 0 to 9\r\n\r\n // The maximum number of significant digits of the result of the exponentiatedBy operation.\r\n // If POW_PRECISION is 0, there will be unlimited significant digits.\r\n POW_PRECISION = 0, // 0 to MAX\r\n\r\n // The format specification used by the BigNumber.prototype.toFormat method.\r\n FORMAT = {\r\n prefix: '',\r\n groupSize: 3,\r\n secondaryGroupSize: 0,\r\n groupSeparator: ',',\r\n decimalSeparator: '.',\r\n fractionGroupSize: 0,\r\n fractionGroupSeparator: '\\xA0', // non-breaking space\r\n suffix: ''\r\n },\r\n\r\n // The alphabet used for base conversion. It must be at least 2 characters long, with no '+',\r\n // '-', '.', whitespace, or repeated character.\r\n // '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_'\r\n ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz',\r\n alphabetHasNormalDecimalDigits = true;\r\n\r\n\r\n //------------------------------------------------------------------------------------------\r\n\r\n\r\n // CONSTRUCTOR\r\n\r\n\r\n /*\r\n * The BigNumber constructor and exported function.\r\n * Create and return a new instance of a BigNumber object.\r\n *\r\n * v {number|string|BigNumber} A numeric value.\r\n * [b] {number} The base of v. Integer, 2 to ALPHABET.length inclusive.\r\n */\r\n function BigNumber(v, b) {\r\n var alphabet, c, caseChanged, e, i, isNum, len, str,\r\n x = this;\r\n\r\n // Enable constructor call without `new`.\r\n if (!(x instanceof BigNumber)) return new BigNumber(v, b);\r\n\r\n if (b == null) {\r\n\r\n if (v && v._isBigNumber === true) {\r\n x.s = v.s;\r\n\r\n if (!v.c || v.e > MAX_EXP) {\r\n x.c = x.e = null;\r\n } else if (v.e < MIN_EXP) {\r\n x.c = [x.e = 0];\r\n } else {\r\n x.e = v.e;\r\n x.c = v.c.slice();\r\n }\r\n\r\n return;\r\n }\r\n\r\n if ((isNum = typeof v == 'number') && v * 0 == 0) {\r\n\r\n // Use `1 / n` to handle minus zero also.\r\n x.s = 1 / v < 0 ? (v = -v, -1) : 1;\r\n\r\n // Fast path for integers, where n < 2147483648 (2**31).\r\n if (v === ~~v) {\r\n for (e = 0, i = v; i >= 10; i /= 10, e++);\r\n\r\n if (e > MAX_EXP) {\r\n x.c = x.e = null;\r\n } else {\r\n x.e = e;\r\n x.c = [v];\r\n }\r\n\r\n return;\r\n }\r\n\r\n str = String(v);\r\n } else {\r\n\r\n if (!isNumeric.test(str = String(v))) return parseNumeric(x, str, isNum);\r\n\r\n x.s = str.charCodeAt(0) == 45 ? (str = str.slice(1), -1) : 1;\r\n }\r\n\r\n // Decimal point?\r\n if ((e = str.indexOf('.')) > -1) str = str.replace('.', '');\r\n\r\n // Exponential form?\r\n if ((i = str.search(/e/i)) > 0) {\r\n\r\n // Determine exponent.\r\n if (e < 0) e = i;\r\n e += +str.slice(i + 1);\r\n str = str.substring(0, i);\r\n } else if (e < 0) {\r\n\r\n // Integer.\r\n e = str.length;\r\n }\r\n\r\n } else {\r\n\r\n // '[BigNumber Error] Base {not a primitive number|not an integer|out of range}: {b}'\r\n intCheck(b, 2, ALPHABET.length, 'Base');\r\n\r\n // Allow exponential notation to be used with base 10 argument, while\r\n // also rounding to DECIMAL_PLACES as with other bases.\r\n if (b == 10 && alphabetHasNormalDecimalDigits) {\r\n x = new BigNumber(v);\r\n return round(x, DECIMAL_PLACES + x.e + 1, ROUNDING_MODE);\r\n }\r\n\r\n str = String(v);\r\n\r\n if (isNum = typeof v == 'number') {\r\n\r\n // Avoid potential interpretation of Infinity and NaN as base 44+ values.\r\n if (v * 0 != 0) return parseNumeric(x, str, isNum, b);\r\n\r\n x.s = 1 / v < 0 ? (str = str.slice(1), -1) : 1;\r\n\r\n // '[BigNumber Error] Number primitive has more than 15 significant digits: {n}'\r\n if (BigNumber.DEBUG && str.replace(/^0\\.0*|\\./, '').length > 15) {\r\n throw Error\r\n (tooManyDigits + v);\r\n }\r\n } else {\r\n x.s = str.charCodeAt(0) === 45 ? (str = str.slice(1), -1) : 1;\r\n }\r\n\r\n alphabet = ALPHABET.slice(0, b);\r\n e = i = 0;\r\n\r\n // Check that str is a valid base b number.\r\n // Don't use RegExp, so alphabet can contain special characters.\r\n for (len = str.length; i < len; i++) {\r\n if (alphabet.indexOf(c = str.charAt(i)) < 0) {\r\n if (c == '.') {\r\n\r\n // If '.' is not the first character and it has not be found before.\r\n if (i > e) {\r\n e = len;\r\n continue;\r\n }\r\n } else if (!caseChanged) {\r\n\r\n // Allow e.g. hexadecimal 'FF' as well as 'ff'.\r\n if (str == str.toUpperCase() && (str = str.toLowerCase()) ||\r\n str == str.toLowerCase() && (str = str.toUpperCase())) {\r\n caseChanged = true;\r\n i = -1;\r\n e = 0;\r\n continue;\r\n }\r\n }\r\n\r\n return parseNumeric(x, String(v), isNum, b);\r\n }\r\n }\r\n\r\n // Prevent later check for length on converted number.\r\n isNum = false;\r\n str = convertBase(str, b, 10, x.s);\r\n\r\n // Decimal point?\r\n if ((e = str.indexOf('.')) > -1) str = str.replace('.', '');\r\n else e = str.length;\r\n }\r\n\r\n // Determine leading zeros.\r\n for (i = 0; str.charCodeAt(i) === 48; i++);\r\n\r\n // Determine trailing zeros.\r\n for (len = str.length; str.charCodeAt(--len) === 48;);\r\n\r\n if (str = str.slice(i, ++len)) {\r\n len -= i;\r\n\r\n // '[BigNumber Error] Number primitive has more than 15 significant digits: {n}'\r\n if (isNum && BigNumber.DEBUG &&\r\n len > 15 && (v > MAX_SAFE_INTEGER || v !== mathfloor(v))) {\r\n throw Error\r\n (tooManyDigits + (x.s * v));\r\n }\r\n\r\n // Overflow?\r\n if ((e = e - i - 1) > MAX_EXP) {\r\n\r\n // Infinity.\r\n x.c = x.e = null;\r\n\r\n // Underflow?\r\n } else if (e < MIN_EXP) {\r\n\r\n // Zero.\r\n x.c = [x.e = 0];\r\n } else {\r\n x.e = e;\r\n x.c = [];\r\n\r\n // Transform base\r\n\r\n // e is the base 10 exponent.\r\n // i is where to slice str to get the first element of the coefficient array.\r\n i = (e + 1) % LOG_BASE;\r\n if (e < 0) i += LOG_BASE; // i < 1\r\n\r\n if (i < len) {\r\n if (i) x.c.push(+str.slice(0, i));\r\n\r\n for (len -= LOG_BASE; i < len;) {\r\n x.c.push(+str.slice(i, i += LOG_BASE));\r\n }\r\n\r\n i = LOG_BASE - (str = str.slice(i)).length;\r\n } else {\r\n i -= len;\r\n }\r\n\r\n for (; i--; str += '0');\r\n x.c.push(+str);\r\n }\r\n } else {\r\n\r\n // Zero.\r\n x.c = [x.e = 0];\r\n }\r\n }\r\n\r\n\r\n // CONSTRUCTOR PROPERTIES\r\n\r\n\r\n BigNumber.clone = clone;\r\n\r\n BigNumber.ROUND_UP = 0;\r\n BigNumber.ROUND_DOWN = 1;\r\n BigNumber.ROUND_CEIL = 2;\r\n BigNumber.ROUND_FLOOR = 3;\r\n BigNumber.ROUND_HALF_UP = 4;\r\n BigNumber.ROUND_HALF_DOWN = 5;\r\n BigNumber.ROUND_HALF_EVEN = 6;\r\n BigNumber.ROUND_HALF_CEIL = 7;\r\n BigNumber.ROUND_HALF_FLOOR = 8;\r\n BigNumber.EUCLID = 9;\r\n\r\n\r\n /*\r\n * Configure infrequently-changing library-wide settings.\r\n *\r\n * Accept an object with the following optional properties (if the value of a property is\r\n * a number, it must be an integer within the inclusive range stated):\r\n *\r\n * DECIMAL_PLACES {number} 0 to MAX\r\n * ROUNDING_MODE {number} 0 to 8\r\n * EXPONENTIAL_AT {number|number[]} -MAX to MAX or [-MAX to 0, 0 to MAX]\r\n * RANGE {number|number[]} -MAX to MAX (not zero) or [-MAX to -1, 1 to MAX]\r\n * CRYPTO {boolean} true or false\r\n * MODULO_MODE {number} 0 to 9\r\n * POW_PRECISION {number} 0 to MAX\r\n * ALPHABET {string} A string of two or more unique characters which does\r\n * not contain '.'.\r\n * FORMAT {object} An object with some of the following properties:\r\n * prefix {string}\r\n * groupSize {number}\r\n * secondaryGroupSize {number}\r\n * groupSeparator {string}\r\n * decimalSeparator {string}\r\n * fractionGroupSize {number}\r\n * fractionGroupSeparator {string}\r\n * suffix {string}\r\n *\r\n * (The values assigned to the above FORMAT object properties are not checked for validity.)\r\n *\r\n * E.g.\r\n * BigNumber.config({ DECIMAL_PLACES : 20, ROUNDING_MODE : 4 })\r\n *\r\n * Ignore properties/parameters set to null or undefined, except for ALPHABET.\r\n *\r\n * Return an object with the properties current values.\r\n */\r\n BigNumber.config = BigNumber.set = function (obj) {\r\n var p, v;\r\n\r\n if (obj != null) {\r\n\r\n if (typeof obj == 'object') {\r\n\r\n // DECIMAL_PLACES {number} Integer, 0 to MAX inclusive.\r\n // '[BigNumber Error] DECIMAL_PLACES {not a primitive number|not an integer|out of range}: {v}'\r\n if (obj.hasOwnProperty(p = 'DECIMAL_PLACES')) {\r\n v = obj[p];\r\n intCheck(v, 0, MAX, p);\r\n DECIMAL_PLACES = v;\r\n }\r\n\r\n // ROUNDING_MODE {number} Integer, 0 to 8 inclusive.\r\n // '[BigNumber Error] ROUNDING_MODE {not a primitive number|not an integer|out of range}: {v}'\r\n if (obj.hasOwnProperty(p = 'ROUNDING_MODE')) {\r\n v = obj[p];\r\n intCheck(v, 0, 8, p);\r\n ROUNDING_MODE = v;\r\n }\r\n\r\n // EXPONENTIAL_AT {number|number[]}\r\n // Integer, -MAX to MAX inclusive or\r\n // [integer -MAX to 0 inclusive, 0 to MAX inclusive].\r\n // '[BigNumber Error] EXPONENTIAL_AT {not a primitive number|not an integer|out of range}: {v}'\r\n if (obj.hasOwnProperty(p = 'EXPONENTIAL_AT')) {\r\n v = obj[p];\r\n if (v && v.pop) {\r\n intCheck(v[0], -MAX, 0, p);\r\n intCheck(v[1], 0, MAX, p);\r\n TO_EXP_NEG = v[0];\r\n TO_EXP_POS = v[1];\r\n } else {\r\n intCheck(v, -MAX, MAX, p);\r\n TO_EXP_NEG = -(TO_EXP_POS = v < 0 ? -v : v);\r\n }\r\n }\r\n\r\n // RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or\r\n // [integer -MAX to -1 inclusive, integer 1 to MAX inclusive].\r\n // '[BigNumber Error] RANGE {not a primitive number|not an integer|out of range|cannot be zero}: {v}'\r\n if (obj.hasOwnProperty(p = 'RANGE')) {\r\n v = obj[p];\r\n if (v && v.pop) {\r\n intCheck(v[0], -MAX, -1, p);\r\n intCheck(v[1], 1, MAX, p);\r\n MIN_EXP = v[0];\r\n MAX_EXP = v[1];\r\n } else {\r\n intCheck(v, -MAX, MAX, p);\r\n if (v) {\r\n MIN_EXP = -(MAX_EXP = v < 0 ? -v : v);\r\n } else {\r\n throw Error\r\n (bignumberError + p + ' cannot be zero: ' + v);\r\n }\r\n }\r\n }\r\n\r\n // CRYPTO {boolean} true or false.\r\n // '[BigNumber Error] CRYPTO not true or false: {v}'\r\n // '[BigNumber Error] crypto unavailable'\r\n if (obj.hasOwnProperty(p = 'CRYPTO')) {\r\n v = obj[p];\r\n if (v === !!v) {\r\n if (v) {\r\n if (typeof crypto != 'undefined' && crypto &&\r\n (crypto.getRandomValues || crypto.randomBytes)) {\r\n CRYPTO = v;\r\n } else {\r\n CRYPTO = !v;\r\n throw Error\r\n (bignumberError + 'crypto unavailable');\r\n }\r\n } else {\r\n CRYPTO = v;\r\n }\r\n } else {\r\n throw Error\r\n (bignumberError + p + ' not true or false: ' + v);\r\n }\r\n }\r\n\r\n // MODULO_MODE {number} Integer, 0 to 9 inclusive.\r\n // '[BigNumber Error] MODULO_MODE {not a primitive number|not an integer|out of range}: {v}'\r\n if (obj.hasOwnProperty(p = 'MODULO_MODE')) {\r\n v = obj[p];\r\n intCheck(v, 0, 9, p);\r\n MODULO_MODE = v;\r\n }\r\n\r\n // POW_PRECISION {number} Integer, 0 to MAX inclusive.\r\n // '[BigNumber Error] POW_PRECISION {not a primitive number|not an integer|out of range}: {v}'\r\n if (obj.hasOwnProperty(p = 'POW_PRECISION')) {\r\n v = obj[p];\r\n intCheck(v, 0, MAX, p);\r\n POW_PRECISION = v;\r\n }\r\n\r\n // FORMAT {object}\r\n // '[BigNumber Error] FORMAT not an object: {v}'\r\n if (obj.hasOwnProperty(p = 'FORMAT')) {\r\n v = obj[p];\r\n if (typeof v == 'object') FORMAT = v;\r\n else throw Error\r\n (bignumberError + p + ' not an object: ' + v);\r\n }\r\n\r\n // ALPHABET {string}\r\n // '[BigNumber Error] ALPHABET invalid: {v}'\r\n if (obj.hasOwnProperty(p = 'ALPHABET')) {\r\n v = obj[p];\r\n\r\n // Disallow if less than two characters,\r\n // or if it contains '+', '-', '.', whitespace, or a repeated character.\r\n if (typeof v == 'string' && !/^.?$|[+\\-.\\s]|(.).*\\1/.test(v)) {\r\n alphabetHasNormalDecimalDigits = v.slice(0, 10) == '0123456789';\r\n ALPHABET = v;\r\n } else {\r\n throw Error\r\n (bignumberError + p + ' invalid: ' + v);\r\n }\r\n }\r\n\r\n } else {\r\n\r\n // '[BigNumber Error] Object expected: {v}'\r\n throw Error\r\n (bignumberError + 'Object expected: ' + obj);\r\n }\r\n }\r\n\r\n return {\r\n DECIMAL_PLACES: DECIMAL_PLACES,\r\n ROUNDING_MODE: ROUNDING_MODE,\r\n EXPONENTIAL_AT: [TO_EXP_NEG, TO_EXP_POS],\r\n RANGE: [MIN_EXP, MAX_EXP],\r\n CRYPTO: CRYPTO,\r\n MODULO_MODE: MODULO_MODE,\r\n POW_PRECISION: POW_PRECISION,\r\n FORMAT: FORMAT,\r\n ALPHABET: ALPHABET\r\n };\r\n };\r\n\r\n\r\n /*\r\n * Return true if v is a BigNumber instance, otherwise return false.\r\n *\r\n * If BigNumber.DEBUG is true, throw if a BigNumber instance is not well-formed.\r\n *\r\n * v {any}\r\n *\r\n * '[BigNumber Error] Invalid BigNumber: {v}'\r\n */\r\n BigNumber.isBigNumber = function (v) {\r\n if (!v || v._isBigNumber !== true) return false;\r\n if (!BigNumber.DEBUG) return true;\r\n\r\n var i, n,\r\n c = v.c,\r\n e = v.e,\r\n s = v.s;\r\n\r\n out: if ({}.toString.call(c) == '[object Array]') {\r\n\r\n if ((s === 1 || s === -1) && e >= -MAX && e <= MAX && e === mathfloor(e)) {\r\n\r\n // If the first element is zero, the BigNumber value must be zero.\r\n if (c[0] === 0) {\r\n if (e === 0 && c.length === 1) return true;\r\n break out;\r\n }\r\n\r\n // Calculate number of digits that c[0] should have, based on the exponent.\r\n i = (e + 1) % LOG_BASE;\r\n if (i < 1) i += LOG_BASE;\r\n\r\n // Calculate number of digits of c[0].\r\n //if (Math.ceil(Math.log(c[0] + 1) / Math.LN10) == i) {\r\n if (String(c[0]).length == i) {\r\n\r\n for (i = 0; i < c.length; i++) {\r\n n = c[i];\r\n if (n < 0 || n >= BASE || n !== mathfloor(n)) break out;\r\n }\r\n\r\n // Last element cannot be zero, unless it is the only element.\r\n if (n !== 0) return true;\r\n }\r\n }\r\n\r\n // Infinity/NaN\r\n } else if (c === null && e === null && (s === null || s === 1 || s === -1)) {\r\n return true;\r\n }\r\n\r\n throw Error\r\n (bignumberError + 'Invalid BigNumber: ' + v);\r\n };\r\n\r\n\r\n /*\r\n * Return a new BigNumber whose value is the maximum of the arguments.\r\n *\r\n * arguments {number|string|BigNumber}\r\n */\r\n BigNumber.maximum = BigNumber.max = function () {\r\n return maxOrMin(arguments, -1);\r\n };\r\n\r\n\r\n /*\r\n * Return a new BigNumber whose value is the minimum of the arguments.\r\n *\r\n * arguments {number|string|BigNumber}\r\n */\r\n BigNumber.minimum = BigNumber.min = function () {\r\n return maxOrMin(arguments, 1);\r\n };\r\n\r\n\r\n /*\r\n * Return a new BigNumber with a random value equal to or greater than 0 and less than 1,\r\n * and with dp, or DECIMAL_PLACES if dp is omitted, decimal places (or less if trailing\r\n * zeros are produced).\r\n *\r\n * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.\r\n *\r\n * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp}'\r\n * '[BigNumber Error] crypto unavailable'\r\n */\r\n BigNumber.random = (function () {\r\n var pow2_53 = 0x20000000000000;\r\n\r\n // Return a 53 bit integer n, where 0 <= n < 9007199254740992.\r\n // Check if Math.random() produces more than 32 bits of randomness.\r\n // If it does, assume at least 53 bits are produced, otherwise assume at least 30 bits.\r\n // 0x40000000 is 2^30, 0x800000 is 2^23, 0x1fffff is 2^21 - 1.\r\n var random53bitInt = (Math.random() * pow2_53) & 0x1fffff\r\n ? function () { return mathfloor(Math.random() * pow2_53); }\r\n : function () { return ((Math.random() * 0x40000000 | 0) * 0x800000) +\r\n (Math.random() * 0x800000 | 0); };\r\n\r\n return function (dp) {\r\n var a, b, e, k, v,\r\n i = 0,\r\n c = [],\r\n rand = new BigNumber(ONE);\r\n\r\n if (dp == null) dp = DECIMAL_PLACES;\r\n else intCheck(dp, 0, MAX);\r\n\r\n k = mathceil(dp / LOG_BASE);\r\n\r\n if (CRYPTO) {\r\n\r\n // Browsers supporting crypto.getRandomValues.\r\n if (crypto.getRandomValues) {\r\n\r\n a = crypto.getRandomValues(new Uint32Array(k *= 2));\r\n\r\n for (; i < k;) {\r\n\r\n // 53 bits:\r\n // ((Math.pow(2, 32) - 1) * Math.pow(2, 21)).toString(2)\r\n // 11111 11111111 11111111 11111111 11100000 00000000 00000000\r\n // ((Math.pow(2, 32) - 1) >>> 11).toString(2)\r\n // 11111 11111111 11111111\r\n // 0x20000 is 2^21.\r\n v = a[i] * 0x20000 + (a[i + 1] >>> 11);\r\n\r\n // Rejection sampling:\r\n // 0 <= v < 9007199254740992\r\n // Probability that v >= 9e15, is\r\n // 7199254740992 / 9007199254740992 ~= 0.0008, i.e. 1 in 1251\r\n if (v >= 9e15) {\r\n b = crypto.getRandomValues(new Uint32Array(2));\r\n a[i] = b[0];\r\n a[i + 1] = b[1];\r\n } else {\r\n\r\n // 0 <= v <= 8999999999999999\r\n // 0 <= (v % 1e14) <= 99999999999999\r\n c.push(v % 1e14);\r\n i += 2;\r\n }\r\n }\r\n i = k / 2;\r\n\r\n // Node.js supporting crypto.randomBytes.\r\n } else if (crypto.randomBytes) {\r\n\r\n // buffer\r\n a = crypto.randomBytes(k *= 7);\r\n\r\n for (; i < k;) {\r\n\r\n // 0x1000000000000 is 2^48, 0x10000000000 is 2^40\r\n // 0x100000000 is 2^32, 0x1000000 is 2^24\r\n // 11111 11111111 11111111 11111111 11111111 11111111 11111111\r\n // 0 <= v < 9007199254740992\r\n v = ((a[i] & 31) * 0x1000000000000) + (a[i + 1] * 0x10000000000) +\r\n (a[i + 2] * 0x100000000) + (a[i + 3] * 0x1000000) +\r\n (a[i + 4] << 16) + (a[i + 5] << 8) + a[i + 6];\r\n\r\n if (v >= 9e15) {\r\n crypto.randomBytes(7).copy(a, i);\r\n } else {\r\n\r\n // 0 <= (v % 1e14) <= 99999999999999\r\n c.push(v % 1e14);\r\n i += 7;\r\n }\r\n }\r\n i = k / 7;\r\n } else {\r\n CRYPTO = false;\r\n throw Error\r\n (bignumberError + 'crypto unavailable');\r\n }\r\n }\r\n\r\n // Use Math.random.\r\n if (!CRYPTO) {\r\n\r\n for (; i < k;) {\r\n v = random53bitInt();\r\n if (v < 9e15) c[i++] = v % 1e14;\r\n }\r\n }\r\n\r\n k = c[--i];\r\n dp %= LOG_BASE;\r\n\r\n // Convert trailing digits to zeros according to dp.\r\n if (k && dp) {\r\n v = POWS_TEN[LOG_BASE - dp];\r\n c[i] = mathfloor(k / v) * v;\r\n }\r\n\r\n // Remove trailing elements which are zero.\r\n for (; c[i] === 0; c.pop(), i--);\r\n\r\n // Zero?\r\n if (i < 0) {\r\n c = [e = 0];\r\n } else {\r\n\r\n // Remove leading elements which are zero and adjust exponent accordingly.\r\n for (e = -1 ; c[0] === 0; c.splice(0, 1), e -= LOG_BASE);\r\n\r\n // Count the digits of the first element of c to determine leading zeros, and...\r\n for (i = 1, v = c[0]; v >= 10; v /= 10, i++);\r\n\r\n // adjust the exponent accordingly.\r\n if (i < LOG_BASE) e -= LOG_BASE - i;\r\n }\r\n\r\n rand.e = e;\r\n rand.c = c;\r\n return rand;\r\n };\r\n })();\r\n\r\n\r\n /*\r\n * Return a BigNumber whose value is the sum of the arguments.\r\n *\r\n * arguments {number|string|BigNumber}\r\n */\r\n BigNumber.sum = function () {\r\n var i = 1,\r\n args = arguments,\r\n sum = new BigNumber(args[0]);\r\n for (; i < args.length;) sum = sum.plus(args[i++]);\r\n return sum;\r\n };\r\n\r\n\r\n // PRIVATE FUNCTIONS\r\n\r\n\r\n // Called by BigNumber and BigNumber.prototype.toString.\r\n convertBase = (function () {\r\n var decimal = '0123456789';\r\n\r\n /*\r\n * Convert string of baseIn to an array of numbers of baseOut.\r\n * Eg. toBaseOut('255', 10, 16) returns [15, 15].\r\n * Eg. toBaseOut('ff', 16, 10) returns [2, 5, 5].\r\n */\r\n function toBaseOut(str, baseIn, baseOut, alphabet) {\r\n var j,\r\n arr = [0],\r\n arrL,\r\n i = 0,\r\n len = str.length;\r\n\r\n for (; i < len;) {\r\n for (arrL = arr.length; arrL--; arr[arrL] *= baseIn);\r\n\r\n arr[0] += alphabet.indexOf(str.charAt(i++));\r\n\r\n for (j = 0; j < arr.length; j++) {\r\n\r\n if (arr[j] > baseOut - 1) {\r\n if (arr[j + 1] == null) arr[j + 1] = 0;\r\n arr[j + 1] += arr[j] / baseOut | 0;\r\n arr[j] %= baseOut;\r\n }\r\n }\r\n }\r\n\r\n return arr.reverse();\r\n }\r\n\r\n // Convert a numeric string of baseIn to a numeric string of baseOut.\r\n // If the caller is toString, we are converting from base 10 to baseOut.\r\n // If the caller is BigNumber, we are converting from baseIn to base 10.\r\n return function (str, baseIn, baseOut, sign, callerIsToString) {\r\n var alphabet, d, e, k, r, x, xc, y,\r\n i = str.indexOf('.'),\r\n dp = DECIMAL_PLACES,\r\n rm = ROUNDING_MODE;\r\n\r\n // Non-integer.\r\n if (i >= 0) {\r\n k = POW_PRECISION;\r\n\r\n // Unlimited precision.\r\n POW_PRECISION = 0;\r\n str = str.replace('.', '');\r\n y = new BigNumber(baseIn);\r\n x = y.pow(str.length - i);\r\n POW_PRECISION = k;\r\n\r\n // Convert str as if an integer, then restore the fraction part by dividing the\r\n // result by its base raised to a power.\r\n\r\n y.c = toBaseOut(toFixedPoint(coeffToString(x.c), x.e, '0'),\r\n 10, baseOut, decimal);\r\n y.e = y.c.length;\r\n }\r\n\r\n // Convert the number as integer.\r\n\r\n xc = toBaseOut(str, baseIn, baseOut, callerIsToString\r\n ? (alphabet = ALPHABET, decimal)\r\n : (alphabet = decimal, ALPHABET));\r\n\r\n // xc now represents str as an integer and converted to baseOut. e is the exponent.\r\n e = k = xc.length;\r\n\r\n // Remove trailing zeros.\r\n for (; xc[--k] == 0; xc.pop());\r\n\r\n // Zero?\r\n if (!xc[0]) return alphabet.charAt(0);\r\n\r\n // Does str represent an integer? If so, no need for the division.\r\n if (i < 0) {\r\n --e;\r\n } else {\r\n x.c = xc;\r\n x.e = e;\r\n\r\n // The sign is needed for correct rounding.\r\n x.s = sign;\r\n x = div(x, y, dp, rm, baseOut);\r\n xc = x.c;\r\n r = x.r;\r\n e = x.e;\r\n }\r\n\r\n // xc now represents str converted to baseOut.\r\n\r\n // THe index of the rounding digit.\r\n d = e + dp + 1;\r\n\r\n // The rounding digit: the digit to the right of the digit that may be rounded up.\r\n i = xc[d];\r\n\r\n // Look at the rounding digits and mode to determine whether to round up.\r\n\r\n k = baseOut / 2;\r\n r = r || d < 0 || xc[d + 1] != null;\r\n\r\n r = rm < 4 ? (i != null || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2))\r\n : i > k || i == k &&(rm == 4 || r || rm == 6 && xc[d - 1] & 1 ||\r\n rm == (x.s < 0 ? 8 : 7));\r\n\r\n // If the index of the rounding digit is not greater than zero, or xc represents\r\n // zero, then the result of the base conversion is zero or, if rounding up, a value\r\n // such as 0.00001.\r\n if (d < 1 || !xc[0]) {\r\n\r\n // 1^-dp or 0\r\n str = r ? toFixedPoint(alphabet.charAt(1), -dp, alphabet.charAt(0)) : alphabet.charAt(0);\r\n } else {\r\n\r\n // Truncate xc to the required number of decimal places.\r\n xc.length = d;\r\n\r\n // Round up?\r\n if (r) {\r\n\r\n // Rounding up may mean the previous digit has to be rounded up and so on.\r\n for (--baseOut; ++xc[--d] > baseOut;) {\r\n xc[d] = 0;\r\n\r\n if (!d) {\r\n ++e;\r\n xc = [1].concat(xc);\r\n }\r\n }\r\n }\r\n\r\n // Determine trailing zeros.\r\n for (k = xc.length; !xc[--k];);\r\n\r\n // E.g. [4, 11, 15] becomes 4bf.\r\n for (i = 0, str = ''; i <= k; str += alphabet.charAt(xc[i++]));\r\n\r\n // Add leading zeros, decimal point and trailing zeros as required.\r\n str = toFixedPoint(str, e, alphabet.charAt(0));\r\n }\r\n\r\n // The caller will add the sign.\r\n return str;\r\n };\r\n })();\r\n\r\n\r\n // Perform division in the specified base. Called by div and convertBase.\r\n div = (function () {\r\n\r\n // Assume non-zero x and k.\r\n function multiply(x, k, base) {\r\n var m, temp, xlo, xhi,\r\n carry = 0,\r\n i = x.length,\r\n klo = k % SQRT_BASE,\r\n khi = k / SQRT_BASE | 0;\r\n\r\n for (x = x.slice(); i--;) {\r\n xlo = x[i] % SQRT_BASE;\r\n xhi = x[i] / SQRT_BASE | 0;\r\n m = khi * xlo + xhi * klo;\r\n temp = klo * xlo + ((m % SQRT_BASE) * SQRT_BASE) + carry;\r\n carry = (temp / base | 0) + (m / SQRT_BASE | 0) + khi * xhi;\r\n x[i] = temp % base;\r\n }\r\n\r\n if (carry) x = [carry].concat(x);\r\n\r\n return x;\r\n }\r\n\r\n function compare(a, b, aL, bL) {\r\n var i, cmp;\r\n\r\n if (aL != bL) {\r\n cmp = aL > bL ? 1 : -1;\r\n } else {\r\n\r\n for (i = cmp = 0; i < aL; i++) {\r\n\r\n if (a[i] != b[i]) {\r\n cmp = a[i] > b[i] ? 1 : -1;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return cmp;\r\n }\r\n\r\n function subtract(a, b, aL, base) {\r\n var i = 0;\r\n\r\n // Subtract b from a.\r\n for (; aL--;) {\r\n a[aL] -= i;\r\n i = a[aL] < b[aL] ? 1 : 0;\r\n a[aL] = i * base + a[aL] - b[aL];\r\n }\r\n\r\n // Remove leading zeros.\r\n for (; !a[0] && a.length > 1; a.splice(0, 1));\r\n }\r\n\r\n // x: dividend, y: divisor.\r\n return function (x, y, dp, rm, base) {\r\n var cmp, e, i, more, n, prod, prodL, q, qc, rem, remL, rem0, xi, xL, yc0,\r\n yL, yz,\r\n s = x.s == y.s ? 1 : -1,\r\n xc = x.c,\r\n yc = y.c;\r\n\r\n // Either NaN, Infinity or 0?\r\n if (!xc || !xc[0] || !yc || !yc[0]) {\r\n\r\n return new BigNumber(\r\n\r\n // Return NaN if either NaN, or both Infinity or 0.\r\n !x.s || !y.s || (xc ? yc && xc[0] == yc[0] : !yc) ? NaN :\r\n\r\n // Return ±0 if x is ±0 or y is ±Infinity, or return ±Infinity as y is ±0.\r\n xc && xc[0] == 0 || !yc ? s * 0 : s / 0\r\n );\r\n }\r\n\r\n q = new BigNumber(s);\r\n qc = q.c = [];\r\n e = x.e - y.e;\r\n s = dp + e + 1;\r\n\r\n if (!base) {\r\n base = BASE;\r\n e = bitFloor(x.e / LOG_BASE) - bitFloor(y.e / LOG_BASE);\r\n s = s / LOG_BASE | 0;\r\n }\r\n\r\n // Result exponent may be one less then the current value of e.\r\n // The coefficients of the BigNumbers from convertBase may have trailing zeros.\r\n for (i = 0; yc[i] == (xc[i] || 0); i++);\r\n\r\n if (yc[i] > (xc[i] || 0)) e--;\r\n\r\n if (s < 0) {\r\n qc.push(1);\r\n more = true;\r\n } else {\r\n xL = xc.length;\r\n yL = yc.length;\r\n i = 0;\r\n s += 2;\r\n\r\n // Normalise xc and yc so highest order digit of yc is >= base / 2.\r\n\r\n n = mathfloor(base / (yc[0] + 1));\r\n\r\n // Not necessary, but to handle odd bases where yc[0] == (base / 2) - 1.\r\n // if (n > 1 || n++ == 1 && yc[0] < base / 2) {\r\n if (n > 1) {\r\n yc = multiply(yc, n, base);\r\n xc = multiply(xc, n, base);\r\n yL = yc.length;\r\n xL = xc.length;\r\n }\r\n\r\n xi = yL;\r\n rem = xc.slice(0, yL);\r\n remL = rem.length;\r\n\r\n // Add zeros to make remainder as long as divisor.\r\n for (; remL < yL; rem[remL++] = 0);\r\n yz = yc.slice();\r\n yz = [0].concat(yz);\r\n yc0 = yc[0];\r\n if (yc[1] >= base / 2) yc0++;\r\n // Not necessary, but to prevent trial digit n > base, when using base 3.\r\n // else if (base == 3 && yc0 == 1) yc0 = 1 + 1e-15;\r\n\r\n do {\r\n n = 0;\r\n\r\n // Compare divisor and remainder.\r\n cmp = compare(yc, rem, yL, remL);\r\n\r\n // If divisor < remainder.\r\n if (cmp < 0) {\r\n\r\n // Calculate trial digit, n.\r\n\r\n rem0 = rem[0];\r\n if (yL != remL) rem0 = rem0 * base + (rem[1] || 0);\r\n\r\n // n is how many times the divisor goes into the current remainder.\r\n n = mathfloor(rem0 / yc0);\r\n\r\n // Algorithm:\r\n // product = divisor multiplied by trial digit (n).\r\n // Compare product and remainder.\r\n // If product is greater than remainder:\r\n // Subtract divisor from product, decrement trial digit.\r\n // Subtract product from remainder.\r\n // If product was less than remainder at the last compare:\r\n // Compare new remainder and divisor.\r\n // If remainder is greater than divisor:\r\n // Subtract divisor from remainder, increment trial digit.\r\n\r\n if (n > 1) {\r\n\r\n // n may be > base only when base is 3.\r\n if (n >= base) n = base - 1;\r\n\r\n // product = divisor * trial digit.\r\n prod = multiply(yc, n, base);\r\n prodL = prod.length;\r\n remL = rem.length;\r\n\r\n // Compare product and remainder.\r\n // If product > remainder then trial digit n too high.\r\n // n is 1 too high about 5% of the time, and is not known to have\r\n // ever been more than 1 too high.\r\n while (compare(prod, rem, prodL, remL) == 1) {\r\n n--;\r\n\r\n // Subtract divisor from product.\r\n subtract(prod, yL < prodL ? yz : yc, prodL, base);\r\n prodL = prod.length;\r\n cmp = 1;\r\n }\r\n } else {\r\n\r\n // n is 0 or 1, cmp is -1.\r\n // If n is 0, there is no need to compare yc and rem again below,\r\n // so change cmp to 1 to avoid it.\r\n // If n is 1, leave cmp as -1, so yc and rem are compared again.\r\n if (n == 0) {\r\n\r\n // divisor < remainder, so n must be at least 1.\r\n cmp = n = 1;\r\n }\r\n\r\n // product = divisor\r\n prod = yc.slice();\r\n prodL = prod.length;\r\n }\r\n\r\n if (prodL < remL) prod = [0].concat(prod);\r\n\r\n // Subtract product from remainder.\r\n subtract(rem, prod, remL, base);\r\n remL = rem.length;\r\n\r\n // If product was < remainder.\r\n if (cmp == -1) {\r\n\r\n // Compare divisor and new remainder.\r\n // If divisor < new remainder, subtract divisor from remainder.\r\n // Trial digit n too low.\r\n // n is 1 too low about 5% of the time, and very rarely 2 too low.\r\n while (compare(yc, rem, yL, remL) < 1) {\r\n n++;\r\n\r\n // Subtract divisor from remainder.\r\n subtract(rem, yL < remL ? yz : yc, remL, base);\r\n remL = rem.length;\r\n }\r\n }\r\n } else if (cmp === 0) {\r\n n++;\r\n rem = [0];\r\n } // else cmp === 1 and n will be 0\r\n\r\n // Add the next digit, n, to the result array.\r\n qc[i++] = n;\r\n\r\n // Update the remainder.\r\n if (rem[0]) {\r\n rem[remL++] = xc[xi] || 0;\r\n } else {\r\n rem = [xc[xi]];\r\n remL = 1;\r\n }\r\n } while ((xi++ < xL || rem[0] != null) && s--);\r\n\r\n more = rem[0] != null;\r\n\r\n // Leading zero?\r\n if (!qc[0]) qc.splice(0, 1);\r\n }\r\n\r\n if (base == BASE) {\r\n\r\n // To calculate q.e, first get the number of digits of qc[0].\r\n for (i = 1, s = qc[0]; s >= 10; s /= 10, i++);\r\n\r\n round(q, dp + (q.e = i + e * LOG_BASE - 1) + 1, rm, more);\r\n\r\n // Caller is convertBase.\r\n } else {\r\n q.e = e;\r\n q.r = +more;\r\n }\r\n\r\n return q;\r\n };\r\n })();\r\n\r\n\r\n /*\r\n * Return a string representing the value of BigNumber n in fixed-point or exponential\r\n * notation rounded to the specified decimal places or significant digits.\r\n *\r\n * n: a BigNumber.\r\n * i: the index of the last digit required (i.e. the digit that may be rounded up).\r\n * rm: the rounding mode.\r\n * id: 1 (toExponential) or 2 (toPrecision).\r\n */\r\n function format(n, i, rm, id) {\r\n var c0, e, ne, len, str;\r\n\r\n if (rm == null) rm = ROUNDING_MODE;\r\n else intCheck(rm, 0, 8);\r\n\r\n if (!n.c) return n.toString();\r\n\r\n c0 = n.c[0];\r\n ne = n.e;\r\n\r\n if (i == null) {\r\n str = coeffToString(n.c);\r\n str = id == 1 || id == 2 && (ne <= TO_EXP_NEG || ne >= TO_EXP_POS)\r\n ? toExponential(str, ne)\r\n : toFixedPoint(str, ne, '0');\r\n } else {\r\n n = round(new BigNumber(n), i, rm);\r\n\r\n // n.e may have changed if the value was rounded up.\r\n e = n.e;\r\n\r\n str = coeffToString(n.c);\r\n len = str.length;\r\n\r\n // toPrecision returns exponential notation if the number of significant digits\r\n // specified is less than the number of digits necessary to represent the integer\r\n // part of the value in fixed-point notation.\r\n\r\n // Exponential notation.\r\n if (id == 1 || id == 2 && (i <= e || e <= TO_EXP_NEG)) {\r\n\r\n // Append zeros?\r\n for (; len < i; str += '0', len++);\r\n str = toExponential(str, e);\r\n\r\n // Fixed-point notation.\r\n } else {\r\n i -= ne;\r\n str = toFixedPoint(str, e, '0');\r\n\r\n // Append zeros?\r\n if (e + 1 > len) {\r\n if (--i > 0) for (str += '.'; i--; str += '0');\r\n } else {\r\n i += e - len;\r\n if (i > 0) {\r\n if (e + 1 == len) str += '.';\r\n for (; i--; str += '0');\r\n }\r\n }\r\n }\r\n }\r\n\r\n return n.s < 0 && c0 ? '-' + str : str;\r\n }\r\n\r\n\r\n // Handle BigNumber.max and BigNumber.min.\r\n // If any number is NaN, return NaN.\r\n function maxOrMin(args, n) {\r\n var k, y,\r\n i = 1,\r\n x = new BigNumber(args[0]);\r\n\r\n for (; i < args.length; i++) {\r\n y = new BigNumber(args[i]);\r\n if (!y.s || (k = compare(x, y)) === n || k === 0 && x.s === n) {\r\n x = y;\r\n }\r\n }\r\n\r\n return x;\r\n }\r\n\r\n\r\n /*\r\n * Strip trailing zeros, calculate base 10 exponent and check against MIN_EXP and MAX_EXP.\r\n * Called by minus, plus and times.\r\n */\r\n function normalise(n, c, e) {\r\n var i = 1,\r\n j = c.length;\r\n\r\n // Remove trailing zeros.\r\n for (; !c[--j]; c.pop());\r\n\r\n // Calculate the base 10 exponent. First get the number of digits of c[0].\r\n for (j = c[0]; j >= 10; j /= 10, i++);\r\n\r\n // Overflow?\r\n if ((e = i + e * LOG_BASE - 1) > MAX_EXP) {\r\n\r\n // Infinity.\r\n n.c = n.e = null;\r\n\r\n // Underflow?\r\n } else if (e < MIN_EXP) {\r\n\r\n // Zero.\r\n n.c = [n.e = 0];\r\n } else {\r\n n.e = e;\r\n n.c = c;\r\n }\r\n\r\n return n;\r\n }\r\n\r\n\r\n // Handle values that fail the validity test in BigNumber.\r\n parseNumeric = (function () {\r\n var basePrefix = /^(-?)0([xbo])(?=\\w[\\w.]*$)/i,\r\n dotAfter = /^([^.]+)\\.$/,\r\n dotBefore = /^\\.([^.]+)$/,\r\n isInfinityOrNaN = /^-?(Infinity|NaN)$/,\r\n whitespaceOrPlus = /^\\s*\\+(?=[\\w.])|^\\s+|\\s+$/g;\r\n\r\n return function (x, str, isNum, b) {\r\n var base,\r\n s = isNum ? str : str.replace(whitespaceOrPlus, '');\r\n\r\n // No exception on ±Infinity or NaN.\r\n if (isInfinityOrNaN.test(s)) {\r\n x.s = isNaN(s) ? null : s < 0 ? -1 : 1;\r\n } else {\r\n if (!isNum) {\r\n\r\n // basePrefix = /^(-?)0([xbo])(?=\\w[\\w.]*$)/i\r\n s = s.replace(basePrefix, function (m, p1, p2) {\r\n base = (p2 = p2.toLowerCase()) == 'x' ? 16 : p2 == 'b' ? 2 : 8;\r\n return !b || b == base ? p1 : m;\r\n });\r\n\r\n if (b) {\r\n base = b;\r\n\r\n // E.g. '1.' to '1', '.1' to '0.1'\r\n s = s.replace(dotAfter, '$1').replace(dotBefore, '0.$1');\r\n }\r\n\r\n if (str != s) return new BigNumber(s, base);\r\n }\r\n\r\n // '[BigNumber Error] Not a number: {n}'\r\n // '[BigNumber Error] Not a base {b} number: {n}'\r\n if (BigNumber.DEBUG) {\r\n throw Error\r\n (bignumberError + 'Not a' + (b ? ' base ' + b : '') + ' number: ' + str);\r\n }\r\n\r\n // NaN\r\n x.s = null;\r\n }\r\n\r\n x.c = x.e = null;\r\n }\r\n })();\r\n\r\n\r\n /*\r\n * Round x to sd significant digits using rounding mode rm. Check for over/under-flow.\r\n * If r is truthy, it is known that there are more digits after the rounding digit.\r\n */\r\n function round(x, sd, rm, r) {\r\n var d, i, j, k, n, ni, rd,\r\n xc = x.c,\r\n pows10 = POWS_TEN;\r\n\r\n // if x is not Infinity or NaN...\r\n if (xc) {\r\n\r\n // rd is the rounding digit, i.e. the digit after the digit that may be rounded up.\r\n // n is a base 1e14 number, the value of the element of array x.c containing rd.\r\n // ni is the index of n within x.c.\r\n // d is the number of digits of n.\r\n // i is the index of rd within n including leading zeros.\r\n // j is the actual index of rd within n (if < 0, rd is a leading zero).\r\n out: {\r\n\r\n // Get the number of digits of the first element of xc.\r\n for (d = 1, k = xc[0]; k >= 10; k /= 10, d++);\r\n i = sd - d;\r\n\r\n // If the rounding digit is in the first element of xc...\r\n if (i < 0) {\r\n i += LOG_BASE;\r\n j = sd;\r\n n = xc[ni = 0];\r\n\r\n // Get the rounding digit at index j of n.\r\n rd = mathfloor(n / pows10[d - j - 1] % 10);\r\n } else {\r\n ni = mathceil((i + 1) / LOG_BASE);\r\n\r\n if (ni >= xc.length) {\r\n\r\n if (r) {\r\n\r\n // Needed by sqrt.\r\n for (; xc.length <= ni; xc.push(0));\r\n n = rd = 0;\r\n d = 1;\r\n i %= LOG_BASE;\r\n j = i - LOG_BASE + 1;\r\n } else {\r\n break out;\r\n }\r\n } else {\r\n n = k = xc[ni];\r\n\r\n // Get the number of digits of n.\r\n for (d = 1; k >= 10; k /= 10, d++);\r\n\r\n // Get the index of rd within n.\r\n i %= LOG_BASE;\r\n\r\n // Get the index of rd within n, adjusted for leading zeros.\r\n // The number of leading zeros of n is given by LOG_BASE - d.\r\n j = i - LOG_BASE + d;\r\n\r\n // Get the rounding digit at index j of n.\r\n rd = j < 0 ? 0 : mathfloor(n / pows10[d - j - 1] % 10);\r\n }\r\n }\r\n\r\n r = r || sd < 0 ||\r\n\r\n // Are there any non-zero digits after the rounding digit?\r\n // The expression n % pows10[d - j - 1] returns all digits of n to the right\r\n // of the digit at j, e.g. if n is 908714 and j is 2, the expression gives 714.\r\n xc[ni + 1] != null || (j < 0 ? n : n % pows10[d - j - 1]);\r\n\r\n r = rm < 4\r\n ? (rd || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2))\r\n : rd > 5 || rd == 5 && (rm == 4 || r || rm == 6 &&\r\n\r\n // Check whether the digit to the left of the rounding digit is odd.\r\n ((i > 0 ? j > 0 ? n / pows10[d - j] : 0 : xc[ni - 1]) % 10) & 1 ||\r\n rm == (x.s < 0 ? 8 : 7));\r\n\r\n if (sd < 1 || !xc[0]) {\r\n xc.length = 0;\r\n\r\n if (r) {\r\n\r\n // Convert sd to decimal places.\r\n sd -= x.e + 1;\r\n\r\n // 1, 0.1, 0.01, 0.001, 0.0001 etc.\r\n xc[0] = pows10[(LOG_BASE - sd % LOG_BASE) % LOG_BASE];\r\n x.e = -sd || 0;\r\n } else {\r\n\r\n // Zero.\r\n xc[0] = x.e = 0;\r\n }\r\n\r\n return x;\r\n }\r\n\r\n // Remove excess digits.\r\n if (i == 0) {\r\n xc.length = ni;\r\n k = 1;\r\n ni--;\r\n } else {\r\n xc.length = ni + 1;\r\n k = pows10[LOG_BASE - i];\r\n\r\n // E.g. 56700 becomes 56000 if 7 is the rounding digit.\r\n // j > 0 means i > number of leading zeros of n.\r\n xc[ni] = j > 0 ? mathfloor(n / pows10[d - j] % pows10[j]) * k : 0;\r\n }\r\n\r\n // Round up?\r\n if (r) {\r\n\r\n for (; ;) {\r\n\r\n // If the digit to be rounded up is in the first element of xc...\r\n if (ni == 0) {\r\n\r\n // i will be the length of xc[0] before k is added.\r\n for (i = 1, j = xc[0]; j >= 10; j /= 10, i++);\r\n j = xc[0] += k;\r\n for (k = 1; j >= 10; j /= 10, k++);\r\n\r\n // if i != k the length has increased.\r\n if (i != k) {\r\n x.e++;\r\n if (xc[0] == BASE) xc[0] = 1;\r\n }\r\n\r\n break;\r\n } else {\r\n xc[ni] += k;\r\n if (xc[ni] != BASE) break;\r\n xc[ni--] = 0;\r\n k = 1;\r\n }\r\n }\r\n }\r\n\r\n // Remove trailing zeros.\r\n for (i = xc.length; xc[--i] === 0; xc.pop());\r\n }\r\n\r\n // Overflow? Infinity.\r\n if (x.e > MAX_EXP) {\r\n x.c = x.e = null;\r\n\r\n // Underflow? Zero.\r\n } else if (x.e < MIN_EXP) {\r\n x.c = [x.e = 0];\r\n }\r\n }\r\n\r\n return x;\r\n }\r\n\r\n\r\n function valueOf(n) {\r\n var str,\r\n e = n.e;\r\n\r\n if (e === null) return n.toString();\r\n\r\n str = coeffToString(n.c);\r\n\r\n str = e <= TO_EXP_NEG || e >= TO_EXP_POS\r\n ? toExponential(str, e)\r\n : toFixedPoint(str, e, '0');\r\n\r\n return n.s < 0 ? '-' + str : str;\r\n }\r\n\r\n\r\n // PROTOTYPE/INSTANCE METHODS\r\n\r\n\r\n /*\r\n * Return a new BigNumber whose value is the absolute value of this BigNumber.\r\n */\r\n P.absoluteValue = P.abs = function () {\r\n var x = new BigNumber(this);\r\n if (x.s < 0) x.s = 1;\r\n return x;\r\n };\r\n\r\n\r\n /*\r\n * Return\r\n * 1 if the value of this BigNumber is greater than the value of BigNumber(y, b),\r\n * -1 if the value of this BigNumber is less than the value of BigNumber(y, b),\r\n * 0 if they have the same value,\r\n * or null if the value of either is NaN.\r\n */\r\n P.comparedTo = function (y, b) {\r\n return compare(this, new BigNumber(y, b));\r\n };\r\n\r\n\r\n /*\r\n * If dp is undefined or null or true or false, return the number of decimal places of the\r\n * value of this BigNumber, or null if the value of this BigNumber is ±Infinity or NaN.\r\n *\r\n * Otherwise, if dp is a number, return a new BigNumber whose value is the value of this\r\n * BigNumber rounded to a maximum of dp decimal places using rounding mode rm, or\r\n * ROUNDING_MODE if rm is omitted.\r\n *\r\n * [dp] {number} Decimal places: integer, 0 to MAX inclusive.\r\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\r\n *\r\n * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}'\r\n */\r\n P.decimalPlaces = P.dp = function (dp, rm) {\r\n var c, n, v,\r\n x = this;\r\n\r\n if (dp != null) {\r\n intCheck(dp, 0, MAX);\r\n if (rm == null) rm = ROUNDING_MODE;\r\n else intCheck(rm, 0, 8);\r\n\r\n return round(new BigNumber(x), dp + x.e + 1, rm);\r\n }\r\n\r\n if (!(c = x.c)) return null;\r\n n = ((v = c.length - 1) - bitFloor(this.e / LOG_BASE)) * LOG_BASE;\r\n\r\n // Subtract the number of trailing zeros of the last number.\r\n if (v = c[v]) for (; v % 10 == 0; v /= 10, n--);\r\n if (n < 0) n = 0;\r\n\r\n return n;\r\n };\r\n\r\n\r\n /*\r\n * n / 0 = I\r\n * n / N = N\r\n * n / I = 0\r\n * 0 / n = 0\r\n * 0 / 0 = N\r\n * 0 / N = N\r\n * 0 / I = 0\r\n * N / n = N\r\n * N / 0 = N\r\n * N / N = N\r\n * N / I = N\r\n * I / n = I\r\n * I / 0 = I\r\n * I / N = N\r\n * I / I = N\r\n *\r\n * Return a new BigNumber whose value is the value of this BigNumber divided by the value of\r\n * BigNumber(y, b), rounded according to DECIMAL_PLACES and ROUNDING_MODE.\r\n */\r\n P.dividedBy = P.div = function (y, b) {\r\n return div(this, new BigNumber(y, b), DECIMAL_PLACES, ROUNDING_MODE);\r\n };\r\n\r\n\r\n /*\r\n * Return a new BigNumber whose value is the integer part of dividing the value of this\r\n * BigNumber by the value of BigNumber(y, b).\r\n */\r\n P.dividedToIntegerBy = P.idiv = function (y, b) {\r\n return div(this, new BigNumber(y, b), 0, 1);\r\n };\r\n\r\n\r\n /*\r\n * Return a BigNumber whose value is the value of this BigNumber exponentiated by n.\r\n *\r\n * If m is present, return the result modulo m.\r\n * If n is negative round according to DECIMAL_PLACES and ROUNDING_MODE.\r\n * If POW_PRECISION is non-zero and m is not present, round to POW_PRECISION using ROUNDING_MODE.\r\n *\r\n * The modular power operation works efficiently when x, n, and m are integers, otherwise it\r\n * is equivalent to calculating x.exponentiatedBy(n).modulo(m) with a POW_PRECISION of 0.\r\n *\r\n * n {number|string|BigNumber} The exponent. An integer.\r\n * [m] {number|string|BigNumber} The modulus.\r\n *\r\n * '[BigNumber Error] Exponent not an integer: {n}'\r\n */\r\n P.exponentiatedBy = P.pow = function (n, m) {\r\n var half, isModExp, i, k, more, nIsBig, nIsNeg, nIsOdd, y,\r\n x = this;\r\n\r\n n = new BigNumber(n);\r\n\r\n // Allow NaN and ±Infinity, but not other non-integers.\r\n if (n.c && !n.isInteger()) {\r\n throw Error\r\n (bignumberError + 'Exponent not an integer: ' + valueOf(n));\r\n }\r\n\r\n if (m != null) m = new BigNumber(m);\r\n\r\n // Exponent of MAX_SAFE_INTEGER is 15.\r\n nIsBig = n.e > 14;\r\n\r\n // If x is NaN, ±Infinity, ±0 or ±1, or n is ±Infinity, NaN or ±0.\r\n if (!x.c || !x.c[0] || x.c[0] == 1 && !x.e && x.c.length == 1 || !n.c || !n.c[0]) {\r\n\r\n // The sign of the result of pow when x is negative depends on the evenness of n.\r\n // If +n overflows to ±Infinity, the evenness of n would be not be known.\r\n y = new BigNumber(Math.pow(+valueOf(x), nIsBig ? n.s * (2 - isOdd(n)) : +valueOf(n)));\r\n return m ? y.mod(m) : y;\r\n }\r\n\r\n nIsNeg = n.s < 0;\r\n\r\n if (m) {\r\n\r\n // x % m returns NaN if abs(m) is zero, or m is NaN.\r\n if (m.c ? !m.c[0] : !m.s) return new BigNumber(NaN);\r\n\r\n isModExp = !nIsNeg && x.isInteger() && m.isInteger();\r\n\r\n if (isModExp) x = x.mod(m);\r\n\r\n // Overflow to ±Infinity: >=2**1e10 or >=1.0000024**1e15.\r\n // Underflow to ±0: <=0.79**1e10 or <=0.9999975**1e15.\r\n } else if (n.e > 9 && (x.e > 0 || x.e < -1 || (x.e == 0\r\n // [1, 240000000]\r\n ? x.c[0] > 1 || nIsBig && x.c[1] >= 24e7\r\n // [80000000000000] [99999750000000]\r\n : x.c[0] < 8e13 || nIsBig && x.c[0] <= 9999975e7))) {\r\n\r\n // If x is negative and n is odd, k = -0, else k = 0.\r\n k = x.s < 0 && isOdd(n) ? -0 : 0;\r\n\r\n // If x >= 1, k = ±Infinity.\r\n if (x.e > -1) k = 1 / k;\r\n\r\n // If n is negative return ±0, else return ±Infinity.\r\n return new BigNumber(nIsNeg ? 1 / k : k);\r\n\r\n } else if (POW_PRECISION) {\r\n\r\n // Truncating each coefficient array to a length of k after each multiplication\r\n // equates to truncating significant digits to POW_PRECISION + [28, 41],\r\n // i.e. there will be a minimum of 28 guard digits retained.\r\n k = mathceil(POW_PRECISION / LOG_BASE + 2);\r\n }\r\n\r\n if (nIsBig) {\r\n half = new BigNumber(0.5);\r\n if (nIsNeg) n.s = 1;\r\n nIsOdd = isOdd(n);\r\n } else {\r\n i = Math.abs(+valueOf(n));\r\n nIsOdd = i % 2;\r\n }\r\n\r\n y = new BigNumber(ONE);\r\n\r\n // Performs 54 loop iterations for n of 9007199254740991.\r\n for (; ;) {\r\n\r\n if (nIsOdd) {\r\n y = y.times(x);\r\n if (!y.c) break;\r\n\r\n if (k) {\r\n if (y.c.length > k) y.c.length = k;\r\n } else if (isModExp) {\r\n y = y.mod(m); //y = y.minus(div(y, m, 0, MODULO_MODE).times(m));\r\n }\r\n }\r\n\r\n if (i) {\r\n i = mathfloor(i / 2);\r\n if (i === 0) break;\r\n nIsOdd = i % 2;\r\n } else {\r\n n = n.times(half);\r\n round(n, n.e + 1, 1);\r\n\r\n if (n.e > 14) {\r\n nIsOdd = isOdd(n);\r\n } else {\r\n i = +valueOf(n);\r\n if (i === 0) break;\r\n nIsOdd = i % 2;\r\n }\r\n }\r\n\r\n x = x.times(x);\r\n\r\n if (k) {\r\n if (x.c && x.c.length > k) x.c.length = k;\r\n } else if (isModExp) {\r\n x = x.mod(m); //x = x.minus(div(x, m, 0, MODULO_MODE).times(m));\r\n }\r\n }\r\n\r\n if (isModExp) return y;\r\n if (nIsNeg) y = ONE.div(y);\r\n\r\n return m ? y.mod(m) : k ? round(y, POW_PRECISION, ROUNDING_MODE, more) : y;\r\n };\r\n\r\n\r\n /*\r\n * Return a new BigNumber whose value is the value of this BigNumber rounded to an integer\r\n * using rounding mode rm, or ROUNDING_MODE if rm is omitted.\r\n *\r\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\r\n *\r\n * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {rm}'\r\n */\r\n P.integerValue = function (rm) {\r\n var n = new BigNumber(this);\r\n if (rm == null) rm = ROUNDING_MODE;\r\n else intCheck(rm, 0, 8);\r\n return round(n, n.e + 1, rm);\r\n };\r\n\r\n\r\n /*\r\n * Return true if the value of this BigNumber is equal to the value of BigNumber(y, b),\r\n * otherwise return false.\r\n */\r\n P.isEqualTo = P.eq = function (y, b) {\r\n return compare(this, new BigNumber(y, b)) === 0;\r\n };\r\n\r\n\r\n /*\r\n * Return true if the value of this BigNumber is a finite number, otherwise return false.\r\n */\r\n P.isFinite = function () {\r\n return !!this.c;\r\n };\r\n\r\n\r\n /*\r\n * Return true if the value of this BigNumber is greater than the value of BigNumber(y, b),\r\n * otherwise return false.\r\n */\r\n P.isGreaterThan = P.gt = function (y, b) {\r\n return compare(this, new BigNumber(y, b)) > 0;\r\n };\r\n\r\n\r\n /*\r\n * Return true if the value of this BigNumber is greater than or equal to the value of\r\n * BigNumber(y, b), otherwise return false.\r\n */\r\n P.isGreaterThanOrEqualTo = P.gte = function (y, b) {\r\n return (b = compare(this, new BigNumber(y, b))) === 1 || b === 0;\r\n\r\n };\r\n\r\n\r\n /*\r\n * Return true if the value of this BigNumber is an integer, otherwise return false.\r\n */\r\n P.isInteger = function () {\r\n return !!this.c && bitFloor(this.e / LOG_BASE) > this.c.length - 2;\r\n };\r\n\r\n\r\n /*\r\n * Return true if the value of this BigNumber is less than the value of BigNumber(y, b),\r\n * otherwise return false.\r\n */\r\n P.isLessThan = P.lt = function (y, b) {\r\n return compare(this, new BigNumber(y, b)) < 0;\r\n };\r\n\r\n\r\n /*\r\n * Return true if the value of this BigNumber is less than or equal to the value of\r\n * BigNumber(y, b), otherwise return false.\r\n */\r\n P.isLessThanOrEqualTo = P.lte = function (y, b) {\r\n return (b = compare(this, new BigNumber(y, b))) === -1 || b === 0;\r\n };\r\n\r\n\r\n /*\r\n * Return true if the value of this BigNumber is NaN, otherwise return false.\r\n */\r\n P.isNaN = function () {\r\n return !this.s;\r\n };\r\n\r\n\r\n /*\r\n * Return true if the value of this BigNumber is negative, otherwise return false.\r\n */\r\n P.isNegative = function () {\r\n return this.s < 0;\r\n };\r\n\r\n\r\n /*\r\n * Return true if the value of this BigNumber is positive, otherwise return false.\r\n */\r\n P.isPositive = function () {\r\n return this.s > 0;\r\n };\r\n\r\n\r\n /*\r\n * Return true if the value of this BigNumber is 0 or -0, otherwise return false.\r\n */\r\n P.isZero = function () {\r\n return !!this.c && this.c[0] == 0;\r\n };\r\n\r\n\r\n /*\r\n * n - 0 = n\r\n * n - N = N\r\n * n - I = -I\r\n * 0 - n = -n\r\n * 0 - 0 = 0\r\n * 0 - N = N\r\n * 0 - I = -I\r\n * N - n = N\r\n * N - 0 = N\r\n * N - N = N\r\n * N - I = N\r\n * I - n = I\r\n * I - 0 = I\r\n * I - N = N\r\n * I - I = N\r\n *\r\n * Return a new BigNumber whose value is the value of this BigNumber minus the value of\r\n * BigNumber(y, b).\r\n */\r\n P.minus = function (y, b) {\r\n var i, j, t, xLTy,\r\n x = this,\r\n a = x.s;\r\n\r\n y = new BigNumber(y, b);\r\n b = y.s;\r\n\r\n // Either NaN?\r\n if (!a || !b) return new BigNumber(NaN);\r\n\r\n // Signs differ?\r\n if (a != b) {\r\n y.s = -b;\r\n return x.plus(y);\r\n }\r\n\r\n var xe = x.e / LOG_BASE,\r\n ye = y.e / LOG_BASE,\r\n xc = x.c,\r\n yc = y.c;\r\n\r\n if (!xe || !ye) {\r\n\r\n // Either Infinity?\r\n if (!xc || !yc) return xc ? (y.s = -b, y) : new BigNumber(yc ? x : NaN);\r\n\r\n // Either zero?\r\n if (!xc[0] || !yc[0]) {\r\n\r\n // Return y if y is non-zero, x if x is non-zero, or zero if both are zero.\r\n return yc[0] ? (y.s = -b, y) : new BigNumber(xc[0] ? x :\r\n\r\n // IEEE 754 (2008) 6.3: n - n = -0 when rounding to -Infinity\r\n ROUNDING_MODE == 3 ? -0 : 0);\r\n }\r\n }\r\n\r\n xe = bitFloor(xe);\r\n ye = bitFloor(ye);\r\n xc = xc.slice();\r\n\r\n // Determine which is the bigger number.\r\n if (a = xe - ye) {\r\n\r\n if (xLTy = a < 0) {\r\n a = -a;\r\n t = xc;\r\n } else {\r\n ye = xe;\r\n t = yc;\r\n }\r\n\r\n t.reverse();\r\n\r\n // Prepend zeros to equalise exponents.\r\n for (b = a; b--; t.push(0));\r\n t.reverse();\r\n } else {\r\n\r\n // Exponents equal. Check digit by digit.\r\n j = (xLTy = (a = xc.length) < (b = yc.length)) ? a : b;\r\n\r\n for (a = b = 0; b < j; b++) {\r\n\r\n if (xc[b] != yc[b]) {\r\n xLTy = xc[b] < yc[b];\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // x < y? Point xc to the array of the bigger number.\r\n if (xLTy) {\r\n t = xc;\r\n xc = yc;\r\n yc = t;\r\n y.s = -y.s;\r\n }\r\n\r\n b = (j = yc.length) - (i = xc.length);\r\n\r\n // Append zeros to xc if shorter.\r\n // No need to add zeros to yc if shorter as subtract only needs to start at yc.length.\r\n if (b > 0) for (; b--; xc[i++] = 0);\r\n b = BASE - 1;\r\n\r\n // Subtract yc from xc.\r\n for (; j > a;) {\r\n\r\n if (xc[--j] < yc[j]) {\r\n for (i = j; i && !xc[--i]; xc[i] = b);\r\n --xc[i];\r\n xc[j] += BASE;\r\n }\r\n\r\n xc[j] -= yc[j];\r\n }\r\n\r\n // Remove leading zeros and adjust exponent accordingly.\r\n for (; xc[0] == 0; xc.splice(0, 1), --ye);\r\n\r\n // Zero?\r\n if (!xc[0]) {\r\n\r\n // Following IEEE 754 (2008) 6.3,\r\n // n - n = +0 but n - n = -0 when rounding towards -Infinity.\r\n y.s = ROUNDING_MODE == 3 ? -1 : 1;\r\n y.c = [y.e = 0];\r\n return y;\r\n }\r\n\r\n // No need to check for Infinity as +x - +y != Infinity && -x - -y != Infinity\r\n // for finite x and y.\r\n return normalise(y, xc, ye);\r\n };\r\n\r\n\r\n /*\r\n * n % 0 = N\r\n * n % N = N\r\n * n % I = n\r\n * 0 % n = 0\r\n * -0 % n = -0\r\n * 0 % 0 = N\r\n * 0 % N = N\r\n * 0 % I = 0\r\n * N % n = N\r\n * N % 0 = N\r\n * N % N = N\r\n * N % I = N\r\n * I % n = N\r\n * I % 0 = N\r\n * I % N = N\r\n * I % I = N\r\n *\r\n * Return a new BigNumber whose value is the value of this BigNumber modulo the value of\r\n * BigNumber(y, b). The result depends on the value of MODULO_MODE.\r\n */\r\n P.modulo = P.mod = function (y, b) {\r\n var q, s,\r\n x = this;\r\n\r\n y = new BigNumber(y, b);\r\n\r\n // Return NaN if x is Infinity or NaN, or y is NaN or zero.\r\n if (!x.c || !y.s || y.c && !y.c[0]) {\r\n return new BigNumber(NaN);\r\n\r\n // Return x if y is Infinity or x is zero.\r\n } else if (!y.c || x.c && !x.c[0]) {\r\n return new BigNumber(x);\r\n }\r\n\r\n if (MODULO_MODE == 9) {\r\n\r\n // Euclidian division: q = sign(y) * floor(x / abs(y))\r\n // r = x - qy where 0 <= r < abs(y)\r\n s = y.s;\r\n y.s = 1;\r\n q = div(x, y, 0, 3);\r\n y.s = s;\r\n q.s *= s;\r\n } else {\r\n q = div(x, y, 0, MODULO_MODE);\r\n }\r\n\r\n y = x.minus(q.times(y));\r\n\r\n // To match JavaScript %, ensure sign of zero is sign of dividend.\r\n if (!y.c[0] && MODULO_MODE == 1) y.s = x.s;\r\n\r\n return y;\r\n };\r\n\r\n\r\n /*\r\n * n * 0 = 0\r\n * n * N = N\r\n * n * I = I\r\n * 0 * n = 0\r\n * 0 * 0 = 0\r\n * 0 * N = N\r\n * 0 * I = N\r\n * N * n = N\r\n * N * 0 = N\r\n * N * N = N\r\n * N * I = N\r\n * I * n = I\r\n * I * 0 = N\r\n * I * N = N\r\n * I * I = I\r\n *\r\n * Return a new BigNumber whose value is the value of this BigNumber multiplied by the value\r\n * of BigNumber(y, b).\r\n */\r\n P.multipliedBy = P.times = function (y, b) {\r\n var c, e, i, j, k, m, xcL, xlo, xhi, ycL, ylo, yhi, zc,\r\n base, sqrtBase,\r\n x = this,\r\n xc = x.c,\r\n yc = (y = new BigNumber(y, b)).c;\r\n\r\n // Either NaN, ±Infinity or ±0?\r\n if (!xc || !yc || !xc[0] || !yc[0]) {\r\n\r\n // Return NaN if either is NaN, or one is 0 and the other is Infinity.\r\n if (!x.s || !y.s || xc && !xc[0] && !yc || yc && !yc[0] && !xc) {\r\n y.c = y.e = y.s = null;\r\n } else {\r\n y.s *= x.s;\r\n\r\n // Return ±Infinity if either is ±Infinity.\r\n if (!xc || !yc) {\r\n y.c = y.e = null;\r\n\r\n // Return ±0 if either is ±0.\r\n } else {\r\n y.c = [0];\r\n y.e = 0;\r\n }\r\n }\r\n\r\n return y;\r\n }\r\n\r\n e = bitFloor(x.e / LOG_BASE) + bitFloor(y.e / LOG_BASE);\r\n y.s *= x.s;\r\n xcL = xc.length;\r\n ycL = yc.length;\r\n\r\n // Ensure xc points to longer array and xcL to its length.\r\n if (xcL < ycL) {\r\n zc = xc;\r\n xc = yc;\r\n yc = zc;\r\n i = xcL;\r\n xcL = ycL;\r\n ycL = i;\r\n }\r\n\r\n // Initialise the result array with zeros.\r\n for (i = xcL + ycL, zc = []; i--; zc.push(0));\r\n\r\n base = BASE;\r\n sqrtBase = SQRT_BASE;\r\n\r\n for (i = ycL; --i >= 0;) {\r\n c = 0;\r\n ylo = yc[i] % sqrtBase;\r\n yhi = yc[i] / sqrtBase | 0;\r\n\r\n for (k = xcL, j = i + k; j > i;) {\r\n xlo = xc[--k] % sqrtBase;\r\n xhi = xc[k] / sqrtBase | 0;\r\n m = yhi * xlo + xhi * ylo;\r\n xlo = ylo * xlo + ((m % sqrtBase) * sqrtBase) + zc[j] + c;\r\n c = (xlo / base | 0) + (m / sqrtBase | 0) + yhi * xhi;\r\n zc[j--] = xlo % base;\r\n }\r\n\r\n zc[j] = c;\r\n }\r\n\r\n if (c) {\r\n ++e;\r\n } else {\r\n zc.splice(0, 1);\r\n }\r\n\r\n return normalise(y, zc, e);\r\n };\r\n\r\n\r\n /*\r\n * Return a new BigNumber whose value is the value of this BigNumber negated,\r\n * i.e. multiplied by -1.\r\n */\r\n P.negated = function () {\r\n var x = new BigNumber(this);\r\n x.s = -x.s || null;\r\n return x;\r\n };\r\n\r\n\r\n /*\r\n * n + 0 = n\r\n * n + N = N\r\n * n + I = I\r\n * 0 + n = n\r\n * 0 + 0 = 0\r\n * 0 + N = N\r\n * 0 + I = I\r\n * N + n = N\r\n * N + 0 = N\r\n * N + N = N\r\n * N + I = N\r\n * I + n = I\r\n * I + 0 = I\r\n * I + N = N\r\n * I + I = I\r\n *\r\n * Return a new BigNumber whose value is the value of this BigNumber plus the value of\r\n * BigNumber(y, b).\r\n */\r\n P.plus = function (y, b) {\r\n var t,\r\n x = this,\r\n a = x.s;\r\n\r\n y = new BigNumber(y, b);\r\n b = y.s;\r\n\r\n // Either NaN?\r\n if (!a || !b) return new BigNumber(NaN);\r\n\r\n // Signs differ?\r\n if (a != b) {\r\n y.s = -b;\r\n return x.minus(y);\r\n }\r\n\r\n var xe = x.e / LOG_BASE,\r\n ye = y.e / LOG_BASE,\r\n xc = x.c,\r\n yc = y.c;\r\n\r\n if (!xe || !ye) {\r\n\r\n // Return ±Infinity if either ±Infinity.\r\n if (!xc || !yc) return new BigNumber(a / 0);\r\n\r\n // Either zero?\r\n // Return y if y is non-zero, x if x is non-zero, or zero if both are zero.\r\n if (!xc[0] || !yc[0]) return yc[0] ? y : new BigNumber(xc[0] ? x : a * 0);\r\n }\r\n\r\n xe = bitFloor(xe);\r\n ye = bitFloor(ye);\r\n xc = xc.slice();\r\n\r\n // Prepend zeros to equalise exponents. Faster to use reverse then do unshifts.\r\n if (a = xe - ye) {\r\n if (a > 0) {\r\n ye = xe;\r\n t = yc;\r\n } else {\r\n a = -a;\r\n t = xc;\r\n }\r\n\r\n t.reverse();\r\n for (; a--; t.push(0));\r\n t.reverse();\r\n }\r\n\r\n a = xc.length;\r\n b = yc.length;\r\n\r\n // Point xc to the longer array, and b to the shorter length.\r\n if (a - b < 0) {\r\n t = yc;\r\n yc = xc;\r\n xc = t;\r\n b = a;\r\n }\r\n\r\n // Only start adding at yc.length - 1 as the further digits of xc can be ignored.\r\n for (a = 0; b;) {\r\n a = (xc[--b] = xc[b] + yc[b] + a) / BASE | 0;\r\n xc[b] = BASE === xc[b] ? 0 : xc[b] % BASE;\r\n }\r\n\r\n if (a) {\r\n xc = [a].concat(xc);\r\n ++ye;\r\n }\r\n\r\n // No need to check for zero, as +x + +y != 0 && -x + -y != 0\r\n // ye = MAX_EXP + 1 possible\r\n return normalise(y, xc, ye);\r\n };\r\n\r\n\r\n /*\r\n * If sd is undefined or null or true or false, return the number of significant digits of\r\n * the value of this BigNumber, or null if the value of this BigNumber is ±Infinity or NaN.\r\n * If sd is true include integer-part trailing zeros in the count.\r\n *\r\n * Otherwise, if sd is a number, return a new BigNumber whose value is the value of this\r\n * BigNumber rounded to a maximum of sd significant digits using rounding mode rm, or\r\n * ROUNDING_MODE if rm is omitted.\r\n *\r\n * sd {number|boolean} number: significant digits: integer, 1 to MAX inclusive.\r\n * boolean: whether to count integer-part trailing zeros: true or false.\r\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\r\n *\r\n * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {sd|rm}'\r\n */\r\n P.precision = P.sd = function (sd, rm) {\r\n var c, n, v,\r\n x = this;\r\n\r\n if (sd != null && sd !== !!sd) {\r\n intCheck(sd, 1, MAX);\r\n if (rm == null) rm = ROUNDING_MODE;\r\n else intCheck(rm, 0, 8);\r\n\r\n return round(new BigNumber(x), sd, rm);\r\n }\r\n\r\n if (!(c = x.c)) return null;\r\n v = c.length - 1;\r\n n = v * LOG_BASE + 1;\r\n\r\n if (v = c[v]) {\r\n\r\n // Subtract the number of trailing zeros of the last element.\r\n for (; v % 10 == 0; v /= 10, n--);\r\n\r\n // Add the number of digits of the first element.\r\n for (v = c[0]; v >= 10; v /= 10, n++);\r\n }\r\n\r\n if (sd && x.e + 1 > n) n = x.e + 1;\r\n\r\n return n;\r\n };\r\n\r\n\r\n /*\r\n * Return a new BigNumber whose value is the value of this BigNumber shifted by k places\r\n * (powers of 10). Shift to the right if n > 0, and to the left if n < 0.\r\n *\r\n * k {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive.\r\n *\r\n * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {k}'\r\n */\r\n P.shiftedBy = function (k) {\r\n intCheck(k, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER);\r\n return this.times('1e' + k);\r\n };\r\n\r\n\r\n /*\r\n * sqrt(-n) = N\r\n * sqrt(N) = N\r\n * sqrt(-I) = N\r\n * sqrt(I) = I\r\n * sqrt(0) = 0\r\n * sqrt(-0) = -0\r\n *\r\n * Return a new BigNumber whose value is the square root of the value of this BigNumber,\r\n * rounded according to DECIMAL_PLACES and ROUNDING_MODE.\r\n */\r\n P.squareRoot = P.sqrt = function () {\r\n var m, n, r, rep, t,\r\n x = this,\r\n c = x.c,\r\n s = x.s,\r\n e = x.e,\r\n dp = DECIMAL_PLACES + 4,\r\n half = new BigNumber('0.5');\r\n\r\n // Negative/NaN/Infinity/zero?\r\n if (s !== 1 || !c || !c[0]) {\r\n return new BigNumber(!s || s < 0 && (!c || c[0]) ? NaN : c ? x : 1 / 0);\r\n }\r\n\r\n // Initial estimate.\r\n s = Math.sqrt(+valueOf(x));\r\n\r\n // Math.sqrt underflow/overflow?\r\n // Pass x to Math.sqrt as integer, then adjust the exponent of the result.\r\n if (s == 0 || s == 1 / 0) {\r\n n = coeffToString(c);\r\n if ((n.length + e) % 2 == 0) n += '0';\r\n s = Math.sqrt(+n);\r\n e = bitFloor((e + 1) / 2) - (e < 0 || e % 2);\r\n\r\n if (s == 1 / 0) {\r\n n = '5e' + e;\r\n } else {\r\n n = s.toExponential();\r\n n = n.slice(0, n.indexOf('e') + 1) + e;\r\n }\r\n\r\n r = new BigNumber(n);\r\n } else {\r\n r = new BigNumber(s + '');\r\n }\r\n\r\n // Check for zero.\r\n // r could be zero if MIN_EXP is changed after the this value was created.\r\n // This would cause a division by zero (x/t) and hence Infinity below, which would cause\r\n // coeffToString to throw.\r\n if (r.c[0]) {\r\n e = r.e;\r\n s = e + dp;\r\n if (s < 3) s = 0;\r\n\r\n // Newton-Raphson iteration.\r\n for (; ;) {\r\n t = r;\r\n r = half.times(t.plus(div(x, t, dp, 1)));\r\n\r\n if (coeffToString(t.c).slice(0, s) === (n = coeffToString(r.c)).slice(0, s)) {\r\n\r\n // The exponent of r may here be one less than the final result exponent,\r\n // e.g 0.0009999 (e-4) --> 0.001 (e-3), so adjust s so the rounding digits\r\n // are indexed correctly.\r\n if (r.e < e) --s;\r\n n = n.slice(s - 3, s + 1);\r\n\r\n // The 4th rounding digit may be in error by -1 so if the 4 rounding digits\r\n // are 9999 or 4999 (i.e. approaching a rounding boundary) continue the\r\n // iteration.\r\n if (n == '9999' || !rep && n == '4999') {\r\n\r\n // On the first iteration only, check to see if rounding up gives the\r\n // exact result as the nines may infinitely repeat.\r\n if (!rep) {\r\n round(t, t.e + DECIMAL_PLACES + 2, 0);\r\n\r\n if (t.times(t).eq(x)) {\r\n r = t;\r\n break;\r\n }\r\n }\r\n\r\n dp += 4;\r\n s += 4;\r\n rep = 1;\r\n } else {\r\n\r\n // If rounding digits are null, 0{0,4} or 50{0,3}, check for exact\r\n // result. If not, then there are further digits and m will be truthy.\r\n if (!+n || !+n.slice(1) && n.charAt(0) == '5') {\r\n\r\n // Truncate to the first rounding digit.\r\n round(r, r.e + DECIMAL_PLACES + 2, 1);\r\n m = !r.times(r).eq(x);\r\n }\r\n\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return round(r, r.e + DECIMAL_PLACES + 1, ROUNDING_MODE, m);\r\n };\r\n\r\n\r\n /*\r\n * Return a string representing the value of this BigNumber in exponential notation and\r\n * rounded using ROUNDING_MODE to dp fixed decimal places.\r\n *\r\n * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.\r\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\r\n *\r\n * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}'\r\n */\r\n P.toExponential = function (dp, rm) {\r\n if (dp != null) {\r\n intCheck(dp, 0, MAX);\r\n dp++;\r\n }\r\n return format(this, dp, rm, 1);\r\n };\r\n\r\n\r\n /*\r\n * Return a string representing the value of this BigNumber in fixed-point notation rounding\r\n * to dp fixed decimal places using rounding mode rm, or ROUNDING_MODE if rm is omitted.\r\n *\r\n * Note: as with JavaScript's number type, (-0).toFixed(0) is '0',\r\n * but e.g. (-0.00001).toFixed(0) is '-0'.\r\n *\r\n * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.\r\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\r\n *\r\n * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}'\r\n */\r\n P.toFixed = function (dp, rm) {\r\n if (dp != null) {\r\n intCheck(dp, 0, MAX);\r\n dp = dp + this.e + 1;\r\n }\r\n return format(this, dp, rm);\r\n };\r\n\r\n\r\n /*\r\n * Return a string representing the value of this BigNumber in fixed-point notation rounded\r\n * using rm or ROUNDING_MODE to dp decimal places, and formatted according to the properties\r\n * of the format or FORMAT object (see BigNumber.set).\r\n *\r\n * The formatting object may contain some or all of the properties shown below.\r\n *\r\n * FORMAT = {\r\n * prefix: '',\r\n * groupSize: 3,\r\n * secondaryGroupSize: 0,\r\n * groupSeparator: ',',\r\n * decimalSeparator: '.',\r\n * fractionGroupSize: 0,\r\n * fractionGroupSeparator: '\\xA0', // non-breaking space\r\n * suffix: ''\r\n * };\r\n *\r\n * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.\r\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\r\n * [format] {object} Formatting options. See FORMAT pbject above.\r\n *\r\n * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}'\r\n * '[BigNumber Error] Argument not an object: {format}'\r\n */\r\n P.toFormat = function (dp, rm, format) {\r\n var str,\r\n x = this;\r\n\r\n if (format == null) {\r\n if (dp != null && rm && typeof rm == 'object') {\r\n format = rm;\r\n rm = null;\r\n } else if (dp && typeof dp == 'object') {\r\n format = dp;\r\n dp = rm = null;\r\n } else {\r\n format = FORMAT;\r\n }\r\n } else if (typeof format != 'object') {\r\n throw Error\r\n (bignumberError + 'Argument not an object: ' + format);\r\n }\r\n\r\n str = x.toFixed(dp, rm);\r\n\r\n if (x.c) {\r\n var i,\r\n arr = str.split('.'),\r\n g1 = +format.groupSize,\r\n g2 = +format.secondaryGroupSize,\r\n groupSeparator = format.groupSeparator || '',\r\n intPart = arr[0],\r\n fractionPart = arr[1],\r\n isNeg = x.s < 0,\r\n intDigits = isNeg ? intPart.slice(1) : intPart,\r\n len = intDigits.length;\r\n\r\n if (g2) {\r\n i = g1;\r\n g1 = g2;\r\n g2 = i;\r\n len -= i;\r\n }\r\n\r\n if (g1 > 0 && len > 0) {\r\n i = len % g1 || g1;\r\n intPart = intDigits.substr(0, i);\r\n for (; i < len; i += g1) intPart += groupSeparator + intDigits.substr(i, g1);\r\n if (g2 > 0) intPart += groupSeparator + intDigits.slice(i);\r\n if (isNeg) intPart = '-' + intPart;\r\n }\r\n\r\n str = fractionPart\r\n ? intPart + (format.decimalSeparator || '') + ((g2 = +format.fractionGroupSize)\r\n ? fractionPart.replace(new RegExp('\\\\d{' + g2 + '}\\\\B', 'g'),\r\n '$&' + (format.fractionGroupSeparator || ''))\r\n : fractionPart)\r\n : intPart;\r\n }\r\n\r\n return (format.prefix || '') + str + (format.suffix || '');\r\n };\r\n\r\n\r\n /*\r\n * Return an array of two BigNumbers representing the value of this BigNumber as a simple\r\n * fraction with an integer numerator and an integer denominator.\r\n * The denominator will be a positive non-zero value less than or equal to the specified\r\n * maximum denominator. If a maximum denominator is not specified, the denominator will be\r\n * the lowest value necessary to represent the number exactly.\r\n *\r\n * [md] {number|string|BigNumber} Integer >= 1, or Infinity. The maximum denominator.\r\n *\r\n * '[BigNumber Error] Argument {not an integer|out of range} : {md}'\r\n */\r\n P.toFraction = function (md) {\r\n var d, d0, d1, d2, e, exp, n, n0, n1, q, r, s,\r\n x = this,\r\n xc = x.c;\r\n\r\n if (md != null) {\r\n n = new BigNumber(md);\r\n\r\n // Throw if md is less than one or is not an integer, unless it is Infinity.\r\n if (!n.isInteger() && (n.c || n.s !== 1) || n.lt(ONE)) {\r\n throw Error\r\n (bignumberError + 'Argument ' +\r\n (n.isInteger() ? 'out of range: ' : 'not an integer: ') + valueOf(n));\r\n }\r\n }\r\n\r\n if (!xc) return new BigNumber(x);\r\n\r\n d = new BigNumber(ONE);\r\n n1 = d0 = new BigNumber(ONE);\r\n d1 = n0 = new BigNumber(ONE);\r\n s = coeffToString(xc);\r\n\r\n // Determine initial denominator.\r\n // d is a power of 10 and the minimum max denominator that specifies the value exactly.\r\n e = d.e = s.length - x.e - 1;\r\n d.c[0] = POWS_TEN[(exp = e % LOG_BASE) < 0 ? LOG_BASE + exp : exp];\r\n md = !md || n.comparedTo(d) > 0 ? (e > 0 ? d : n1) : n;\r\n\r\n exp = MAX_EXP;\r\n MAX_EXP = 1 / 0;\r\n n = new BigNumber(s);\r\n\r\n // n0 = d1 = 0\r\n n0.c[0] = 0;\r\n\r\n for (; ;) {\r\n q = div(n, d, 0, 1);\r\n d2 = d0.plus(q.times(d1));\r\n if (d2.comparedTo(md) == 1) break;\r\n d0 = d1;\r\n d1 = d2;\r\n n1 = n0.plus(q.times(d2 = n1));\r\n n0 = d2;\r\n d = n.minus(q.times(d2 = d));\r\n n = d2;\r\n }\r\n\r\n d2 = div(md.minus(d0), d1, 0, 1);\r\n n0 = n0.plus(d2.times(n1));\r\n d0 = d0.plus(d2.times(d1));\r\n n0.s = n1.s = x.s;\r\n e = e * 2;\r\n\r\n // Determine which fraction is closer to x, n0/d0 or n1/d1\r\n r = div(n1, d1, e, ROUNDING_MODE).minus(x).abs().comparedTo(\r\n div(n0, d0, e, ROUNDING_MODE).minus(x).abs()) < 1 ? [n1, d1] : [n0, d0];\r\n\r\n MAX_EXP = exp;\r\n\r\n return r;\r\n };\r\n\r\n\r\n /*\r\n * Return the value of this BigNumber converted to a number primitive.\r\n */\r\n P.toNumber = function () {\r\n return +valueOf(this);\r\n };\r\n\r\n\r\n /*\r\n * Return a string representing the value of this BigNumber rounded to sd significant digits\r\n * using rounding mode rm or ROUNDING_MODE. If sd is less than the number of digits\r\n * necessary to represent the integer part of the value in fixed-point notation, then use\r\n * exponential notation.\r\n *\r\n * [sd] {number} Significant digits. Integer, 1 to MAX inclusive.\r\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\r\n *\r\n * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {sd|rm}'\r\n */\r\n P.toPrecision = function (sd, rm) {\r\n if (sd != null) intCheck(sd, 1, MAX);\r\n return format(this, sd, rm, 2);\r\n };\r\n\r\n\r\n /*\r\n * Return a string representing the value of this BigNumber in base b, or base 10 if b is\r\n * omitted. If a base is specified, including base 10, round according to DECIMAL_PLACES and\r\n * ROUNDING_MODE. If a base is not specified, and this BigNumber has a positive exponent\r\n * that is equal to or greater than TO_EXP_POS, or a negative exponent equal to or less than\r\n * TO_EXP_NEG, return exponential notation.\r\n *\r\n * [b] {number} Integer, 2 to ALPHABET.length inclusive.\r\n *\r\n * '[BigNumber Error] Base {not a primitive number|not an integer|out of range}: {b}'\r\n */\r\n P.toString = function (b) {\r\n var str,\r\n n = this,\r\n s = n.s,\r\n e = n.e;\r\n\r\n // Infinity or NaN?\r\n if (e === null) {\r\n if (s) {\r\n str = 'Infinity';\r\n if (s < 0) str = '-' + str;\r\n } else {\r\n str = 'NaN';\r\n }\r\n } else {\r\n if (b == null) {\r\n str = e <= TO_EXP_NEG || e >= TO_EXP_POS\r\n ? toExponential(coeffToString(n.c), e)\r\n : toFixedPoint(coeffToString(n.c), e, '0');\r\n } else if (b === 10 && alphabetHasNormalDecimalDigits) {\r\n n = round(new BigNumber(n), DECIMAL_PLACES + e + 1, ROUNDING_MODE);\r\n str = toFixedPoint(coeffToString(n.c), n.e, '0');\r\n } else {\r\n intCheck(b, 2, ALPHABET.length, 'Base');\r\n str = convertBase(toFixedPoint(coeffToString(n.c), e, '0'), 10, b, s, true);\r\n }\r\n\r\n if (s < 0 && n.c[0]) str = '-' + str;\r\n }\r\n\r\n return str;\r\n };\r\n\r\n\r\n /*\r\n * Return as toString, but do not accept a base argument, and include the minus sign for\r\n * negative zero.\r\n */\r\n P.valueOf = P.toJSON = function () {\r\n return valueOf(this);\r\n };\r\n\r\n\r\n P._isBigNumber = true;\r\n\r\n P[Symbol.toStringTag] = 'BigNumber';\r\n\r\n // Node.js v10.12.0+\r\n P[Symbol.for('nodejs.util.inspect.custom')] = P.valueOf;\r\n\r\n if (configObject != null) BigNumber.set(configObject);\r\n\r\n return BigNumber;\r\n}\r\n\r\n\r\n// PRIVATE HELPER FUNCTIONS\r\n\r\n// These functions don't need access to variables,\r\n// e.g. DECIMAL_PLACES, in the scope of the `clone` function above.\r\n\r\n\r\nfunction bitFloor(n) {\r\n var i = n | 0;\r\n return n > 0 || n === i ? i : i - 1;\r\n}\r\n\r\n\r\n// Return a coefficient array as a string of base 10 digits.\r\nfunction coeffToString(a) {\r\n var s, z,\r\n i = 1,\r\n j = a.length,\r\n r = a[0] + '';\r\n\r\n for (; i < j;) {\r\n s = a[i++] + '';\r\n z = LOG_BASE - s.length;\r\n for (; z--; s = '0' + s);\r\n r += s;\r\n }\r\n\r\n // Determine trailing zeros.\r\n for (j = r.length; r.charCodeAt(--j) === 48;);\r\n\r\n return r.slice(0, j + 1 || 1);\r\n}\r\n\r\n\r\n// Compare the value of BigNumbers x and y.\r\nfunction compare(x, y) {\r\n var a, b,\r\n xc = x.c,\r\n yc = y.c,\r\n i = x.s,\r\n j = y.s,\r\n k = x.e,\r\n l = y.e;\r\n\r\n // Either NaN?\r\n if (!i || !j) return null;\r\n\r\n a = xc && !xc[0];\r\n b = yc && !yc[0];\r\n\r\n // Either zero?\r\n if (a || b) return a ? b ? 0 : -j : i;\r\n\r\n // Signs differ?\r\n if (i != j) return i;\r\n\r\n a = i < 0;\r\n b = k == l;\r\n\r\n // Either Infinity?\r\n if (!xc || !yc) return b ? 0 : !xc ^ a ? 1 : -1;\r\n\r\n // Compare exponents.\r\n if (!b) return k > l ^ a ? 1 : -1;\r\n\r\n j = (k = xc.length) < (l = yc.length) ? k : l;\r\n\r\n // Compare digit by digit.\r\n for (i = 0; i < j; i++) if (xc[i] != yc[i]) return xc[i] > yc[i] ^ a ? 1 : -1;\r\n\r\n // Compare lengths.\r\n return k == l ? 0 : k > l ^ a ? 1 : -1;\r\n}\r\n\r\n\r\n/*\r\n * Check that n is a primitive number, an integer, and in range, otherwise throw.\r\n */\r\nfunction intCheck(n, min, max, name) {\r\n if (n < min || n > max || n !== mathfloor(n)) {\r\n throw Error\r\n (bignumberError + (name || 'Argument') + (typeof n == 'number'\r\n ? n < min || n > max ? ' out of range: ' : ' not an integer: '\r\n : ' not a primitive number: ') + String(n));\r\n }\r\n}\r\n\r\n\r\n// Assumes finite n.\r\nfunction isOdd(n) {\r\n var k = n.c.length - 1;\r\n return bitFloor(n.e / LOG_BASE) == k && n.c[k] % 2 != 0;\r\n}\r\n\r\n\r\nfunction toExponential(str, e) {\r\n return (str.length > 1 ? str.charAt(0) + '.' + str.slice(1) : str) +\r\n (e < 0 ? 'e' : 'e+') + e;\r\n}\r\n\r\n\r\nfunction toFixedPoint(str, e, z) {\r\n var len, zs;\r\n\r\n // Negative exponent?\r\n if (e < 0) {\r\n\r\n // Prepend zeros.\r\n for (zs = z + '.'; ++e; zs += z);\r\n str = zs + str;\r\n\r\n // Positive exponent\r\n } else {\r\n len = str.length;\r\n\r\n // Append zeros.\r\n if (++e > len) {\r\n for (zs = z, e -= len; --e; zs += z);\r\n str += zs;\r\n } else if (e < len) {\r\n str = str.slice(0, e) + '.' + str.slice(e);\r\n }\r\n }\r\n\r\n return str;\r\n}\r\n\r\n\r\n// EXPORT\r\n\r\n\r\nexport var BigNumber = clone();\r\n\r\nexport default BigNumber;\r\n","class SplayTreeNode {\r\n key;\r\n left = null;\r\n right = null;\r\n constructor(key) {\r\n this.key = key;\r\n }\r\n}\r\nclass SplayTreeSetNode extends SplayTreeNode {\r\n constructor(key) {\r\n super(key);\r\n }\r\n}\r\nclass SplayTreeMapNode extends SplayTreeNode {\r\n value;\r\n constructor(key, value) {\r\n super(key);\r\n this.value = value;\r\n }\r\n replaceValue(value) {\r\n const node = new SplayTreeMapNode(this.key, value);\r\n node.left = this.left;\r\n node.right = this.right;\r\n return node;\r\n }\r\n}\r\nclass SplayTree {\r\n size = 0;\r\n modificationCount = 0;\r\n splayCount = 0;\r\n splay(key) {\r\n const root = this.root;\r\n if (root == null) {\r\n this.compare(key, key);\r\n return -1;\r\n }\r\n let right = null;\r\n let newTreeRight = null;\r\n let left = null;\r\n let newTreeLeft = null;\r\n let current = root;\r\n const compare = this.compare;\r\n let comp;\r\n while (true) {\r\n comp = compare(current.key, key);\r\n if (comp > 0) {\r\n let currentLeft = current.left;\r\n if (currentLeft == null)\r\n break;\r\n comp = compare(currentLeft.key, key);\r\n if (comp > 0) {\r\n current.left = currentLeft.right;\r\n currentLeft.right = current;\r\n current = currentLeft;\r\n currentLeft = current.left;\r\n if (currentLeft == null)\r\n break;\r\n }\r\n if (right == null) {\r\n newTreeRight = current;\r\n }\r\n else {\r\n right.left = current;\r\n }\r\n right = current;\r\n current = currentLeft;\r\n }\r\n else if (comp < 0) {\r\n let currentRight = current.right;\r\n if (currentRight == null)\r\n break;\r\n comp = compare(currentRight.key, key);\r\n if (comp < 0) {\r\n current.right = currentRight.left;\r\n currentRight.left = current;\r\n current = currentRight;\r\n currentRight = current.right;\r\n if (currentRight == null)\r\n break;\r\n }\r\n if (left == null) {\r\n newTreeLeft = current;\r\n }\r\n else {\r\n left.right = current;\r\n }\r\n left = current;\r\n current = currentRight;\r\n }\r\n else {\r\n break;\r\n }\r\n }\r\n if (left != null) {\r\n left.right = current.left;\r\n current.left = newTreeLeft;\r\n }\r\n if (right != null) {\r\n right.left = current.right;\r\n current.right = newTreeRight;\r\n }\r\n if (this.root !== current) {\r\n this.root = current;\r\n this.splayCount++;\r\n }\r\n return comp;\r\n }\r\n splayMin(node) {\r\n let current = node;\r\n let nextLeft = current.left;\r\n while (nextLeft != null) {\r\n const left = nextLeft;\r\n current.left = left.right;\r\n left.right = current;\r\n current = left;\r\n nextLeft = current.left;\r\n }\r\n return current;\r\n }\r\n splayMax(node) {\r\n let current = node;\r\n let nextRight = current.right;\r\n while (nextRight != null) {\r\n const right = nextRight;\r\n current.right = right.left;\r\n right.left = current;\r\n current = right;\r\n nextRight = current.right;\r\n }\r\n return current;\r\n }\r\n _delete(key) {\r\n if (this.root == null)\r\n return null;\r\n const comp = this.splay(key);\r\n if (comp != 0)\r\n return null;\r\n let root = this.root;\r\n const result = root;\r\n const left = root.left;\r\n this.size--;\r\n if (left == null) {\r\n this.root = root.right;\r\n }\r\n else {\r\n const right = root.right;\r\n root = this.splayMax(left);\r\n root.right = right;\r\n this.root = root;\r\n }\r\n this.modificationCount++;\r\n return result;\r\n }\r\n addNewRoot(node, comp) {\r\n this.size++;\r\n this.modificationCount++;\r\n const root = this.root;\r\n if (root == null) {\r\n this.root = node;\r\n return;\r\n }\r\n if (comp < 0) {\r\n node.left = root;\r\n node.right = root.right;\r\n root.right = null;\r\n }\r\n else {\r\n node.right = root;\r\n node.left = root.left;\r\n root.left = null;\r\n }\r\n this.root = node;\r\n }\r\n _first() {\r\n const root = this.root;\r\n if (root == null)\r\n return null;\r\n this.root = this.splayMin(root);\r\n return this.root;\r\n }\r\n _last() {\r\n const root = this.root;\r\n if (root == null)\r\n return null;\r\n this.root = this.splayMax(root);\r\n return this.root;\r\n }\r\n clear() {\r\n this.root = null;\r\n this.size = 0;\r\n this.modificationCount++;\r\n }\r\n has(key) {\r\n return this.validKey(key) && this.splay(key) == 0;\r\n }\r\n defaultCompare() {\r\n return (a, b) => a < b ? -1 : a > b ? 1 : 0;\r\n }\r\n wrap() {\r\n return {\r\n getRoot: () => { return this.root; },\r\n setRoot: (root) => { this.root = root; },\r\n getSize: () => { return this.size; },\r\n getModificationCount: () => { return this.modificationCount; },\r\n getSplayCount: () => { return this.splayCount; },\r\n setSplayCount: (count) => { this.splayCount = count; },\r\n splay: (key) => { return this.splay(key); },\r\n has: (key) => { return this.has(key); },\r\n };\r\n }\r\n}\r\nexport class SplayTreeMap extends SplayTree {\r\n root = null;\r\n compare;\r\n validKey;\r\n constructor(compare, isValidKey) {\r\n super();\r\n this.compare = compare ?? this.defaultCompare();\r\n this.validKey = isValidKey ?? ((a) => a != null && a != undefined);\r\n }\r\n delete(key) {\r\n if (!this.validKey(key))\r\n return false;\r\n return this._delete(key) != null;\r\n }\r\n forEach(f) {\r\n const nodes = new SplayTreeMapEntryIterableIterator(this.wrap());\r\n let result;\r\n while (result = nodes.next(), !result.done) {\r\n f(result.value[1], result.value[0], this);\r\n }\r\n }\r\n get(key) {\r\n if (!this.validKey(key))\r\n return undefined;\r\n if (this.root != null) {\r\n const comp = this.splay(key);\r\n if (comp == 0) {\r\n return this.root.value;\r\n }\r\n }\r\n return undefined;\r\n }\r\n hasValue(value) {\r\n const initialSplayCount = this.splayCount;\r\n const visit = (node) => {\r\n while (node != null) {\r\n if (node.value == value)\r\n return true;\r\n if (initialSplayCount != this.splayCount) {\r\n throw \"Concurrent modification during iteration.\";\r\n }\r\n if (node.right != null && visit(node.right)) {\r\n return true;\r\n }\r\n node = node.left;\r\n }\r\n return false;\r\n };\r\n return visit(this.root);\r\n }\r\n set(key, value) {\r\n const comp = this.splay(key);\r\n if (comp == 0) {\r\n this.root = this.root.replaceValue(value);\r\n this.splayCount += 1;\r\n return this;\r\n }\r\n this.addNewRoot(new SplayTreeMapNode(key, value), comp);\r\n return this;\r\n }\r\n setAll(other) {\r\n other.forEach((value, key) => {\r\n this.set(key, value);\r\n });\r\n }\r\n setIfAbsent(key, ifAbsent) {\r\n let comp = this.splay(key);\r\n if (comp == 0) {\r\n return this.root.value;\r\n }\r\n const modificationCount = this.modificationCount;\r\n const splayCount = this.splayCount;\r\n const value = ifAbsent();\r\n if (modificationCount != this.modificationCount) {\r\n throw \"Concurrent modification during iteration.\";\r\n }\r\n if (splayCount != this.splayCount) {\r\n comp = this.splay(key);\r\n }\r\n this.addNewRoot(new SplayTreeMapNode(key, value), comp);\r\n return value;\r\n }\r\n isEmpty() {\r\n return this.root == null;\r\n }\r\n isNotEmpty() {\r\n return !this.isEmpty();\r\n }\r\n firstKey() {\r\n if (this.root == null)\r\n return null;\r\n return this._first().key;\r\n }\r\n lastKey() {\r\n if (this.root == null)\r\n return null;\r\n return this._last().key;\r\n }\r\n lastKeyBefore(key) {\r\n if (key == null)\r\n throw \"Invalid arguments(s)\";\r\n if (this.root == null)\r\n return null;\r\n const comp = this.splay(key);\r\n if (comp < 0)\r\n return this.root.key;\r\n let node = this.root.left;\r\n if (node == null)\r\n return null;\r\n let nodeRight = node.right;\r\n while (nodeRight != null) {\r\n node = nodeRight;\r\n nodeRight = node.right;\r\n }\r\n return node.key;\r\n }\r\n firstKeyAfter(key) {\r\n if (key == null)\r\n throw \"Invalid arguments(s)\";\r\n if (this.root == null)\r\n return null;\r\n const comp = this.splay(key);\r\n if (comp > 0)\r\n return this.root.key;\r\n let node = this.root.right;\r\n if (node == null)\r\n return null;\r\n let nodeLeft = node.left;\r\n while (nodeLeft != null) {\r\n node = nodeLeft;\r\n nodeLeft = node.left;\r\n }\r\n return node.key;\r\n }\r\n update(key, update, ifAbsent) {\r\n let comp = this.splay(key);\r\n if (comp == 0) {\r\n const modificationCount = this.modificationCount;\r\n const splayCount = this.splayCount;\r\n const newValue = update(this.root.value);\r\n if (modificationCount != this.modificationCount) {\r\n throw \"Concurrent modification during iteration.\";\r\n }\r\n if (splayCount != this.splayCount) {\r\n this.splay(key);\r\n }\r\n this.root = this.root.replaceValue(newValue);\r\n this.splayCount += 1;\r\n return newValue;\r\n }\r\n if (ifAbsent != null) {\r\n const modificationCount = this.modificationCount;\r\n const splayCount = this.splayCount;\r\n const newValue = ifAbsent();\r\n if (modificationCount != this.modificationCount) {\r\n throw \"Concurrent modification during iteration.\";\r\n }\r\n if (splayCount != this.splayCount) {\r\n comp = this.splay(key);\r\n }\r\n this.addNewRoot(new SplayTreeMapNode(key, newValue), comp);\r\n return newValue;\r\n }\r\n throw \"Invalid argument (key): Key not in map.\";\r\n }\r\n updateAll(update) {\r\n const root = this.root;\r\n if (root == null)\r\n return;\r\n const iterator = new SplayTreeMapEntryIterableIterator(this.wrap());\r\n let node;\r\n while (node = iterator.next(), !node.done) {\r\n const newValue = update(...node.value);\r\n iterator.replaceValue(newValue);\r\n }\r\n }\r\n keys() {\r\n return new SplayTreeKeyIterableIterator(this.wrap());\r\n }\r\n values() {\r\n return new SplayTreeValueIterableIterator(this.wrap());\r\n }\r\n entries() {\r\n return this[Symbol.iterator]();\r\n }\r\n [Symbol.iterator]() {\r\n return new SplayTreeMapEntryIterableIterator(this.wrap());\r\n }\r\n [Symbol.toStringTag] = '[object Map]';\r\n}\r\nexport class SplayTreeSet extends SplayTree {\r\n root = null;\r\n compare;\r\n validKey;\r\n constructor(compare, isValidKey) {\r\n super();\r\n this.compare = compare ?? this.defaultCompare();\r\n this.validKey = isValidKey ?? ((v) => v != null && v != undefined);\r\n }\r\n delete(element) {\r\n if (!this.validKey(element))\r\n return false;\r\n return this._delete(element) != null;\r\n }\r\n deleteAll(elements) {\r\n for (const element of elements) {\r\n this.delete(element);\r\n }\r\n }\r\n forEach(f) {\r\n const nodes = this[Symbol.iterator]();\r\n let result;\r\n while (result = nodes.next(), !result.done) {\r\n f(result.value, result.value, this);\r\n }\r\n }\r\n add(element) {\r\n const compare = this.splay(element);\r\n if (compare != 0)\r\n this.addNewRoot(new SplayTreeSetNode(element), compare);\r\n return this;\r\n }\r\n addAndReturn(element) {\r\n const compare = this.splay(element);\r\n if (compare != 0)\r\n this.addNewRoot(new SplayTreeSetNode(element), compare);\r\n return this.root.key;\r\n }\r\n addAll(elements) {\r\n for (const element of elements) {\r\n this.add(element);\r\n }\r\n }\r\n isEmpty() {\r\n return this.root == null;\r\n }\r\n isNotEmpty() {\r\n return this.root != null;\r\n }\r\n single() {\r\n if (this.size == 0)\r\n throw \"Bad state: No element\";\r\n if (this.size > 1)\r\n throw \"Bad state: Too many element\";\r\n return this.root.key;\r\n }\r\n first() {\r\n if (this.size == 0)\r\n throw \"Bad state: No element\";\r\n return this._first().key;\r\n }\r\n last() {\r\n if (this.size == 0)\r\n throw \"Bad state: No element\";\r\n return this._last().key;\r\n }\r\n lastBefore(element) {\r\n if (element == null)\r\n throw \"Invalid arguments(s)\";\r\n if (this.root == null)\r\n return null;\r\n const comp = this.splay(element);\r\n if (comp < 0)\r\n return this.root.key;\r\n let node = this.root.left;\r\n if (node == null)\r\n return null;\r\n let nodeRight = node.right;\r\n while (nodeRight != null) {\r\n node = nodeRight;\r\n nodeRight = node.right;\r\n }\r\n return node.key;\r\n }\r\n firstAfter(element) {\r\n if (element == null)\r\n throw \"Invalid arguments(s)\";\r\n if (this.root == null)\r\n return null;\r\n const comp = this.splay(element);\r\n if (comp > 0)\r\n return this.root.key;\r\n let node = this.root.right;\r\n if (node == null)\r\n return null;\r\n let nodeLeft = node.left;\r\n while (nodeLeft != null) {\r\n node = nodeLeft;\r\n nodeLeft = node.left;\r\n }\r\n return node.key;\r\n }\r\n retainAll(elements) {\r\n const retainSet = new SplayTreeSet(this.compare, this.validKey);\r\n const modificationCount = this.modificationCount;\r\n for (const object of elements) {\r\n if (modificationCount != this.modificationCount) {\r\n throw \"Concurrent modification during iteration.\";\r\n }\r\n if (this.validKey(object) && this.splay(object) == 0) {\r\n retainSet.add(this.root.key);\r\n }\r\n }\r\n if (retainSet.size != this.size) {\r\n this.root = retainSet.root;\r\n this.size = retainSet.size;\r\n this.modificationCount++;\r\n }\r\n }\r\n lookup(object) {\r\n if (!this.validKey(object))\r\n return null;\r\n const comp = this.splay(object);\r\n if (comp != 0)\r\n return null;\r\n return this.root.key;\r\n }\r\n intersection(other) {\r\n const result = new SplayTreeSet(this.compare, this.validKey);\r\n for (const element of this) {\r\n if (other.has(element))\r\n result.add(element);\r\n }\r\n return result;\r\n }\r\n difference(other) {\r\n const result = new SplayTreeSet(this.compare, this.validKey);\r\n for (const element of this) {\r\n if (!other.has(element))\r\n result.add(element);\r\n }\r\n return result;\r\n }\r\n union(other) {\r\n const u = this.clone();\r\n u.addAll(other);\r\n return u;\r\n }\r\n clone() {\r\n const set = new SplayTreeSet(this.compare, this.validKey);\r\n set.size = this.size;\r\n set.root = this.copyNode(this.root);\r\n return set;\r\n }\r\n copyNode(node) {\r\n if (node == null)\r\n return null;\r\n function copyChildren(node, dest) {\r\n let left;\r\n let right;\r\n do {\r\n left = node.left;\r\n right = node.right;\r\n if (left != null) {\r\n const newLeft = new SplayTreeSetNode(left.key);\r\n dest.left = newLeft;\r\n copyChildren(left, newLeft);\r\n }\r\n if (right != null) {\r\n const newRight = new SplayTreeSetNode(right.key);\r\n dest.right = newRight;\r\n node = right;\r\n dest = newRight;\r\n }\r\n } while (right != null);\r\n }\r\n const result = new SplayTreeSetNode(node.key);\r\n copyChildren(node, result);\r\n return result;\r\n }\r\n toSet() {\r\n return this.clone();\r\n }\r\n entries() {\r\n return new SplayTreeSetEntryIterableIterator(this.wrap());\r\n }\r\n keys() {\r\n return this[Symbol.iterator]();\r\n }\r\n values() {\r\n return this[Symbol.iterator]();\r\n }\r\n [Symbol.iterator]() {\r\n return new SplayTreeKeyIterableIterator(this.wrap());\r\n }\r\n [Symbol.toStringTag] = '[object Set]';\r\n}\r\nclass SplayTreeIterableIterator {\r\n tree;\r\n path = new Array();\r\n modificationCount = null;\r\n splayCount;\r\n constructor(tree) {\r\n this.tree = tree;\r\n this.splayCount = tree.getSplayCount();\r\n }\r\n [Symbol.iterator]() {\r\n return this;\r\n }\r\n next() {\r\n if (this.moveNext())\r\n return { done: false, value: this.current() };\r\n return { done: true, value: null };\r\n }\r\n current() {\r\n if (!this.path.length)\r\n return null;\r\n const node = this.path[this.path.length - 1];\r\n return this.getValue(node);\r\n }\r\n rebuildPath(key) {\r\n this.path.splice(0, this.path.length);\r\n this.tree.splay(key);\r\n this.path.push(this.tree.getRoot());\r\n this.splayCount = this.tree.getSplayCount();\r\n }\r\n findLeftMostDescendent(node) {\r\n while (node != null) {\r\n this.path.push(node);\r\n node = node.left;\r\n }\r\n }\r\n moveNext() {\r\n if (this.modificationCount != this.tree.getModificationCount()) {\r\n if (this.modificationCount == null) {\r\n this.modificationCount = this.tree.getModificationCount();\r\n let node = this.tree.getRoot();\r\n while (node != null) {\r\n this.path.push(node);\r\n node = node.left;\r\n }\r\n return this.path.length > 0;\r\n }\r\n throw \"Concurrent modification during iteration.\";\r\n }\r\n if (!this.path.length)\r\n return false;\r\n if (this.splayCount != this.tree.getSplayCount()) {\r\n this.rebuildPath(this.path[this.path.length - 1].key);\r\n }\r\n let node = this.path[this.path.length - 1];\r\n let next = node.right;\r\n if (next != null) {\r\n while (next != null) {\r\n this.path.push(next);\r\n next = next.left;\r\n }\r\n return true;\r\n }\r\n this.path.pop();\r\n while (this.path.length && this.path[this.path.length - 1].right === node) {\r\n node = this.path.pop();\r\n }\r\n return this.path.length > 0;\r\n }\r\n}\r\nclass SplayTreeKeyIterableIterator extends SplayTreeIterableIterator {\r\n getValue(node) {\r\n return node.key;\r\n }\r\n}\r\nclass SplayTreeSetEntryIterableIterator extends SplayTreeIterableIterator {\r\n getValue(node) {\r\n return [node.key, node.key];\r\n }\r\n}\r\nclass SplayTreeValueIterableIterator extends SplayTreeIterableIterator {\r\n constructor(map) {\r\n super(map);\r\n }\r\n getValue(node) {\r\n return node.value;\r\n }\r\n}\r\nclass SplayTreeMapEntryIterableIterator extends SplayTreeIterableIterator {\r\n constructor(map) {\r\n super(map);\r\n }\r\n getValue(node) {\r\n return [node.key, node.value];\r\n }\r\n replaceValue(value) {\r\n if (this.modificationCount != this.tree.getModificationCount()) {\r\n throw \"Concurrent modification during iteration.\";\r\n }\r\n if (this.splayCount != this.tree.getSplayCount()) {\r\n this.rebuildPath(this.path[this.path.length - 1].key);\r\n }\r\n const last = this.path.pop();\r\n const newLast = last.replaceValue(value);\r\n if (!this.path.length) {\r\n this.tree.setRoot(newLast);\r\n }\r\n else {\r\n const parent = this.path[this.path.length - 1];\r\n if (last === parent.left) {\r\n parent.left = newLast;\r\n }\r\n else {\r\n parent.right = newLast;\r\n }\r\n }\r\n this.path.push(newLast);\r\n const count = this.tree.getSplayCount() + 1;\r\n this.tree.setSplayCount(count);\r\n this.splayCount = count;\r\n }\r\n}\r\n","export default (x) => {\n return x;\n};\n","import BigNumber from \"bignumber.js\";\nimport { SplayTreeSet } from \"splaytree-ts\";\nimport compare from \"./compare.js\";\nimport identity from \"./identity.js\";\nexport default (eps) => {\n if (eps) {\n const xTree = new SplayTreeSet(compare(eps));\n const yTree = new SplayTreeSet(compare(eps));\n const snapCoord = (coord, tree) => {\n return tree.addAndReturn(coord);\n };\n const snap = (v) => {\n return {\n x: snapCoord(v.x, xTree),\n y: snapCoord(v.y, yTree),\n };\n };\n snap({ x: new BigNumber(0), y: new BigNumber(0) });\n return snap;\n }\n return identity;\n};\n","import compare from \"./compare.js\";\nimport orient from \"./orient.js\";\nimport snap from \"./snap.js\";\nconst set = (eps) => {\n return {\n set: (eps) => { precision = set(eps); },\n reset: () => set(eps),\n compare: compare(eps),\n snap: snap(eps),\n orient: orient(eps)\n };\n};\nexport let precision = set();\n","/**\n * A bounding box has the format:\n *\n * { ll: { x: xmin, y: ymin }, ur: { x: xmax, y: ymax } }\n *\n */\nexport const isInBbox = (bbox, point) => {\n return (bbox.ll.x.isLessThanOrEqualTo(point.x) &&\n point.x.isLessThanOrEqualTo(bbox.ur.x) &&\n bbox.ll.y.isLessThanOrEqualTo(point.y) &&\n point.y.isLessThanOrEqualTo(bbox.ur.y));\n};\n/* Returns either null, or a bbox (aka an ordered pair of points)\n * If there is only one point of overlap, a bbox with identical points\n * will be returned */\nexport const getBboxOverlap = (b1, b2) => {\n // check if the bboxes overlap at all\n if (b2.ur.x.isLessThan(b1.ll.x) ||\n b1.ur.x.isLessThan(b2.ll.x) ||\n b2.ur.y.isLessThan(b1.ll.y) ||\n b1.ur.y.isLessThan(b2.ll.y))\n return null;\n // find the middle two X values\n const lowerX = b1.ll.x.isLessThan(b2.ll.x) ? b2.ll.x : b1.ll.x;\n const upperX = b1.ur.x.isLessThan(b2.ur.x) ? b1.ur.x : b2.ur.x;\n // find the middle two Y values\n const lowerY = b1.ll.y.isLessThan(b2.ll.y) ? b2.ll.y : b1.ll.y;\n const upperY = b1.ur.y.isLessThan(b2.ur.y) ? b1.ur.y : b2.ur.y;\n // put those middle values together to get the overlap\n return { ll: { x: lowerX, y: lowerY }, ur: { x: upperX, y: upperY } };\n};\n","/* Cross Product of two vectors with first point at origin */\nexport const crossProduct = (a, b) => a.x.times(b.y).minus(a.y.times(b.x));\n/* Dot Product of two vectors with first point at origin */\nexport const dotProduct = (a, b) => a.x.times(b.x).plus(a.y.times(b.y));\nexport const length = (v) => dotProduct(v, v).sqrt();\n/* Get the sine of the angle from pShared -> pAngle to pShaed -> pBase */\nexport const sineOfAngle = (pShared, pBase, pAngle) => {\n const vBase = { x: pBase.x.minus(pShared.x), y: pBase.y.minus(pShared.y) };\n const vAngle = { x: pAngle.x.minus(pShared.x), y: pAngle.y.minus(pShared.y) };\n return crossProduct(vAngle, vBase).div(length(vAngle)).div(length(vBase));\n};\n/* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */\nexport const cosineOfAngle = (pShared, pBase, pAngle) => {\n const vBase = { x: pBase.x.minus(pShared.x), y: pBase.y.minus(pShared.y) };\n const vAngle = { x: pAngle.x.minus(pShared.x), y: pAngle.y.minus(pShared.y) };\n return dotProduct(vAngle, vBase).div(length(vAngle)).div(length(vBase));\n};\n/* Get the x coordinate where the given line (defined by a point and vector)\n * crosses the horizontal line with the given y coordiante.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nexport const horizontalIntersection = (pt, v, y) => {\n if (v.y.isZero())\n return null;\n return { x: pt.x.plus((v.x.div(v.y)).times(y.minus(pt.y))), y: y };\n};\n/* Get the y coordinate where the given line (defined by a point and vector)\n * crosses the vertical line with the given x coordiante.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nexport const verticalIntersection = (pt, v, x) => {\n if (v.x.isZero())\n return null;\n return { x: x, y: pt.y.plus((v.y.div(v.x)).times(x.minus(pt.x))) };\n};\n/* Get the intersection of two lines, each defined by a base point and a vector.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nexport const intersection = (pt1, v1, pt2, v2) => {\n // take some shortcuts for vertical and horizontal lines\n // this also ensures we don't calculate an intersection and then discover\n // it's actually outside the bounding box of the line\n if (v1.x.isZero())\n return verticalIntersection(pt2, v2, pt1.x);\n if (v2.x.isZero())\n return verticalIntersection(pt1, v1, pt2.x);\n if (v1.y.isZero())\n return horizontalIntersection(pt2, v2, pt1.y);\n if (v2.y.isZero())\n return horizontalIntersection(pt1, v1, pt2.y);\n // General case for non-overlapping segments.\n // This algorithm is based on Schneider and Eberly.\n // http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf - pg 244\n const kross = crossProduct(v1, v2);\n if (kross.isZero())\n return null;\n const ve = { x: pt2.x.minus(pt1.x), y: pt2.y.minus(pt1.y) };\n const d1 = crossProduct(ve, v1).div(kross);\n const d2 = crossProduct(ve, v2).div(kross);\n // take the average of the two calculations to minimize rounding error\n const x1 = pt1.x.plus(d2.times(v1.x)), x2 = pt2.x.plus(d1.times(v2.x));\n const y1 = pt1.y.plus(d2.times(v1.y)), y2 = pt2.y.plus(d1.times(v2.y));\n const x = x1.plus(x2).div(2);\n const y = y1.plus(y2).div(2);\n return { x: x, y: y };\n};\n/* Given a vector, return one that is perpendicular */\nexport const perpendicular = (v) => {\n return { x: v.y.negated(), y: v.x };\n};\n","import Segment from \"./segment.js\";\nimport { cosineOfAngle, sineOfAngle } from \"./vector.js\";\nexport default class SweepEvent {\n point;\n isLeft;\n segment;\n otherSE;\n consumedBy;\n // for ordering sweep events in the sweep event queue\n static compare(a, b) {\n // favor event with a point that the sweep line hits first\n const ptCmp = SweepEvent.comparePoints(a.point, b.point);\n if (ptCmp !== 0)\n return ptCmp;\n // the points are the same, so link them if needed\n if (a.point !== b.point)\n a.link(b);\n // favor right events over left\n if (a.isLeft !== b.isLeft)\n return a.isLeft ? 1 : -1;\n // we have two matching left or right endpoints\n // ordering of this case is the same as for their segments\n return Segment.compare(a.segment, b.segment);\n }\n // for ordering points in sweep line order\n static comparePoints(aPt, bPt) {\n if (aPt.x.isLessThan(bPt.x))\n return -1;\n if (aPt.x.isGreaterThan(bPt.x))\n return 1;\n if (aPt.y.isLessThan(bPt.y))\n return -1;\n if (aPt.y.isGreaterThan(bPt.y))\n return 1;\n return 0;\n }\n // Warning: 'point' input will be modified and re-used (for performance)\n constructor(point, isLeft) {\n if (point.events === undefined)\n point.events = [this];\n else\n point.events.push(this);\n this.point = point;\n this.isLeft = isLeft;\n // this.segment, this.otherSE set by factory\n }\n link(other) {\n if (other.point === this.point) {\n throw new Error(\"Tried to link already linked events\");\n }\n const otherEvents = other.point.events;\n for (let i = 0, iMax = otherEvents.length; i < iMax; i++) {\n const evt = otherEvents[i];\n this.point.events.push(evt);\n evt.point = this.point;\n }\n this.checkForConsuming();\n }\n /* Do a pass over our linked events and check to see if any pair\n * of segments match, and should be consumed. */\n checkForConsuming() {\n // FIXME: The loops in this method run O(n^2) => no good.\n // Maintain little ordered sweep event trees?\n // Can we maintaining an ordering that avoids the need\n // for the re-sorting with getLeftmostComparator in geom-out?\n // Compare each pair of events to see if other events also match\n const numEvents = this.point.events.length;\n for (let i = 0; i < numEvents; i++) {\n const evt1 = this.point.events[i];\n if (evt1.segment.consumedBy !== undefined)\n continue;\n for (let j = i + 1; j < numEvents; j++) {\n const evt2 = this.point.events[j];\n if (evt2.consumedBy !== undefined)\n continue;\n if (evt1.otherSE.point.events !== evt2.otherSE.point.events)\n continue;\n evt1.segment.consume(evt2.segment);\n }\n }\n }\n getAvailableLinkedEvents() {\n // point.events is always of length 2 or greater\n const events = [];\n for (let i = 0, iMax = this.point.events.length; i < iMax; i++) {\n const evt = this.point.events[i];\n if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) {\n events.push(evt);\n }\n }\n return events;\n }\n /**\n * Returns a comparator function for sorting linked events that will\n * favor the event that will give us the smallest left-side angle.\n * All ring construction starts as low as possible heading to the right,\n * so by always turning left as sharp as possible we'll get polygons\n * without uncessary loops & holes.\n *\n * The comparator function has a compute cache such that it avoids\n * re-computing already-computed values.\n */\n getLeftmostComparator(baseEvent) {\n const cache = new Map();\n const fillCache = (linkedEvent) => {\n const nextEvent = linkedEvent.otherSE;\n cache.set(linkedEvent, {\n sine: sineOfAngle(this.point, baseEvent.point, nextEvent.point),\n cosine: cosineOfAngle(this.point, baseEvent.point, nextEvent.point),\n });\n };\n return (a, b) => {\n if (!cache.has(a))\n fillCache(a);\n if (!cache.has(b))\n fillCache(b);\n const { sine: asine, cosine: acosine } = cache.get(a);\n const { sine: bsine, cosine: bcosine } = cache.get(b);\n // both on or above x-axis\n if (asine.isGreaterThanOrEqualTo(0) && bsine.isGreaterThanOrEqualTo(0)) {\n if (acosine.isLessThan(bcosine))\n return 1;\n if (acosine.isGreaterThan(bcosine))\n return -1;\n return 0;\n }\n // both below x-axis\n if (asine.isLessThan(0) && bsine.isLessThan(0)) {\n if (acosine.isLessThan(bcosine))\n return -1;\n if (acosine.isGreaterThan(bcosine))\n return 1;\n return 0;\n }\n // one above x-axis, one below\n if (bsine.isLessThan(asine))\n return -1;\n if (bsine.isGreaterThan(asine))\n return 1;\n return 0;\n };\n }\n}\n","import { getBboxOverlap, isInBbox } from \"./bbox.js\";\nimport operation from \"./operation.js\";\nimport { precision } from \"./precision.js\";\nimport SweepEvent from \"./sweep-event.js\";\nimport { intersection } from \"./vector.js\";\n// Give segments unique ID's to get consistent sorting of\n// segments and sweep events when all else is identical\nlet segmentId = 0;\nexport default class Segment {\n id;\n leftSE;\n rightSE;\n rings;\n windings;\n ringOut;\n consumedBy;\n prev;\n _prevInResult;\n _beforeState;\n _afterState;\n _isInResult;\n /* This compare() function is for ordering segments in the sweep\n * line tree, and does so according to the following criteria:\n *\n * Consider the vertical line that lies an infinestimal step to the\n * right of the right-more of the two left endpoints of the input\n * segments. Imagine slowly moving a point up from negative infinity\n * in the increasing y direction. Which of the two segments will that\n * point intersect first? That segment comes 'before' the other one.\n *\n * If neither segment would be intersected by such a line, (if one\n * or more of the segments are vertical) then the line to be considered\n * is directly on the right-more of the two left inputs.\n */\n static compare(a, b) {\n const alx = a.leftSE.point.x;\n const blx = b.leftSE.point.x;\n const arx = a.rightSE.point.x;\n const brx = b.rightSE.point.x;\n // check if they're even in the same vertical plane\n if (brx.isLessThan(alx))\n return 1;\n if (arx.isLessThan(blx))\n return -1;\n const aly = a.leftSE.point.y;\n const bly = b.leftSE.point.y;\n const ary = a.rightSE.point.y;\n const bry = b.rightSE.point.y;\n // is left endpoint of segment B the right-more?\n if (alx.isLessThan(blx)) {\n // are the two segments in the same horizontal plane?\n if (bly.isLessThan(aly) && bly.isLessThan(ary))\n return 1;\n if (bly.isGreaterThan(aly) && bly.isGreaterThan(ary))\n return -1;\n // is the B left endpoint colinear to segment A?\n const aCmpBLeft = a.comparePoint(b.leftSE.point);\n if (aCmpBLeft < 0)\n return 1;\n if (aCmpBLeft > 0)\n return -1;\n // is the A right endpoint colinear to segment B ?\n const bCmpARight = b.comparePoint(a.rightSE.point);\n if (bCmpARight !== 0)\n return bCmpARight;\n // colinear segments, consider the one with left-more\n // left endpoint to be first (arbitrary?)\n return -1;\n }\n // is left endpoint of segment A the right-more?\n if (alx.isGreaterThan(blx)) {\n if (aly.isLessThan(bly) && aly.isLessThan(bry))\n return -1;\n if (aly.isGreaterThan(bly) && aly.isGreaterThan(bry))\n return 1;\n // is the A left endpoint colinear to segment B?\n const bCmpALeft = b.comparePoint(a.leftSE.point);\n if (bCmpALeft !== 0)\n return bCmpALeft;\n // is the B right endpoint colinear to segment A?\n const aCmpBRight = a.comparePoint(b.rightSE.point);\n if (aCmpBRight < 0)\n return 1;\n if (aCmpBRight > 0)\n return -1;\n // colinear segments, consider the one with left-more\n // left endpoint to be first (arbitrary?)\n return 1;\n }\n // if we get here, the two left endpoints are in the same\n // vertical plane, ie alx === blx\n // consider the lower left-endpoint to come first\n if (aly.isLessThan(bly))\n return -1;\n if (aly.isGreaterThan(bly))\n return 1;\n // left endpoints are identical\n // check for colinearity by using the left-more right endpoint\n // is the A right endpoint more left-more?\n if (arx.isLessThan(brx)) {\n const bCmpARight = b.comparePoint(a.rightSE.point);\n if (bCmpARight !== 0)\n return bCmpARight;\n }\n // is the B right endpoint more left-more?\n if (arx.isGreaterThan(brx)) {\n const aCmpBRight = a.comparePoint(b.rightSE.point);\n if (aCmpBRight < 0)\n return 1;\n if (aCmpBRight > 0)\n return -1;\n }\n if (!arx.eq(brx)) {\n // are these two [almost] vertical segments with opposite orientation?\n // if so, the one with the lower right endpoint comes first\n const ay = ary.minus(aly);\n const ax = arx.minus(alx);\n const by = bry.minus(bly);\n const bx = brx.minus(blx);\n if (ay.isGreaterThan(ax) && by.isLessThan(bx))\n return 1;\n if (ay.isLessThan(ax) && by.isGreaterThan(bx))\n return -1;\n }\n // we have colinear segments with matching orientation\n // consider the one with more left-more right endpoint to be first\n if (arx.isGreaterThan(brx))\n return 1;\n if (arx.isLessThan(brx))\n return -1;\n // if we get here, two two right endpoints are in the same\n // vertical plane, ie arx === brx\n // consider the lower right-endpoint to come first\n if (ary.isLessThan(bry))\n return -1;\n if (ary.isGreaterThan(bry))\n return 1;\n // right endpoints identical as well, so the segments are idential\n // fall back on creation order as consistent tie-breaker\n if (a.id < b.id)\n return -1;\n if (a.id > b.id)\n return 1;\n // identical segment, ie a === b\n return 0;\n }\n /* Warning: a reference to ringWindings input will be stored,\n * and possibly will be later modified */\n constructor(leftSE, rightSE, rings, windings) {\n this.id = ++segmentId;\n this.leftSE = leftSE;\n leftSE.segment = this;\n leftSE.otherSE = rightSE;\n this.rightSE = rightSE;\n rightSE.segment = this;\n rightSE.otherSE = leftSE;\n this.rings = rings;\n this.windings = windings;\n // left unset for performance, set later in algorithm\n // this.ringOut, this.consumedBy, this.prev\n }\n static fromRing(pt1, pt2, ring) {\n let leftPt, rightPt, winding;\n // ordering the two points according to sweep line ordering\n const cmpPts = SweepEvent.comparePoints(pt1, pt2);\n if (cmpPts < 0) {\n leftPt = pt1;\n rightPt = pt2;\n winding = 1;\n }\n else if (cmpPts > 0) {\n leftPt = pt2;\n rightPt = pt1;\n winding = -1;\n }\n else\n throw new Error(`Tried to create degenerate segment at [${pt1.x}, ${pt1.y}]`);\n const leftSE = new SweepEvent(leftPt, true);\n const rightSE = new SweepEvent(rightPt, false);\n return new Segment(leftSE, rightSE, [ring], [winding]);\n }\n /* When a segment is split, the rightSE is replaced with a new sweep event */\n replaceRightSE(newRightSE) {\n this.rightSE = newRightSE;\n this.rightSE.segment = this;\n this.rightSE.otherSE = this.leftSE;\n this.leftSE.otherSE = this.rightSE;\n }\n bbox() {\n const y1 = this.leftSE.point.y;\n const y2 = this.rightSE.point.y;\n return {\n ll: { x: this.leftSE.point.x, y: y1.isLessThan(y2) ? y1 : y2 },\n ur: { x: this.rightSE.point.x, y: y1.isGreaterThan(y2) ? y1 : y2 },\n };\n }\n /* A vector from the left point to the right */\n vector() {\n return {\n x: this.rightSE.point.x.minus(this.leftSE.point.x),\n y: this.rightSE.point.y.minus(this.leftSE.point.y),\n };\n }\n isAnEndpoint(pt) {\n return ((pt.x.eq(this.leftSE.point.x) && pt.y.eq(this.leftSE.point.y)) ||\n (pt.x.eq(this.rightSE.point.x) && pt.y.eq(this.rightSE.point.y)));\n }\n /* Compare this segment with a point.\n *\n * A point P is considered to be colinear to a segment if there\n * exists a distance D such that if we travel along the segment\n * from one * endpoint towards the other a distance D, we find\n * ourselves at point P.\n *\n * Return value indicates:\n *\n * 1: point lies above the segment (to the left of vertical)\n * 0: point is colinear to segment\n * -1: point lies below the segment (to the right of vertical)\n */\n comparePoint(point) {\n return precision.orient(this.leftSE.point, point, this.rightSE.point);\n }\n /**\n * Given another segment, returns the first non-trivial intersection\n * between the two segments (in terms of sweep line ordering), if it exists.\n *\n * A 'non-trivial' intersection is one that will cause one or both of the\n * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:\n *\n * * endpoint of segA with endpoint of segB --> trivial\n * * endpoint of segA with point along segB --> non-trivial\n * * endpoint of segB with point along segA --> non-trivial\n * * point along segA with point along segB --> non-trivial\n *\n * If no non-trivial intersection exists, return null\n * Else, return null.\n */\n getIntersection(other) {\n // If bboxes don't overlap, there can't be any intersections\n const tBbox = this.bbox();\n const oBbox = other.bbox();\n const bboxOverlap = getBboxOverlap(tBbox, oBbox);\n if (bboxOverlap === null)\n return null;\n // We first check to see if the endpoints can be considered intersections.\n // This will 'snap' intersections to endpoints if possible, and will\n // handle cases of colinearity.\n const tlp = this.leftSE.point;\n const trp = this.rightSE.point;\n const olp = other.leftSE.point;\n const orp = other.rightSE.point;\n // does each endpoint touch the other segment?\n // note that we restrict the 'touching' definition to only allow segments\n // to touch endpoints that lie forward from where we are in the sweep line pass\n const touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;\n const touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;\n const touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;\n const touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0;\n // do left endpoints match?\n if (touchesThisLSE && touchesOtherLSE) {\n // these two cases are for colinear segments with matching left\n // endpoints, and one segment being longer than the other\n if (touchesThisRSE && !touchesOtherRSE)\n return trp;\n if (!touchesThisRSE && touchesOtherRSE)\n return orp;\n // either the two segments match exactly (two trival intersections)\n // or just on their left endpoint (one trivial intersection\n return null;\n }\n // does this left endpoint matches (other doesn't)\n if (touchesThisLSE) {\n // check for segments that just intersect on opposing endpoints\n if (touchesOtherRSE) {\n if (tlp.x.eq(orp.x) && tlp.y.eq(orp.y))\n return null;\n }\n // t-intersection on left endpoint\n return tlp;\n }\n // does other left endpoint matches (this doesn't)\n if (touchesOtherLSE) {\n // check for segments that just intersect on opposing endpoints\n if (touchesThisRSE) {\n if (trp.x.eq(olp.x) && trp.y.eq(olp.y))\n return null;\n }\n // t-intersection on left endpoint\n return olp;\n }\n // trivial intersection on right endpoints\n if (touchesThisRSE && touchesOtherRSE)\n return null;\n // t-intersections on just one right endpoint\n if (touchesThisRSE)\n return trp;\n if (touchesOtherRSE)\n return orp;\n // None of our endpoints intersect. Look for a general intersection between\n // infinite lines laid over the segments\n const pt = intersection(tlp, this.vector(), olp, other.vector());\n // are the segments parrallel? Note that if they were colinear with overlap,\n // they would have an endpoint intersection and that case was already handled above\n if (pt === null)\n return null;\n // is the intersection found between the lines not on the segments?\n if (!isInBbox(bboxOverlap, pt))\n return null;\n // round the the computed point if needed\n return precision.snap(pt);\n }\n /**\n * Split the given segment into multiple segments on the given points.\n * * Each existing segment will retain its leftSE and a new rightSE will be\n * generated for it.\n * * A new segment will be generated which will adopt the original segment's\n * rightSE, and a new leftSE will be generated for it.\n * * If there are more than two points given to split on, new segments\n * in the middle will be generated with new leftSE and rightSE's.\n * * An array of the newly generated SweepEvents will be returned.\n *\n * Warning: input array of points is modified\n */\n split(point) {\n const newEvents = [];\n const alreadyLinked = point.events !== undefined;\n const newLeftSE = new SweepEvent(point, true);\n const newRightSE = new SweepEvent(point, false);\n const oldRightSE = this.rightSE;\n this.replaceRightSE(newRightSE);\n newEvents.push(newRightSE);\n newEvents.push(newLeftSE);\n const newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice());\n // when splitting a nearly vertical downward-facing segment,\n // sometimes one of the resulting new segments is vertical, in which\n // case its left and right events may need to be swapped\n if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {\n newSeg.swapEvents();\n }\n if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {\n this.swapEvents();\n }\n // in the point we just used to create new sweep events with was already\n // linked to other events, we need to check if either of the affected\n // segments should be consumed\n if (alreadyLinked) {\n newLeftSE.checkForConsuming();\n newRightSE.checkForConsuming();\n }\n return newEvents;\n }\n /* Swap which event is left and right */\n swapEvents() {\n const tmpEvt = this.rightSE;\n this.rightSE = this.leftSE;\n this.leftSE = tmpEvt;\n this.leftSE.isLeft = true;\n this.rightSE.isLeft = false;\n for (let i = 0, iMax = this.windings.length; i < iMax; i++) {\n this.windings[i] *= -1;\n }\n }\n /* Consume another segment. We take their rings under our wing\n * and mark them as consumed. Use for perfectly overlapping segments */\n consume(other) {\n let consumer = this;\n let consumee = other;\n while (consumer.consumedBy)\n consumer = consumer.consumedBy;\n while (consumee.consumedBy)\n consumee = consumee.consumedBy;\n const cmp = Segment.compare(consumer, consumee);\n if (cmp === 0)\n return; // already consumed\n // the winner of the consumption is the earlier segment\n // according to sweep line ordering\n if (cmp > 0) {\n const tmp = consumer;\n consumer = consumee;\n consumee = tmp;\n }\n // make sure a segment doesn't consume it's prev\n if (consumer.prev === consumee) {\n const tmp = consumer;\n consumer = consumee;\n consumee = tmp;\n }\n for (let i = 0, iMax = consumee.rings.length; i < iMax; i++) {\n const ring = consumee.rings[i];\n const winding = consumee.windings[i];\n const index = consumer.rings.indexOf(ring);\n if (index === -1) {\n consumer.rings.push(ring);\n consumer.windings.push(winding);\n }\n else\n consumer.windings[index] += winding;\n }\n consumee.rings = null;\n consumee.windings = null;\n consumee.consumedBy = consumer;\n // mark sweep events consumed as to maintain ordering in sweep event queue\n consumee.leftSE.consumedBy = consumer.leftSE;\n consumee.rightSE.consumedBy = consumer.rightSE;\n }\n /* The first segment previous segment chain that is in the result */\n prevInResult() {\n if (this._prevInResult !== undefined)\n return this._prevInResult;\n if (!this.prev)\n this._prevInResult = null;\n else if (this.prev.isInResult())\n this._prevInResult = this.prev;\n else\n this._prevInResult = this.prev.prevInResult();\n return this._prevInResult;\n }\n beforeState() {\n if (this._beforeState !== undefined)\n return this._beforeState;\n if (!this.prev)\n this._beforeState = {\n rings: [],\n windings: [],\n multiPolys: [],\n };\n else {\n const seg = this.prev.consumedBy || this.prev;\n this._beforeState = seg.afterState();\n }\n return this._beforeState;\n }\n afterState() {\n if (this._afterState !== undefined)\n return this._afterState;\n const beforeState = this.beforeState();\n this._afterState = {\n rings: beforeState.rings.slice(0),\n windings: beforeState.windings.slice(0),\n multiPolys: [],\n };\n const ringsAfter = this._afterState.rings;\n const windingsAfter = this._afterState.windings;\n const mpsAfter = this._afterState.multiPolys;\n // calculate ringsAfter, windingsAfter\n for (let i = 0, iMax = this.rings.length; i < iMax; i++) {\n const ring = this.rings[i];\n const winding = this.windings[i];\n const index = ringsAfter.indexOf(ring);\n if (index === -1) {\n ringsAfter.push(ring);\n windingsAfter.push(winding);\n }\n else\n windingsAfter[index] += winding;\n }\n // calcualte polysAfter\n const polysAfter = [];\n const polysExclude = [];\n for (let i = 0, iMax = ringsAfter.length; i < iMax; i++) {\n if (windingsAfter[i] === 0)\n continue; // non-zero rule\n const ring = ringsAfter[i];\n const poly = ring.poly;\n if (polysExclude.indexOf(poly) !== -1)\n continue;\n if (ring.isExterior)\n polysAfter.push(poly);\n else {\n if (polysExclude.indexOf(poly) === -1)\n polysExclude.push(poly);\n const index = polysAfter.indexOf(ring.poly);\n if (index !== -1)\n polysAfter.splice(index, 1);\n }\n }\n // calculate multiPolysAfter\n for (let i = 0, iMax = polysAfter.length; i < iMax; i++) {\n const mp = polysAfter[i].multiPoly;\n if (mpsAfter.indexOf(mp) === -1)\n mpsAfter.push(mp);\n }\n return this._afterState;\n }\n /* Is this segment part of the final result? */\n isInResult() {\n // if we've been consumed, we're not in the result\n if (this.consumedBy)\n return false;\n if (this._isInResult !== undefined)\n return this._isInResult;\n const mpsBefore = this.beforeState().multiPolys;\n const mpsAfter = this.afterState().multiPolys;\n switch (operation.type) {\n case \"union\": {\n // UNION - included iff:\n // * On one side of us there is 0 poly interiors AND\n // * On the other side there is 1 or more.\n const noBefores = mpsBefore.length === 0;\n const noAfters = mpsAfter.length === 0;\n this._isInResult = noBefores !== noAfters;\n break;\n }\n case \"intersection\": {\n // INTERSECTION - included iff:\n // * on one side of us all multipolys are rep. with poly interiors AND\n // * on the other side of us, not all multipolys are repsented\n // with poly interiors\n let least;\n let most;\n if (mpsBefore.length < mpsAfter.length) {\n least = mpsBefore.length;\n most = mpsAfter.length;\n }\n else {\n least = mpsAfter.length;\n most = mpsBefore.length;\n }\n this._isInResult = most === operation.numMultiPolys && least < most;\n break;\n }\n case \"xor\": {\n // XOR - included iff:\n // * the difference between the number of multipolys represented\n // with poly interiors on our two sides is an odd number\n const diff = Math.abs(mpsBefore.length - mpsAfter.length);\n this._isInResult = diff % 2 === 1;\n break;\n }\n case \"difference\": {\n // DIFFERENCE included iff:\n // * on exactly one side, we have just the subject\n const isJustSubject = (mps) => mps.length === 1 && mps[0].isSubject;\n this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter);\n break;\n }\n }\n return this._isInResult;\n }\n}\n","import BigNumber from \"bignumber.js\";\nimport { precision } from \"./precision.js\";\nimport Segment from \"./segment.js\";\nexport class RingIn {\n poly;\n isExterior;\n segments;\n bbox;\n constructor(geomRing, poly, isExterior) {\n if (!Array.isArray(geomRing) || geomRing.length === 0) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n this.poly = poly;\n this.isExterior = isExterior;\n this.segments = [];\n if (typeof geomRing[0][0] !== \"number\" ||\n typeof geomRing[0][1] !== \"number\") {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n const firstPoint = precision.snap({ x: new BigNumber(geomRing[0][0]), y: new BigNumber(geomRing[0][1]) });\n this.bbox = {\n ll: { x: firstPoint.x, y: firstPoint.y },\n ur: { x: firstPoint.x, y: firstPoint.y },\n };\n let prevPoint = firstPoint;\n for (let i = 1, iMax = geomRing.length; i < iMax; i++) {\n if (typeof geomRing[i][0] !== \"number\" ||\n typeof geomRing[i][1] !== \"number\") {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n const point = precision.snap({ x: new BigNumber(geomRing[i][0]), y: new BigNumber(geomRing[i][1]) });\n // skip repeated points\n if (point.x.eq(prevPoint.x) && point.y.eq(prevPoint.y))\n continue;\n this.segments.push(Segment.fromRing(prevPoint, point, this));\n if (point.x.isLessThan(this.bbox.ll.x))\n this.bbox.ll.x = point.x;\n if (point.y.isLessThan(this.bbox.ll.y))\n this.bbox.ll.y = point.y;\n if (point.x.isGreaterThan(this.bbox.ur.x))\n this.bbox.ur.x = point.x;\n if (point.y.isGreaterThan(this.bbox.ur.y))\n this.bbox.ur.y = point.y;\n prevPoint = point;\n }\n // add segment from last to first if last is not the same as first\n if (!firstPoint.x.eq(prevPoint.x) || !firstPoint.y.eq(prevPoint.y)) {\n this.segments.push(Segment.fromRing(prevPoint, firstPoint, this));\n }\n }\n getSweepEvents() {\n const sweepEvents = [];\n for (let i = 0, iMax = this.segments.length; i < iMax; i++) {\n const segment = this.segments[i];\n sweepEvents.push(segment.leftSE);\n sweepEvents.push(segment.rightSE);\n }\n return sweepEvents;\n }\n}\nexport class PolyIn {\n multiPoly;\n exteriorRing;\n interiorRings;\n bbox;\n constructor(geomPoly, multiPoly) {\n if (!Array.isArray(geomPoly)) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n this.exteriorRing = new RingIn(geomPoly[0], this, true);\n // copy by value\n this.bbox = {\n ll: { x: this.exteriorRing.bbox.ll.x, y: this.exteriorRing.bbox.ll.y },\n ur: { x: this.exteriorRing.bbox.ur.x, y: this.exteriorRing.bbox.ur.y },\n };\n this.interiorRings = [];\n for (let i = 1, iMax = geomPoly.length; i < iMax; i++) {\n const ring = new RingIn(geomPoly[i], this, false);\n if (ring.bbox.ll.x.isLessThan(this.bbox.ll.x))\n this.bbox.ll.x = ring.bbox.ll.x;\n if (ring.bbox.ll.y.isLessThan(this.bbox.ll.y))\n this.bbox.ll.y = ring.bbox.ll.y;\n if (ring.bbox.ur.x.isGreaterThan(this.bbox.ur.x))\n this.bbox.ur.x = ring.bbox.ur.x;\n if (ring.bbox.ur.y.isGreaterThan(this.bbox.ur.y))\n this.bbox.ur.y = ring.bbox.ur.y;\n this.interiorRings.push(ring);\n }\n this.multiPoly = multiPoly;\n }\n getSweepEvents() {\n const sweepEvents = this.exteriorRing.getSweepEvents();\n for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {\n const ringSweepEvents = this.interiorRings[i].getSweepEvents();\n for (let j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {\n sweepEvents.push(ringSweepEvents[j]);\n }\n }\n return sweepEvents;\n }\n}\nexport class MultiPolyIn {\n isSubject;\n polys;\n bbox;\n constructor(geom, isSubject) {\n if (!Array.isArray(geom)) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n try {\n // if the input looks like a polygon, convert it to a multipolygon\n if (typeof geom[0][0][0] === \"number\")\n geom = [geom];\n }\n catch (ex) {\n // The input is either malformed or has empty arrays.\n // In either case, it will be handled later on.\n }\n this.polys = [];\n this.bbox = {\n ll: { x: new BigNumber(Number.POSITIVE_INFINITY), y: new BigNumber(Number.POSITIVE_INFINITY) },\n ur: { x: new BigNumber(Number.NEGATIVE_INFINITY), y: new BigNumber(Number.NEGATIVE_INFINITY) },\n };\n for (let i = 0, iMax = geom.length; i < iMax; i++) {\n const poly = new PolyIn(geom[i], this);\n if (poly.bbox.ll.x.isLessThan(this.bbox.ll.x))\n this.bbox.ll.x = poly.bbox.ll.x;\n if (poly.bbox.ll.y.isLessThan(this.bbox.ll.y))\n this.bbox.ll.y = poly.bbox.ll.y;\n if (poly.bbox.ur.x.isGreaterThan(this.bbox.ur.x))\n this.bbox.ur.x = poly.bbox.ur.x;\n if (poly.bbox.ur.y.isGreaterThan(this.bbox.ur.y))\n this.bbox.ur.y = poly.bbox.ur.y;\n this.polys.push(poly);\n }\n this.isSubject = isSubject;\n }\n getSweepEvents() {\n const sweepEvents = [];\n for (let i = 0, iMax = this.polys.length; i < iMax; i++) {\n const polySweepEvents = this.polys[i].getSweepEvents();\n for (let j = 0, jMax = polySweepEvents.length; j < jMax; j++) {\n sweepEvents.push(polySweepEvents[j]);\n }\n }\n return sweepEvents;\n }\n}\n","import { precision } from \"./precision.js\";\nimport SweepEvent from \"./sweep-event.js\";\nexport class RingOut {\n events;\n poly;\n _isExteriorRing;\n _enclosingRing;\n /* Given the segments from the sweep line pass, compute & return a series\n * of closed rings from all the segments marked to be part of the result */\n static factory(allSegments) {\n const ringsOut = [];\n for (let i = 0, iMax = allSegments.length; i < iMax; i++) {\n const segment = allSegments[i];\n if (!segment.isInResult() || segment.ringOut)\n continue;\n let prevEvent = null;\n let event = segment.leftSE;\n let nextEvent = segment.rightSE;\n const events = [event];\n const startingPoint = event.point;\n const intersectionLEs = [];\n /* Walk the chain of linked events to form a closed ring */\n while (true) {\n prevEvent = event;\n event = nextEvent;\n events.push(event);\n /* Is the ring complete? */\n if (event.point === startingPoint)\n break;\n while (true) {\n const availableLEs = event.getAvailableLinkedEvents();\n /* Did we hit a dead end? This shouldn't happen. Indicates some earlier\n * part of the algorithm malfunctioned... please file a bug report. */\n if (availableLEs.length === 0) {\n const firstPt = events[0].point;\n const lastPt = events[events.length - 1].point;\n throw new Error(`Unable to complete output ring starting at [${firstPt.x},` +\n ` ${firstPt.y}]. Last matching segment found ends at` +\n ` [${lastPt.x}, ${lastPt.y}].`);\n }\n /* Only one way to go, so cotinue on the path */\n if (availableLEs.length === 1) {\n nextEvent = availableLEs[0].otherSE;\n break;\n }\n /* We must have an intersection. Check for a completed loop */\n let indexLE = null;\n for (let j = 0, jMax = intersectionLEs.length; j < jMax; j++) {\n if (intersectionLEs[j].point === event.point) {\n indexLE = j;\n break;\n }\n }\n /* Found a completed loop. Cut that off and make a ring */\n if (indexLE !== null) {\n const intersectionLE = intersectionLEs.splice(indexLE)[0];\n const ringEvents = events.splice(intersectionLE.index);\n ringEvents.unshift(ringEvents[0].otherSE);\n ringsOut.push(new RingOut(ringEvents.reverse()));\n continue;\n }\n /* register the intersection */\n intersectionLEs.push({\n index: events.length,\n point: event.point,\n });\n /* Choose the left-most option to continue the walk */\n const comparator = event.getLeftmostComparator(prevEvent);\n nextEvent = availableLEs.sort(comparator)[0].otherSE;\n break;\n }\n }\n ringsOut.push(new RingOut(events));\n }\n return ringsOut;\n }\n constructor(events) {\n this.events = events;\n for (let i = 0, iMax = events.length; i < iMax; i++) {\n events[i].segment.ringOut = this;\n }\n this.poly = null;\n }\n getGeom() {\n // Remove superfluous points (ie extra points along a straight line),\n let prevPt = this.events[0].point;\n const points = [prevPt];\n for (let i = 1, iMax = this.events.length - 1; i < iMax; i++) {\n const pt = this.events[i].point;\n const nextPt = this.events[i + 1].point;\n if (precision.orient(pt, prevPt, nextPt) === 0)\n continue;\n points.push(pt);\n prevPt = pt;\n }\n // ring was all (within rounding error of angle calc) colinear points\n if (points.length === 1)\n return null;\n // check if the starting point is necessary\n const pt = points[0];\n const nextPt = points[1];\n if (precision.orient(pt, prevPt, nextPt) === 0)\n points.shift();\n points.push(points[0]);\n const step = this.isExteriorRing() ? 1 : -1;\n const iStart = this.isExteriorRing() ? 0 : points.length - 1;\n const iEnd = this.isExteriorRing() ? points.length : -1;\n const orderedPoints = [];\n for (let i = iStart; i != iEnd; i += step)\n orderedPoints.push([points[i].x.toNumber(), points[i].y.toNumber()]);\n return orderedPoints;\n }\n isExteriorRing() {\n if (this._isExteriorRing === undefined) {\n const enclosing = this.enclosingRing();\n this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true;\n }\n return this._isExteriorRing;\n }\n enclosingRing() {\n if (this._enclosingRing === undefined) {\n this._enclosingRing = this._calcEnclosingRing();\n }\n return this._enclosingRing;\n }\n /* Returns the ring that encloses this one, if any */\n _calcEnclosingRing() {\n // start with the ealier sweep line event so that the prevSeg\n // chain doesn't lead us inside of a loop of ours\n let leftMostEvt = this.events[0];\n for (let i = 1, iMax = this.events.length; i < iMax; i++) {\n const evt = this.events[i];\n if (SweepEvent.compare(leftMostEvt, evt) > 0)\n leftMostEvt = evt;\n }\n let prevSeg = leftMostEvt.segment.prevInResult();\n let prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;\n while (true) {\n // no segment found, thus no ring can enclose us\n if (!prevSeg)\n return null;\n // no segments below prev segment found, thus the ring of the prev\n // segment must loop back around and enclose us\n if (!prevPrevSeg)\n return prevSeg.ringOut;\n // if the two segments are of different rings, the ring of the prev\n // segment must either loop around us or the ring of the prev prev\n // seg, which would make us and the ring of the prev peers\n if (prevPrevSeg.ringOut !== prevSeg.ringOut) {\n if (prevPrevSeg.ringOut?.enclosingRing() !== prevSeg.ringOut) {\n return prevSeg.ringOut;\n }\n else\n return prevSeg.ringOut?.enclosingRing();\n }\n // two segments are from the same ring, so this was a penisula\n // of that ring. iterate downward, keep searching\n prevSeg = prevPrevSeg.prevInResult();\n prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;\n }\n }\n}\nexport class PolyOut {\n exteriorRing;\n interiorRings;\n constructor(exteriorRing) {\n this.exteriorRing = exteriorRing;\n exteriorRing.poly = this;\n this.interiorRings = [];\n }\n addInterior(ring) {\n this.interiorRings.push(ring);\n ring.poly = this;\n }\n getGeom() {\n const geom0 = this.exteriorRing.getGeom();\n // exterior ring was all (within rounding error of angle calc) colinear points\n if (geom0 === null)\n return null;\n const geom = [geom0];\n for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {\n const ringGeom = this.interiorRings[i].getGeom();\n // interior ring was all (within rounding error of angle calc) colinear points\n if (ringGeom === null)\n continue;\n geom.push(ringGeom);\n }\n return geom;\n }\n}\nexport class MultiPolyOut {\n rings;\n polys;\n constructor(rings) {\n this.rings = rings;\n this.polys = this._composePolys(rings);\n }\n getGeom() {\n const geom = [];\n for (let i = 0, iMax = this.polys.length; i < iMax; i++) {\n const polyGeom = this.polys[i].getGeom();\n // exterior ring was all (within rounding error of angle calc) colinear points\n if (polyGeom === null)\n continue;\n geom.push(polyGeom);\n }\n return geom;\n }\n _composePolys(rings) {\n const polys = [];\n for (let i = 0, iMax = rings.length; i < iMax; i++) {\n const ring = rings[i];\n if (ring.poly)\n continue;\n if (ring.isExteriorRing())\n polys.push(new PolyOut(ring));\n else {\n const enclosingRing = ring.enclosingRing();\n if (!enclosingRing?.poly)\n polys.push(new PolyOut(enclosingRing));\n enclosingRing?.poly?.addInterior(ring);\n }\n }\n return polys;\n }\n}\n","import { SplayTreeSet } from \"splaytree-ts\";\nimport Segment from \"./segment.js\";\nimport SweepEvent from \"./sweep-event.js\";\n/**\n * NOTE: We must be careful not to change any segments while\n * they are in the SplayTree. AFAIK, there's no way to tell\n * the tree to rebalance itself - thus before splitting\n * a segment that's in the tree, we remove it from the tree,\n * do the split, then re-insert it. (Even though splitting a\n * segment *shouldn't* change its correct position in the\n * sweep line tree, the reality is because of rounding errors,\n * it sometimes does.)\n */\nexport default class SweepLine {\n queue;\n tree;\n segments;\n constructor(queue, comparator = Segment.compare) {\n this.queue = queue;\n this.tree = new SplayTreeSet(comparator);\n this.segments = [];\n }\n process(event) {\n const segment = event.segment;\n const newEvents = [];\n // if we've already been consumed by another segment,\n // clean up our body parts and get out\n if (event.consumedBy) {\n if (event.isLeft)\n this.queue.delete(event.otherSE);\n else\n this.tree.delete(segment);\n return newEvents;\n }\n if (event.isLeft)\n this.tree.add(segment);\n let prevSeg = segment;\n let nextSeg = segment;\n // skip consumed segments still in tree\n do {\n prevSeg = this.tree.lastBefore(prevSeg);\n } while (prevSeg != null && prevSeg.consumedBy != undefined);\n // skip consumed segments still in tree\n do {\n nextSeg = this.tree.firstAfter(nextSeg);\n } while (nextSeg != null && nextSeg.consumedBy != undefined);\n if (event.isLeft) {\n // Check for intersections against the previous segment in the sweep line\n let prevMySplitter = null;\n if (prevSeg) {\n const prevInter = prevSeg.getIntersection(segment);\n if (prevInter !== null) {\n if (!segment.isAnEndpoint(prevInter))\n prevMySplitter = prevInter;\n if (!prevSeg.isAnEndpoint(prevInter)) {\n const newEventsFromSplit = this._splitSafely(prevSeg, prevInter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n // Check for intersections against the next segment in the sweep line\n let nextMySplitter = null;\n if (nextSeg) {\n const nextInter = nextSeg.getIntersection(segment);\n if (nextInter !== null) {\n if (!segment.isAnEndpoint(nextInter))\n nextMySplitter = nextInter;\n if (!nextSeg.isAnEndpoint(nextInter)) {\n const newEventsFromSplit = this._splitSafely(nextSeg, nextInter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n // For simplicity, even if we find more than one intersection we only\n // spilt on the 'earliest' (sweep-line style) of the intersections.\n // The other intersection will be handled in a future process().\n if (prevMySplitter !== null || nextMySplitter !== null) {\n let mySplitter = null;\n if (prevMySplitter === null)\n mySplitter = nextMySplitter;\n else if (nextMySplitter === null)\n mySplitter = prevMySplitter;\n else {\n const cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter);\n mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;\n }\n // Rounding errors can cause changes in ordering,\n // so remove afected segments and right sweep events before splitting\n this.queue.delete(segment.rightSE);\n newEvents.push(segment.rightSE);\n const newEventsFromSplit = segment.split(mySplitter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n if (newEvents.length > 0) {\n // We found some intersections, so re-do the current event to\n // make sure sweep line ordering is totally consistent for later\n // use with the segment 'prev' pointers\n this.tree.delete(segment);\n newEvents.push(event);\n }\n else {\n // done with left event\n this.segments.push(segment);\n segment.prev = prevSeg;\n }\n }\n else {\n // event.isRight\n // since we're about to be removed from the sweep line, check for\n // intersections between our previous and next segments\n if (prevSeg && nextSeg) {\n const inter = prevSeg.getIntersection(nextSeg);\n if (inter !== null) {\n if (!prevSeg.isAnEndpoint(inter)) {\n const newEventsFromSplit = this._splitSafely(prevSeg, inter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n if (!nextSeg.isAnEndpoint(inter)) {\n const newEventsFromSplit = this._splitSafely(nextSeg, inter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n this.tree.delete(segment);\n }\n return newEvents;\n }\n /* Safely split a segment that is currently in the datastructures\n * IE - a segment other than the one that is currently being processed. */\n _splitSafely(seg, pt) {\n // Rounding errors can cause changes in ordering,\n // so remove afected segments and right sweep events before splitting\n // removeNode() doesn't work, so have re-find the seg\n // https://github.com/w8r/splay-tree/pull/5\n this.tree.delete(seg);\n const rightSE = seg.rightSE;\n this.queue.delete(rightSE);\n const newEvents = seg.split(pt);\n newEvents.push(rightSE);\n // splitting can trigger consumption\n if (seg.consumedBy === undefined)\n this.tree.add(seg);\n return newEvents;\n }\n}\n","import { SplayTreeSet } from \"splaytree-ts\";\nimport { getBboxOverlap } from \"./bbox.js\";\nimport * as geomIn from \"./geom-in.js\";\nimport * as geomOut from \"./geom-out.js\";\nimport { precision } from \"./precision.js\";\nimport SweepEvent from \"./sweep-event.js\";\nimport SweepLine from \"./sweep-line.js\";\nexport class Operation {\n type;\n numMultiPolys;\n run(type, geom, moreGeoms) {\n operation.type = type;\n /* Convert inputs to MultiPoly objects */\n const multipolys = [new geomIn.MultiPolyIn(geom, true)];\n for (let i = 0, iMax = moreGeoms.length; i < iMax; i++) {\n multipolys.push(new geomIn.MultiPolyIn(moreGeoms[i], false));\n }\n operation.numMultiPolys = multipolys.length;\n /* BBox optimization for difference operation\n * If the bbox of a multipolygon that's part of the clipping doesn't\n * intersect the bbox of the subject at all, we can just drop that\n * multiploygon. */\n if (operation.type === \"difference\") {\n // in place removal\n const subject = multipolys[0];\n let i = 1;\n while (i < multipolys.length) {\n if (getBboxOverlap(multipolys[i].bbox, subject.bbox) !== null)\n i++;\n else\n multipolys.splice(i, 1);\n }\n }\n /* BBox optimization for intersection operation\n * If we can find any pair of multipolygons whose bbox does not overlap,\n * then the result will be empty. */\n if (operation.type === \"intersection\") {\n // TODO: this is O(n^2) in number of polygons. By sorting the bboxes,\n // it could be optimized to O(n * ln(n))\n for (let i = 0, iMax = multipolys.length; i < iMax; i++) {\n const mpA = multipolys[i];\n for (let j = i + 1, jMax = multipolys.length; j < jMax; j++) {\n if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null)\n return [];\n }\n }\n }\n /* Put segment endpoints in a priority queue */\n const queue = new SplayTreeSet(SweepEvent.compare);\n for (let i = 0, iMax = multipolys.length; i < iMax; i++) {\n const sweepEvents = multipolys[i].getSweepEvents();\n for (let j = 0, jMax = sweepEvents.length; j < jMax; j++) {\n queue.add(sweepEvents[j]);\n }\n }\n /* Pass the sweep line over those endpoints */\n const sweepLine = new SweepLine(queue);\n let evt = null;\n if (queue.size != 0) {\n evt = queue.first();\n queue.delete(evt);\n }\n while (evt) {\n const newEvents = sweepLine.process(evt);\n for (let i = 0, iMax = newEvents.length; i < iMax; i++) {\n const evt = newEvents[i];\n if (evt.consumedBy === undefined)\n queue.add(evt);\n }\n if (queue.size != 0) {\n evt = queue.first();\n queue.delete(evt);\n }\n else {\n evt = null;\n }\n }\n // free some memory we don't need anymore\n precision.reset();\n /* Collect and compile segments we're keeping into a multipolygon */\n const ringsOut = geomOut.RingOut.factory(sweepLine.segments);\n const result = new geomOut.MultiPolyOut(ringsOut);\n return result.getGeom();\n }\n}\n// singleton available by import\nconst operation = new Operation();\nexport default operation;\n","import { precision } from \"./precision.js\";\nimport operation from \"./operation.js\";\nexport const union = (geom, ...moreGeoms) => operation.run(\"union\", geom, moreGeoms);\nexport const intersection = (geom, ...moreGeoms) => operation.run(\"intersection\", geom, moreGeoms);\nexport const xor = (geom, ...moreGeoms) => operation.run(\"xor\", geom, moreGeoms);\nexport const difference = (geom, ...moreGeoms) => operation.run(\"difference\", geom, moreGeoms);\nexport const setPrecision = precision.set;\n","import * as polygonClipping from 'polyclip-ts';\n\nexport function feature(geom) {\n const feat = { type: 'Feature' };\n feat.geometry = geom;\n return feat;\n}\n\nexport function getGeometry(geojson) {\n if (geojson.type === 'Feature') return geojson.geometry;\n return geojson;\n}\n\nexport function getCoords(geojson) {\n if (geojson && geojson.geometry && geojson.geometry.coordinates)\n return geojson.geometry.coordinates;\n return geojson;\n}\n\nexport function turfPoint(coords, precision = -1) {\n if (precision > -1) {\n coords[0] = L.Util.formatNum(coords[0], precision);\n coords[1] = L.Util.formatNum(coords[1], precision);\n }\n\n return feature({ type: 'Point', coordinates: coords });\n}\n\nexport function turfLineString(coords) {\n return feature({ type: 'LineString', coordinates: coords });\n}\n\nexport function turfMultiLineString(coords) {\n return feature({ type: 'MultiLineString', coordinates: coords });\n}\n\nexport function turfPolygon(coords) {\n return feature({ type: 'Polygon', coordinates: coords });\n}\n\nexport function turfMultiPolygon(coords) {\n return feature({ type: 'MultiPolygon', coordinates: coords });\n}\n\nexport function turfFeatureCollection(features) {\n return { type: 'FeatureCollection', features };\n}\n\nexport function intersect(poly1, poly2) {\n const geom1 = getGeometry(poly1);\n const geom2 = getGeometry(poly2);\n\n const intersection = polygonClipping.intersection(\n geom1.coordinates,\n geom2.coordinates\n );\n if (intersection.length === 0) return null;\n if (intersection.length === 1) return turfPolygon(intersection[0]);\n return turfMultiPolygon(intersection);\n}\n\nexport function difference(polygon1, polygon2) {\n const geom1 = getGeometry(polygon1);\n const geom2 = getGeometry(polygon2);\n\n const differenced = polygonClipping.difference(\n geom1.coordinates,\n geom2.coordinates\n );\n if (differenced.length === 0) return null;\n if (differenced.length === 1) return turfPolygon(differenced[0]);\n return turfMultiPolygon(differenced);\n}\n\n// LineString coords returns 1\n// MultiLineString coords returns 2\nexport function getDepthOfCoords(coords) {\n if (Array.isArray(coords)) {\n return 1 + getDepthOfCoords(coords[0]);\n }\n return -1; // return -1 because this is already the lng of the lnglat (geojson) array\n}\n\nexport function flattenPolyline(polyline) {\n if (polyline instanceof L.Polyline) {\n polyline = polyline.toGeoJSON(15);\n }\n\n const coords = getCoords(polyline);\n const depth = getDepthOfCoords(coords);\n const features = [];\n if (depth > 1) {\n coords.forEach((coord) => {\n features.push(turfLineString(coord));\n });\n } else {\n features.push(polyline);\n }\n\n return features;\n}\n\nexport function groupToMultiLineString(group) {\n const coords = [];\n group.eachLayer((layer) => {\n coords.push(getCoords(layer.toGeoJSON(15)));\n });\n return turfMultiLineString(coords);\n}\n\nexport function convertToLatLng(coords) {\n const lnglat = getCoords(coords);\n return L.latLng(lnglat[1], lnglat[0]);\n}\n\nexport function convertArrayToLatLngs(arr) {\n const latlngs = [];\n if (arr.features) {\n arr.features.forEach((geojson) => {\n latlngs.push(convertToLatLng(geojson));\n });\n }\n return latlngs;\n}\n","import Draw from './L.PM.Draw';\nimport { getTranslation } from '../helpers';\n\nDraw.Text = Draw.extend({\n initialize(map) {\n this._map = map;\n this._shape = 'Text';\n this.toolbarButtonName = 'drawText';\n },\n enable(options) {\n // TODO: Think about if these options could be passed globally for all\n // instances of L.PM.Draw. So a dev could set drawing style one time as some kind of config\n L.Util.setOptions(this, options);\n\n // change enabled state\n this._enabled = true;\n\n // create a marker on click on the map\n this._map.on('click', this._createMarker, this);\n\n // toggle the draw button of the Toolbar in case drawing mode got enabled without the button\n this._map.pm.Toolbar.toggleButton(this.toolbarButtonName, true);\n\n // this is the hintmarker on the mouse cursor\n this._hintMarker = L.marker(this._map.getCenter(), {\n interactive: false,\n zIndexOffset: 100,\n icon: L.divIcon({ className: 'marker-icon cursor-marker' }),\n });\n this._setPane(this._hintMarker, 'vertexPane');\n this._hintMarker._pmTempLayer = true;\n this._hintMarker.addTo(this._map);\n\n // show the hintmarker if the option is set\n if (this.options.cursorMarker) {\n L.DomUtil.addClass(this._hintMarker._icon, 'visible');\n }\n\n // add tooltip to hintmarker\n if (this.options.tooltips) {\n this._hintMarker\n .bindTooltip(getTranslation('tooltips.placeText'), {\n permanent: true,\n offset: L.point(0, 10),\n direction: 'bottom',\n\n opacity: 0.8,\n })\n .openTooltip();\n }\n\n // this is just to keep the snappable mixin happy\n this._layer = this._hintMarker;\n\n // sync hint marker with mouse cursor\n this._map.on('mousemove', this._syncHintMarker, this);\n\n this._map.getContainer().classList.add('geoman-draw-cursor');\n\n // fire drawstart event\n this._fireDrawStart();\n this._setGlobalDrawMode();\n },\n disable() {\n // cancel, if drawing mode isn't even enabled\n if (!this._enabled) {\n return;\n }\n\n // change enabled state\n this._enabled = false;\n\n // undbind click event, don't create a marker on click anymore\n this._map.off('click', this._createMarker, this);\n\n // remove hint marker\n this._hintMarker?.remove();\n\n this._map.getContainer().classList.remove('geoman-draw-cursor');\n\n // remove event listener to sync hint marker\n this._map.off('mousemove', this._syncHintMarker, this);\n\n // toggle the draw button of the Toolbar in case drawing mode got disabled without the button\n this._map.pm.Toolbar.toggleButton(this.toolbarButtonName, false);\n\n // cleanup snapping\n if (this.options.snappable) {\n this._cleanupSnapping();\n }\n\n // fire drawend event\n this._fireDrawEnd();\n this._setGlobalDrawMode();\n },\n enabled() {\n return this._enabled;\n },\n toggle(options) {\n if (this.enabled()) {\n this.disable();\n } else {\n this.enable(options);\n }\n },\n _syncHintMarker(e) {\n // move the cursor marker\n this._hintMarker.setLatLng(e.latlng);\n\n // if snapping is enabled, do it\n if (this.options.snappable) {\n const fakeDragEvent = e;\n fakeDragEvent.target = this._hintMarker;\n this._handleSnapping(fakeDragEvent);\n }\n },\n _createMarker(e) {\n if (!e.latlng) {\n return;\n }\n\n // If snap finish is required but the last marker wasn't snapped, do not finish the shape!\n if (\n this.options.requireSnapToFinish &&\n !this._hintMarker._snapped &&\n !this._isFirstLayer()\n ) {\n return;\n }\n\n // assign the coordinate of the click to the hintMarker, that's necessary for\n // mobile where the marker can't follow a cursor\n if (!this._hintMarker._snapped) {\n this._hintMarker.setLatLng(e.latlng);\n }\n\n // get coordinate for new vertex by hintMarker (cursor marker)\n const latlng = this._hintMarker.getLatLng();\n\n this.textArea = this._createTextArea();\n\n if (this.options.textOptions?.className) {\n const cssClasses = this.options.textOptions.className.split(' ');\n this.textArea.classList.add(...cssClasses);\n }\n\n const textAreaIcon = this._createTextIcon(this.textArea);\n\n const marker = new L.Marker(latlng, {\n textMarker: true,\n _textMarkerOverPM: true, // we need to put this into the options, else we can't catch this in the init method\n icon: textAreaIcon,\n });\n this._setPane(marker, 'markerPane');\n this._finishLayer(marker);\n\n if (!marker.pm) {\n // if pm is not create we don't apply dragging to the marker (draggable is applied to the marker, when it is added to the map )\n marker.options.draggable = false;\n }\n // add marker to the map\n marker.addTo(this._map.pm._getContainingLayer());\n if (marker.pm) {\n marker.pm.textArea = this.textArea;\n L.setOptions(marker.pm, {\n removeIfEmpty: this.options.textOptions?.removeIfEmpty ?? true,\n });\n\n const focusAfterDraw = this.options.textOptions?.focusAfterDraw ?? true;\n marker.pm._createTextMarker(focusAfterDraw);\n if (this.options.textOptions?.text) {\n marker.pm.setText(this.options.textOptions.text);\n }\n }\n\n // fire the pm:create event and pass shape and marker\n this._fireCreate(marker);\n\n this._cleanupSnapping();\n\n // disable drawing\n this.disable();\n if (this.options.continueDrawing) {\n this.enable();\n }\n },\n\n _createTextArea() {\n const textArea = document.createElement('textarea');\n textArea.readOnly = true;\n textArea.classList.add('pm-textarea', 'pm-disabled');\n return textArea;\n },\n\n _createTextIcon(textArea) {\n return L.divIcon({\n className: 'pm-text-marker',\n html: textArea,\n });\n },\n});\n","import { getRenderer } from '../helpers';\n\nconst DragMixin = {\n enableLayerDrag() {\n // layer is not allowed to dragged or is not on the map\n if (!this.options.draggable || !this._layer._map) {\n return;\n }\n\n // before enabling layer drag, disable layer editing\n this.disable();\n\n this._layerDragEnabled = true;\n\n // if layer never enabled and _map is not set (for snapping)\n if (!this._map) {\n this._map = this._layer._map;\n }\n\n if (\n this._layer instanceof L.Marker ||\n this._layer instanceof L.ImageOverlay\n ) {\n // prevents dragging the DOM image instead of the marker\n L.DomEvent.on(this._getDOMElem(), 'dragstart', this._stopDOMImageDrag);\n }\n\n // Disable Leaflet Dragging of Markers\n if (this._layer.dragging) {\n this._layer.dragging.disable();\n }\n\n // temporary coord variable for delta calculation\n this._tempDragCoord = null;\n\n // add CSS class\n if (getRenderer(this._layer) instanceof L.Canvas) {\n this._layer.on('mouseout', this.removeDraggingClass, this);\n this._layer.on('mouseover', this.addDraggingClass, this);\n } else {\n this.addDraggingClass();\n }\n\n this._originalMapDragState = this._layer._map.dragging._enabled;\n\n // can we reliably save the map's draggable state?\n // (if the mouse up event happens outside the container, then the map can become undraggable)\n this._safeToCacheDragState = true;\n\n const container = this._getDOMElem();\n\n // check if DOM element exists\n if (container) {\n // add mousedown event to trigger drag\n if (getRenderer(this._layer) instanceof L.Canvas) {\n this._layer.on(\n 'touchstart mousedown',\n this._dragMixinOnMouseDown,\n this\n );\n this._map.pm._addTouchEvents(container);\n } else {\n // We can't just use layer.on('mousedown') because on touch devices the event is not fired if user presses on the layer and then drag it.\n // With checking on touchstart and mousedown on the DOM element we can listen on the needed events\n L.DomEvent.on(\n container,\n 'touchstart mousedown',\n this._simulateMouseDownEvent,\n this\n );\n }\n }\n\n this._fireDragEnable();\n },\n disableLayerDrag() {\n this._layerDragEnabled = false;\n\n // remove CSS class\n if (getRenderer(this._layer) instanceof L.Canvas) {\n this._layer.off('mouseout', this.removeDraggingClass, this);\n this._layer.off('mouseover', this.addDraggingClass, this);\n } else {\n this.removeDraggingClass();\n }\n\n // if the layer is dragged but now disabled\n if (this._originalMapDragState && this._dragging) {\n this._map.dragging.enable();\n }\n\n // no longer save the drag state\n this._safeToCacheDragState = false;\n\n // Disable Leaflet Dragging of Markers\n if (this._layer.dragging) {\n this._layer.dragging.disable();\n }\n\n const container = this._getDOMElem();\n // check if DOM element exists\n if (container) {\n if (getRenderer(this._layer) instanceof L.Canvas) {\n this._layer.off(\n 'touchstart mousedown',\n this._dragMixinOnMouseDown,\n this\n );\n this._map.pm._removeTouchEvents(container);\n } else {\n // disable mousedown event\n L.DomEvent.off(\n container,\n 'touchstart mousedown',\n this._simulateMouseDownEvent,\n this\n );\n }\n }\n\n if (this._layerDragged) {\n this._fireUpdate();\n }\n this._layerDragged = false;\n\n this._fireDragDisable();\n },\n // TODO: make this private in the next major release\n dragging() {\n return this._dragging;\n },\n layerDragEnabled() {\n return !!this._layerDragEnabled;\n },\n // We need to simulate a mousedown event on the layer object. We can't just use layer.on('mousedown') because on touch devices the event is not fired if user presses on the layer and then drag it.\n // With checking on touchstart and mousedown on the DOM element we can listen on the needed events\n _simulateMouseDownEvent(e) {\n const first = e.touches ? e.touches[0] : e;\n const evt = {\n originalEvent: first,\n target: this._layer,\n };\n // we expect in the function to get the clicked latlng / point\n evt.containerPoint = this._map.mouseEventToContainerPoint(first);\n evt.latlng = this._map.containerPointToLatLng(evt.containerPoint);\n\n this._dragMixinOnMouseDown(evt);\n return false;\n },\n _simulateMouseMoveEvent(e) {\n const first = e.touches ? e.touches[0] : e;\n const evt = {\n originalEvent: first,\n target: this._layer,\n };\n // we expect in the function to get the clicked latlng / point\n evt.containerPoint = this._map.mouseEventToContainerPoint(first);\n evt.latlng = this._map.containerPointToLatLng(evt.containerPoint);\n\n this._dragMixinOnMouseMove(evt);\n return false;\n },\n _simulateMouseUpEvent(e) {\n const first = e.touches ? e.touches[0] : e;\n const evt = {\n originalEvent: first,\n target: this._layer,\n };\n if (e.type.indexOf('touch') === -1) {\n // we expect in the function to get the clicked latlng / point\n evt.containerPoint = this._map.mouseEventToContainerPoint(e);\n evt.latlng = this._map.containerPointToLatLng(evt.containerPoint);\n }\n this._dragMixinOnMouseUp(evt);\n return false;\n },\n _dragMixinOnMouseDown(e) {\n // cancel if mouse button is NOT the left button\n if (e.originalEvent.button > 0) {\n return;\n }\n this._overwriteEventIfItComesFromMarker(e);\n\n const fromLayerSync = e._fromLayerSync;\n\n // if other layers found, snapping will be disabled\n const layersToSyncFound = this._syncLayers('_dragMixinOnMouseDown', e);\n\n if (this._layer instanceof L.Marker) {\n if (this.options.snappable && !fromLayerSync && !layersToSyncFound) {\n this._initSnappableMarkers();\n } else {\n this._disableSnapping();\n }\n }\n\n // we need to disable snapping for CircleMarker because they are snapping because of the check in onLayerDrag -> if(_snapped)\n if (this._layer instanceof L.CircleMarker) {\n let _editableOption = 'resizeableCircleMarker';\n if (this._layer instanceof L.Circle) {\n _editableOption = 'resizableCircle';\n }\n\n if (this.options.snappable && !fromLayerSync && !layersToSyncFound) {\n if (!this._layer.pm.options[_editableOption]) {\n this._initSnappableMarkersDrag();\n }\n } else if (this._layer.pm.options[_editableOption]) {\n this._layer.pm._disableSnapping();\n } else {\n this._layer.pm._disableSnappingDrag();\n }\n }\n\n // save current map dragging state\n if (this._safeToCacheDragState) {\n this._originalMapDragState = this._layer._map.dragging._enabled;\n\n // don't cache the state again until another mouse up is registered\n this._safeToCacheDragState = false;\n }\n\n // save for delta calculation\n this._tempDragCoord = e.latlng;\n\n L.DomEvent.on(\n this._map.getContainer(),\n 'touchend mouseup',\n this._simulateMouseUpEvent,\n this\n );\n\n // listen to mousemove on map (instead of polygon),\n // otherwise fast mouse movements stop the drag\n L.DomEvent.on(\n this._map.getContainer(),\n 'touchmove mousemove',\n this._simulateMouseMoveEvent,\n this\n );\n },\n _dragMixinOnMouseMove(e) {\n this._overwriteEventIfItComesFromMarker(e);\n const el = this._getDOMElem();\n\n this._syncLayers('_dragMixinOnMouseMove', e);\n\n if (!this._dragging) {\n // set state\n this._dragging = true;\n L.DomUtil.addClass(el, 'leaflet-pm-dragging');\n\n if (!(this._layer instanceof L.Marker)) {\n // bring it to front to prevent drag interception\n this._layer.bringToFront();\n }\n\n // disbale map drag\n if (this._originalMapDragState) {\n this._map.dragging.disable();\n }\n\n // fire pm:dragstart event\n this._fireDragStart();\n }\n\n // if _tempDragCoord is null add the current latlng to prevent throwing a error. This can happen when for example the layer is removed and added to the map while dragging (MarkerCluster)\n if (!this._tempDragCoord) {\n this._tempDragCoord = e.latlng;\n }\n\n this._onLayerDrag(e);\n\n // update the hidden circle border after dragging\n if (this._layer instanceof L.CircleMarker) {\n this._layer.pm._updateHiddenPolyCircle();\n }\n },\n _dragMixinOnMouseUp(e) {\n const el = this._getDOMElem();\n\n this._syncLayers('_dragMixinOnMouseUp', e);\n\n // re-enable map drag\n if (this._originalMapDragState) {\n this._map.dragging.enable();\n }\n\n // if mouseup event fired, it's safe to cache the map draggable state on the next mouse down\n this._safeToCacheDragState = true;\n // clear up mousemove event\n L.DomEvent.off(\n this._map.getContainer(),\n 'touchmove mousemove',\n this._simulateMouseMoveEvent,\n this\n );\n\n // clear up mouseup event\n L.DomEvent.off(\n this._map.getContainer(),\n 'touchend mouseup',\n this._simulateMouseUpEvent,\n this\n );\n\n // if no drag happened, don't do anything\n if (!this._dragging) {\n return false;\n }\n\n // update the hidden circle border after dragging\n if (this._layer instanceof L.CircleMarker) {\n this._layer.pm._updateHiddenPolyCircle();\n }\n\n this._layerDragged = true;\n\n // timeout to prevent click event after drag :-/\n // TODO: do it better as soon as leaflet has a way to do it better :-)\n window.setTimeout(() => {\n // set state\n this._dragging = false;\n // if the layer is not on the map, we have no DOM element\n if (el) {\n L.DomUtil.removeClass(el, 'leaflet-pm-dragging');\n }\n\n // fire pm:dragend event\n this._fireDragEnd();\n\n // fire edit\n this._fireEdit();\n this._layerEdited = true;\n }, 10);\n\n return true;\n },\n _onLayerDrag(e) {\n // latLng of mouse event\n const { latlng } = e;\n\n // delta coords (how far was dragged)\n const deltaLatLng = {\n lat: latlng.lat - this._tempDragCoord.lat,\n lng: latlng.lng - this._tempDragCoord.lng,\n };\n\n // move the coordinates by the delta\n const moveCoords = (coords) =>\n // alter the coordinates\n coords.map((currentLatLng) => {\n if (Array.isArray(currentLatLng)) {\n // do this recursively as coords might be nested\n return moveCoords(currentLatLng);\n }\n\n // move the coord and return it\n const newLatlng = {\n lat: currentLatLng.lat + deltaLatLng.lat,\n lng: currentLatLng.lng + deltaLatLng.lng,\n };\n\n if (currentLatLng.alt || currentLatLng.alt === 0) {\n newLatlng.alt = currentLatLng.alt;\n }\n return newLatlng;\n });\n\n if (\n (this._layer instanceof L.Circle &&\n this._layer.options.resizableCircle) ||\n (this._layer instanceof L.CircleMarker &&\n this._layer.options.resizeableCircleMarker)\n ) {\n // create the new coordinates array\n const newCoords = moveCoords([this._layer.getLatLng()]);\n // set new coordinates and redraw\n this._layer.setLatLng(newCoords[0]);\n this._fireChange(this._layer.getLatLng(), 'Edit');\n } else if (\n this._layer instanceof L.CircleMarker ||\n this._layer instanceof L.Marker\n ) {\n let coordsRefernce = this._layer.getLatLng();\n if (this._layer._snapped) {\n // if layer is snapped we use the original latlng for re-calculation, else the layer will not be \"unsnappable\" anymore\n coordsRefernce = this._layer._orgLatLng;\n }\n // create the new coordinates array\n const newCoords = moveCoords([coordsRefernce]);\n // set new coordinates and redraw\n this._layer.setLatLng(newCoords[0]);\n this._fireChange(this._layer.getLatLng(), 'Edit');\n } else if (this._layer instanceof L.ImageOverlay) {\n // create the new coordinates array\n const newCoords = moveCoords([\n this._layer.getBounds().getNorthWest(),\n this._layer.getBounds().getSouthEast(),\n ]);\n // set new coordinates and redraw\n this._layer.setBounds(newCoords);\n this._fireChange(this._layer.getBounds(), 'Edit');\n } else {\n // create the new coordinates array\n const newCoords = moveCoords(this._layer.getLatLngs());\n\n // set new coordinates and redraw\n this._layer.setLatLngs(newCoords);\n this._fireChange(this._layer.getLatLngs(), 'Edit');\n }\n\n // save current latlng for next delta calculation\n this._tempDragCoord = latlng;\n\n e.layer = this._layer;\n // fire pm:dragstart event\n this._fireDrag(e);\n },\n addDraggingClass() {\n const el = this._getDOMElem();\n if (el) {\n L.DomUtil.addClass(el, 'leaflet-pm-draggable');\n }\n },\n removeDraggingClass() {\n const el = this._getDOMElem();\n if (el) {\n L.DomUtil.removeClass(el, 'leaflet-pm-draggable');\n }\n },\n _getDOMElem() {\n let el = null;\n if (this._layer._path) {\n el = this._layer._path;\n } else if (this._layer._renderer && this._layer._renderer._container) {\n el = this._layer._renderer._container;\n } else if (this._layer._image) {\n el = this._layer._image;\n } else if (this._layer._icon) {\n el = this._layer._icon;\n }\n return el;\n },\n _overwriteEventIfItComesFromMarker(e) {\n // e.latlng is not the clicked latlng if the layer is a Marker (or the radius below 10) -> Leaflet definition\n // https://github.com/Leaflet/Leaflet/blob/0f904a515879fcd08f69b7f51799ee7f18f23fd8/src/map/Map.js#L1416\n const isMarker =\n e.target.getLatLng && (!e.target._radius || e.target._radius <= 10);\n if (isMarker) {\n // we want the clicked latlng / point, so we overwrite the property e.latlng\n e.containerPoint = this._map.mouseEventToContainerPoint(e.originalEvent);\n e.latlng = this._map.containerPointToLatLng(e.containerPoint);\n }\n },\n _syncLayers(fnc, e) {\n // if layer is in Edit-Mode it should not be possible to drag other layers too. (Marker & CircleMarker & ImageOverlay)\n if (this.enabled()) {\n return false;\n }\n\n if (\n !e._fromLayerSync &&\n this._layer === e.target &&\n this.options.syncLayersOnDrag\n ) {\n e._fromLayerSync = true;\n let layersToSync = [];\n if (L.Util.isArray(this.options.syncLayersOnDrag)) {\n // layers\n layersToSync = this.options.syncLayersOnDrag;\n\n this.options.syncLayersOnDrag.forEach((layer) => {\n if (layer instanceof L.LayerGroup) {\n layersToSync = layersToSync.concat(layer.pm.getLayers(true));\n }\n });\n } else if (this.options.syncLayersOnDrag === true) {\n // LayerGroup\n if (this._parentLayerGroup) {\n for (const key in this._parentLayerGroup) {\n const lg = this._parentLayerGroup[key];\n if (lg.pm) {\n layersToSync = lg.pm.getLayers(true);\n }\n }\n }\n }\n\n if (L.Util.isArray(layersToSync) && layersToSync.length > 0) {\n // filter out layers that don't have leaflet-geoman and not allowed to drag\n layersToSync = layersToSync\n .filter((layer) => !!layer.pm)\n .filter((layer) => !!layer.pm.options.draggable);\n layersToSync.forEach((layer) => {\n if (layer !== this._layer && layer.pm[fnc]) {\n layer._snapped = false;\n layer.pm[fnc](e);\n }\n });\n }\n return layersToSync.length > 0;\n }\n return false;\n },\n _stopDOMImageDrag(e) {\n e.preventDefault();\n return false;\n },\n};\n\nexport default DragMixin;\n","import get from 'lodash/get';\nimport { _convertLatLngs, _toPoint } from '../helpers/ModeHelper';\nimport { calcAngle, copyLatLngs } from '../helpers';\n\n/**\n * We create a temporary polygon with the same latlngs as the layer that we want to rotate.\n * Why polygon? Because then we have the correct center also for polylines with `layer.getCenter()`.\n * We reference the origin layer as `_rotationLayer`. The rotate listeners (`_onRotate...()`) are only applied to the temp polygon and from there we need to rotate the `_rotationLayer` too.\n *\n */\n\nconst RotateMixin = {\n _onRotateStart(e) {\n // prevent that the limit Markers are calculated new\n this._preventRenderingMarkers(true);\n this._rotationOriginLatLng = this._getRotationCenter().clone();\n this._rotationOriginPoint = _toPoint(this._map, this._rotationOriginLatLng);\n this._rotationStartPoint = _toPoint(this._map, e.target.getLatLng());\n // we need to store the initial latlngs so we can always re-calc from the origin latlngs\n this._initialRotateLatLng = copyLatLngs(this._layer);\n this._startAngle = this.getAngle();\n\n const originLatLngs = copyLatLngs(\n this._rotationLayer,\n this._rotationLayer.pm._rotateOrgLatLng\n );\n\n this._fireRotationStart(this._rotationLayer, originLatLngs);\n this._fireRotationStart(this._map, originLatLngs);\n },\n _onRotate(e) {\n const position = _toPoint(this._map, e.target.getLatLng());\n const previous = this._rotationStartPoint;\n const origin = this._rotationOriginPoint;\n\n // rotation diff angle (radiant)\n const angleDiffRadiant =\n Math.atan2(position.y - origin.y, position.x - origin.x) -\n Math.atan2(previous.y - origin.y, previous.x - origin.x);\n\n // rotate the temp polygon\n this._layer.setLatLngs(\n this._rotateLayer(\n angleDiffRadiant,\n this._initialRotateLatLng,\n this._rotationOriginLatLng,\n L.PM.Matrix.init(),\n this._map\n )\n );\n // move the helper markers\n const that = this;\n function forEachLatLng(latlng, path = [], _i = -1) {\n if (_i > -1) {\n path.push(_i);\n }\n if (L.Util.isArray(latlng[0])) {\n latlng.forEach((x, i) => forEachLatLng(x, path.slice(), i));\n } else {\n const markers = get(that._markers, path);\n latlng.forEach((_latlng, j) => {\n const marker = markers[j];\n marker.setLatLng(_latlng);\n });\n }\n }\n forEachLatLng(this._layer.getLatLngs());\n\n const oldLatLngs = copyLatLngs(this._rotationLayer);\n // rotate the origin layer\n this._rotationLayer.setLatLngs(\n this._rotateLayer(\n angleDiffRadiant,\n this._rotationLayer.pm._rotateOrgLatLng,\n this._rotationOriginLatLng,\n L.PM.Matrix.init(),\n this._map\n )\n );\n\n // convert the difference radiant to degrees and add it to the angle before rotation starts\n let angleDiff = (angleDiffRadiant * 180) / Math.PI;\n angleDiff = angleDiff < 0 ? angleDiff + 360 : angleDiff;\n const angle = angleDiff + this._startAngle;\n this._setAngle(angle);\n this._rotationLayer.pm._setAngle(angle);\n\n this._fireRotation(this._rotationLayer, angleDiff, oldLatLngs);\n this._fireRotation(this._map, angleDiff, oldLatLngs);\n this._rotationLayer.pm._fireChange(\n this._rotationLayer.getLatLngs(),\n 'Rotation'\n );\n },\n _onRotateEnd() {\n const startAngle = this._startAngle;\n delete this._rotationOriginLatLng;\n delete this._rotationOriginPoint;\n delete this._rotationStartPoint;\n delete this._initialRotateLatLng;\n delete this._startAngle;\n\n const originLatLngs = copyLatLngs(\n this._rotationLayer,\n this._rotationLayer.pm._rotateOrgLatLng\n );\n // store the new latlngs\n this._rotationLayer.pm._rotateOrgLatLng = copyLatLngs(this._rotationLayer);\n\n this._fireRotationEnd(this._rotationLayer, startAngle, originLatLngs);\n this._fireRotationEnd(this._map, startAngle, originLatLngs);\n this._rotationLayer.pm._fireEdit(this._rotationLayer, 'Rotation');\n\n this._preventRenderingMarkers(false);\n\n this._layerRotated = true;\n },\n _rotateLayer(radiant, latlngs, origin, _matrix, map) {\n const originPoint = _toPoint(map, origin);\n this._matrix = _matrix.clone().rotate(radiant, originPoint).flip();\n return _convertLatLngs(latlngs, this._matrix, map);\n },\n _setAngle(angle) {\n angle = angle < 0 ? angle + 360 : angle;\n this._angle = angle % 360;\n },\n _getRotationCenter() {\n if (this._rotationCenter) {\n return this._rotationCenter;\n }\n\n const polygon = L.polygon(this._layer.getLatLngs(), {\n stroke: false,\n fill: false,\n pmIgnore: true,\n }).addTo(this._layer._map);\n const center = polygon.getCenter();\n polygon.removeFrom(this._layer._map);\n return center;\n },\n\n /*\n *\n * Public functions f.ex. to disable and enable rotation on the layer directly\n *\n */\n enableRotate() {\n if (!this.options.allowRotation) {\n this.disableRotate();\n return;\n }\n\n if (this.rotateEnabled()) {\n this.disableRotate();\n }\n\n if (this._layer instanceof L.Rectangle && this._angle === undefined) {\n this.setInitAngle(\n calcAngle(\n this._layer._map,\n this._layer.getLatLngs()[0][0],\n this._layer.getLatLngs()[0][1]\n ) || 0\n );\n }\n\n // We create an hidden polygon. We set pmIgnore to false, so that the `pm` property will be always create, also if OptIn == true\n const options = {\n fill: false,\n stroke: false,\n pmIgnore: false,\n snapIgnore: true,\n };\n\n // we create a temp polygon for rotation\n this._rotatePoly = L.polygon(this._layer.getLatLngs(), options);\n this._rotatePoly._pmTempLayer = true;\n this._rotatePoly.addTo(this._layer._map);\n this._rotatePoly.pm._setAngle(this.getAngle());\n this._rotatePoly.pm.setRotationCenter(this.getRotationCenter());\n this._rotatePoly.pm.setOptions(this._layer._map.pm.getGlobalOptions());\n this._rotatePoly.pm.setOptions({\n rotate: true,\n snappable: false,\n hideMiddleMarkers: true,\n });\n // we connect the temp polygon (that will be enabled for rotation) with the current layer, so that we can rotate the current layer too\n this._rotatePoly.pm._rotationLayer = this._layer;\n this._rotatePoly.pm.enable();\n\n // store the original latlngs\n this._rotateOrgLatLng = copyLatLngs(this._layer);\n\n this._rotateEnabled = true;\n\n this._layer.on('remove', this.disableRotate, this);\n\n this._fireRotationEnable(this._layer);\n // we need to use this._layer._map because this._map can be undefined if layer was never enabled for editing before\n this._fireRotationEnable(this._layer._map);\n },\n disableRotate() {\n if (this.rotateEnabled()) {\n if (this._rotatePoly.pm._layerRotated) {\n this._fireUpdate();\n }\n this._rotatePoly.pm._layerRotated = false;\n // delete the temp polygon\n this._rotatePoly.pm.disable();\n this._rotatePoly.remove();\n this._rotatePoly.pm.setOptions({ rotate: false });\n this._rotatePoly = undefined;\n this._rotateOrgLatLng = undefined;\n\n this._layer.off('remove', this.disableRotate, this);\n\n this._rotateEnabled = false;\n\n this._fireRotationDisable(this._layer);\n // we need to use this._layer._map because this._map can be undefined if layer was never enabled for editing before\n this._fireRotationDisable(this._layer._map);\n }\n },\n rotateEnabled() {\n return !!this._rotateEnabled;\n },\n // angle is clockwise (0-360)\n rotateLayer(degrees) {\n const oldAngle = this.getAngle();\n const oldLatLngs = this._layer.getLatLngs();\n const rads = degrees * (Math.PI / 180);\n this._layer.setLatLngs(\n this._rotateLayer(\n rads,\n this._layer.getLatLngs(),\n this._getRotationCenter(),\n L.PM.Matrix.init(),\n this._layer._map\n )\n );\n // store the new latlngs\n this._rotateOrgLatLng = L.polygon(this._layer.getLatLngs()).getLatLngs();\n this._setAngle(this.getAngle() + degrees);\n if (\n this.rotateEnabled() &&\n this._rotatePoly &&\n this._rotatePoly.pm.enabled()\n ) {\n this._rotatePoly.setLatLngs(\n this._rotateLayer(\n rads,\n this._rotatePoly.getLatLngs(),\n this._getRotationCenter(),\n L.PM.Matrix.init(),\n this._rotatePoly._map\n )\n );\n this._rotatePoly.pm._initMarkers();\n }\n\n // TODO: for negative angle change the difference is always (360 - angle), do we want this?\n let angleDiff = this.getAngle() - oldAngle;\n angleDiff = angleDiff < 0 ? angleDiff + 360 : angleDiff;\n\n this._startAngle = oldAngle;\n this._fireRotation(this._layer, angleDiff, oldLatLngs, this._layer);\n this._fireRotation(\n this._map || this._layer._map,\n angleDiff,\n oldLatLngs,\n this._layer\n );\n delete this._startAngle;\n this._fireChange(this._layer.getLatLngs(), 'Rotation');\n },\n rotateLayerToAngle(degrees) {\n const newAnlge = degrees - this.getAngle();\n this.rotateLayer(newAnlge);\n },\n // angle is clockwise (0-360)\n getAngle() {\n return this._angle || 0;\n },\n // angle is clockwise (0-360)\n setInitAngle(degrees) {\n this._setAngle(degrees);\n },\n getRotationCenter() {\n return this._getRotationCenter();\n },\n setRotationCenter(center) {\n this._rotationCenter = center;\n\n if (this._rotatePoly) {\n this._rotatePoly.pm.setRotationCenter(center);\n }\n },\n};\n\nexport default RotateMixin;\n","export function _convertLatLng(latlng, matrix, map, zoom) {\n return map.unproject(matrix.transform(map.project(latlng, zoom)), zoom);\n}\n\nexport function _convertLatLngs(latlng, matrix, map) {\n let zoom = map.getMaxZoom();\n if (zoom === Infinity) {\n zoom = map.getZoom();\n }\n if (L.Util.isArray(latlng)) {\n const latlngs = [];\n latlng.forEach((x) => {\n latlngs.push(_convertLatLngs(x, matrix, map));\n });\n return latlngs;\n }\n if (latlng instanceof L.LatLng) {\n return _convertLatLng(latlng, matrix, map, zoom);\n }\n return null;\n}\n\nexport function _toPoint(map, latlng) {\n if (latlng instanceof L.Layer) {\n latlng = latlng.getLatLng();\n }\n let zoom = map.getMaxZoom();\n if (zoom === Infinity) {\n zoom = map.getZoom();\n }\n return map.project(latlng, zoom);\n}\n\nexport function _toLatLng(map, point) {\n let zoom = map.getMaxZoom();\n if (zoom === Infinity) {\n zoom = map.getZoom();\n }\n return map.unproject(point, zoom);\n}\n","import SnapMixin from '../Mixins/Snapping';\nimport DragMixin from '../Mixins/Dragging';\nimport RotateMixin from '../Mixins/Rotating';\nimport EventMixin from '../Mixins/Events';\n\nconst Edit = L.Class.extend({\n includes: [DragMixin, SnapMixin, RotateMixin, EventMixin],\n options: {\n snappable: true, // TODO: next major Release, rename it to allowSnapping\n snapDistance: 20,\n allowSelfIntersection: true,\n allowSelfIntersectionEdit: false,\n preventMarkerRemoval: false,\n removeLayerBelowMinVertexCount: true,\n limitMarkersToCount: -1,\n hideMiddleMarkers: false,\n snapSegment: true,\n syncLayersOnDrag: false,\n draggable: true, // TODO: next major Release, rename it to allowDragging\n allowEditing: true, // disable all interactions on a layer which are activated with `enable()`. For example a Circle can't be dragged in Edit-Mode\n allowRemoval: true,\n allowCutting: true,\n allowRotation: true,\n addVertexOn: 'click',\n removeVertexOn: 'contextmenu',\n removeVertexValidation: undefined,\n addVertexValidation: undefined,\n moveVertexValidation: undefined,\n resizeableCircleMarker: false,\n resizableCircle: true,\n },\n setOptions(options) {\n L.Util.setOptions(this, options);\n },\n getOptions() {\n return this.options;\n },\n applyOptions() {},\n isPolygon() {\n // if it's a polygon, it means the coordinates array is multi dimensional\n return this._layer instanceof L.Polygon;\n },\n getShape() {\n return this._shape;\n },\n _setPane(layer, type) {\n if (type === 'layerPane') {\n layer.options.pane =\n (this._map.pm.globalOptions.panes &&\n this._map.pm.globalOptions.panes.layerPane) ||\n 'overlayPane';\n } else if (type === 'vertexPane') {\n layer.options.pane =\n (this._map.pm.globalOptions.panes &&\n this._map.pm.globalOptions.panes.vertexPane) ||\n 'markerPane';\n } else if (type === 'markerPane') {\n layer.options.pane =\n (this._map.pm.globalOptions.panes &&\n this._map.pm.globalOptions.panes.markerPane) ||\n 'markerPane';\n }\n },\n remove() {\n const map = this._map || this._layer._map;\n map.pm.removeLayer({ target: this._layer });\n },\n _vertexValidation(type, e) {\n const marker = e.target;\n const args = { layer: this._layer, marker, event: e };\n\n let validationFnc = '';\n if (type === 'move') {\n validationFnc = 'moveVertexValidation';\n } else if (type === 'add') {\n validationFnc = 'addVertexValidation';\n } else if (type === 'remove') {\n validationFnc = 'removeVertexValidation';\n }\n\n // if validation goes wrong, we return false\n if (\n this.options[validationFnc] &&\n typeof this.options[validationFnc] === 'function' &&\n !this.options[validationFnc](args)\n ) {\n if (type === 'move') {\n marker._cancelDragEventChain = marker.getLatLng();\n }\n return false;\n }\n\n marker._cancelDragEventChain = null;\n return true;\n },\n _vertexValidationDrag(marker) {\n // we reset the marker to the place before it was dragged. We need this, because we can't stop the drag process in a `dragstart` | `movestart` listener\n if (marker._cancelDragEventChain) {\n marker._latlng = marker._cancelDragEventChain;\n marker.update();\n return false;\n }\n return true;\n },\n _vertexValidationDragEnd(marker) {\n if (marker._cancelDragEventChain) {\n marker._cancelDragEventChain = null;\n return false;\n }\n return true;\n },\n});\n\nexport default Edit;\n","import Edit from './L.PM.Edit';\n\n// LayerGroup doesn't inherit from L.PM.Edit because it's just calling L.PM.Edit.Polygon\n// (which inherits from L.PM.Edit) for each layer,\n// so it's not really a parent class\nEdit.LayerGroup = L.Class.extend({\n initialize(layerGroup) {\n this._layerGroup = layerGroup;\n this._layers = this.getLayers();\n this._getMap();\n\n // init all layers of the group\n this._layers.forEach((layer) => this._initLayer(layer));\n\n // if a new layer is added to the group, reinitialize\n // This only works for FeatureGroups, not LayerGroups\n // https://github.com/Leaflet/Leaflet/issues/4861\n\n const addThrottle = (e) => {\n if (e.layer._pmTempLayer) {\n return;\n }\n this._layers = this.getLayers();\n const _initLayers = this._layers.filter(\n (layer) =>\n !layer.pm._parentLayerGroup ||\n !(this._layerGroup._leaflet_id in layer.pm._parentLayerGroup)\n );\n // init the newly added layers (can be multiple because of the throttle)\n _initLayers.forEach((layer) => {\n this._initLayer(layer);\n });\n // if editing was already enabled for this group, enable it again\n // so the new layers are enabled\n if (\n _initLayers.length > 0 &&\n this._getMap() &&\n this._getMap().pm.globalEditModeEnabled()\n ) {\n if (this.enabled()) {\n this.enable(this.getOptions());\n }\n }\n };\n this._layerGroup.on(\n 'layeradd',\n L.Util.throttle(addThrottle, 100, this),\n this\n );\n\n // Remove the layergroup from the layer\n this._layerGroup.on(\n 'layerremove',\n (e) => {\n this._removeLayerFromGroup(e.target);\n },\n this\n );\n\n const removeThrottle = (e) => {\n if (e.target._pmTempLayer) {\n return;\n }\n this._layers = this.getLayers();\n };\n // if a layer is removed from the group, calc the layers list again.\n // we run this as throttle because the findLayers() is a larger function\n this._layerGroup.on(\n 'layerremove',\n L.Util.throttle(removeThrottle, 100, this),\n this\n );\n },\n enable(options, _layerIds = []) {\n if (_layerIds.length === 0) {\n this._layers = this.getLayers();\n }\n this._options = options;\n this._layers.forEach((layer) => {\n if (layer instanceof L.LayerGroup) {\n if (_layerIds.indexOf(layer._leaflet_id) === -1) {\n _layerIds.push(layer._leaflet_id);\n layer.pm.enable(options, _layerIds);\n }\n } else {\n layer.pm.enable(options);\n }\n });\n },\n disable(_layerIds = []) {\n if (_layerIds.length === 0) {\n this._layers = this.getLayers();\n }\n this._layers.forEach((layer) => {\n if (layer instanceof L.LayerGroup) {\n if (_layerIds.indexOf(layer._leaflet_id) === -1) {\n _layerIds.push(layer._leaflet_id);\n layer.pm.disable(_layerIds);\n }\n } else {\n layer.pm.disable();\n }\n });\n },\n enabled(_layerIds = []) {\n if (_layerIds.length === 0) {\n this._layers = this.getLayers();\n }\n const enabled = this._layers.find((layer) => {\n if (layer instanceof L.LayerGroup) {\n if (_layerIds.indexOf(layer._leaflet_id) === -1) {\n _layerIds.push(layer._leaflet_id);\n return layer.pm.enabled(_layerIds);\n }\n return false; // enabled is already returned because this is not the first time, so we can return always false\n }\n return layer.pm.enabled();\n });\n return !!enabled;\n },\n toggleEdit(options, _layerIds = []) {\n if (_layerIds.length === 0) {\n this._layers = this.getLayers();\n }\n this._options = options;\n this._layers.forEach((layer) => {\n if (layer instanceof L.LayerGroup) {\n if (_layerIds.indexOf(layer._leaflet_id) === -1) {\n _layerIds.push(layer._leaflet_id);\n layer.pm.toggleEdit(options, _layerIds);\n }\n } else {\n layer.pm.toggleEdit(options);\n }\n });\n },\n _initLayer(layer) {\n // add reference for the group to each layer inside said group by id, a layer can have multiple groups\n const id = L.Util.stamp(this._layerGroup);\n if (!layer.pm._parentLayerGroup) {\n layer.pm._parentLayerGroup = {};\n }\n layer.pm._parentLayerGroup[id] = this._layerGroup;\n },\n _removeLayerFromGroup(layer) {\n if (layer.pm && layer.pm._layerGroup) {\n const id = L.Util.stamp(this._layerGroup);\n delete layer.pm._layerGroup[id];\n }\n },\n dragging() {\n this._layers = this.getLayers();\n if (this._layers) {\n const dragging = this._layers.find((layer) => layer.pm.dragging());\n return !!dragging;\n }\n return false;\n },\n getOptions() {\n return this.options;\n },\n _getMap() {\n return this._map || this._layers.find((l) => !!l._map)?._map || null;\n },\n getLayers(\n deep = false,\n filterGeoman = true,\n filterGroupsOut = true,\n _layerIds = []\n ) {\n let layers = [];\n if (deep) {\n // get the layers of LayerGroup children\n this._layerGroup.getLayers().forEach((layer) => {\n layers.push(layer);\n if (layer instanceof L.LayerGroup) {\n if (_layerIds.indexOf(layer._leaflet_id) === -1) {\n _layerIds.push(layer._leaflet_id);\n layers = layers.concat(\n layer.pm.getLayers(true, true, true, _layerIds)\n );\n }\n }\n });\n } else {\n // get all layers of the layer group\n layers = this._layerGroup.getLayers();\n }\n\n if (filterGroupsOut) {\n layers = layers.filter((layer) => !(layer instanceof L.LayerGroup));\n }\n if (filterGeoman) {\n // filter out layers that don't have leaflet-geoman\n layers = layers.filter((layer) => !!layer.pm);\n // filter out everything that's leaflet-geoman specific temporary stuff\n layers = layers.filter((layer) => !layer._pmTempLayer);\n // filter out everything that ignore leaflet-geoman\n layers = layers.filter(\n (layer) =>\n (!L.PM.optIn && !layer.options.pmIgnore) || // if optIn is not set / true and pmIgnore is not set / true (default)\n (L.PM.optIn && layer.options.pmIgnore === false) // if optIn is true and pmIgnore is false);\n );\n }\n return layers;\n },\n setOptions(options, _layerIds = []) {\n if (_layerIds.length === 0) {\n this._layers = this.getLayers();\n }\n this.options = options;\n this._layers.forEach((layer) => {\n if (layer.pm) {\n if (layer instanceof L.LayerGroup) {\n if (_layerIds.indexOf(layer._leaflet_id) === -1) {\n _layerIds.push(layer._leaflet_id);\n layer.pm.setOptions(options, _layerIds);\n }\n } else {\n layer.pm.setOptions(options);\n }\n }\n });\n },\n});\n","import Edit from './L.PM.Edit';\n\nEdit.Marker = Edit.extend({\n _shape: 'Marker',\n initialize(layer) {\n // layer is a marker in this case :-)\n this._layer = layer;\n this._enabled = false;\n\n // register dragend event e.g. to fire pm:edit\n this._layer.on('dragend', this._onDragEnd, this);\n },\n // TODO: remove default option in next major Release\n enable(options = { draggable: true }) {\n L.Util.setOptions(this, options);\n\n // layer is not allowed to edit\n if (!this.options.allowEditing || !this._layer._map) {\n this.disable();\n return;\n }\n\n this._map = this._layer._map;\n\n if (this.enabled()) {\n this.disable();\n }\n this.applyOptions();\n\n // if shape gets removed from map, disable edit mode\n this._layer.on('remove', this.disable, this);\n\n this._enabled = true;\n\n this._fireEnable();\n },\n disable() {\n // if it's not enabled, it doesn't need to be disabled\n if (!this.enabled()) {\n return;\n }\n\n // disable dragging, as this could have been active even without being enabled\n this.disableLayerDrag();\n\n // remove listener\n this._layer.off('remove', this.disable, this);\n this._layer.off('contextmenu', this._removeMarker, this);\n\n if (this._layerEdited) {\n this._fireUpdate();\n }\n this._layerEdited = false;\n this._fireDisable();\n\n this._enabled = false;\n },\n enabled() {\n return this._enabled;\n },\n toggleEdit(options) {\n if (!this.enabled()) {\n this.enable(options);\n } else {\n this.disable();\n }\n },\n applyOptions() {\n if (this.options.snappable) {\n this._initSnappableMarkers();\n } else {\n this._disableSnapping();\n }\n\n if (this.options.draggable) {\n this.enableLayerDrag();\n } else {\n this.disableLayerDrag();\n }\n // enable removal for the marker\n if (!this.options.preventMarkerRemoval) {\n this._layer.on('contextmenu', this._removeMarker, this);\n }\n },\n _removeMarker(e) {\n const marker = e.target;\n marker.remove();\n // TODO: find out why this is fired manually, shouldn't it be catched by L.PM.Map 'layerremove'?\n this._fireRemove(marker);\n this._fireRemove(this._map, marker);\n },\n _onDragEnd() {\n this._fireEdit();\n this._layerEdited = true;\n },\n // overwrite initSnappableMarkers from Snapping.js Mixin\n _initSnappableMarkers() {\n const marker = this._layer;\n\n this.options.snapDistance = this.options.snapDistance || 30;\n this.options.snapSegment =\n this.options.snapSegment === undefined ? true : this.options.snapSegment;\n\n marker.off('pm:drag', this._handleSnapping, this);\n marker.on('pm:drag', this._handleSnapping, this);\n\n marker.off('pm:dragend', this._cleanupSnapping, this);\n marker.on('pm:dragend', this._cleanupSnapping, this);\n\n marker.off('pm:dragstart', this._unsnap, this);\n marker.on('pm:dragstart', this._unsnap, this);\n },\n _disableSnapping() {\n const marker = this._layer;\n marker.off('pm:drag', this._handleSnapping, this);\n marker.off('pm:dragend', this._cleanupSnapping, this);\n marker.off('pm:dragstart', this._unsnap, this);\n },\n});\n","import kinks from '@turf/kinks';\nimport lineIntersect from '@turf/line-intersect';\nimport get from 'lodash/get';\nimport Edit from './L.PM.Edit';\nimport { copyLatLngs, hasValues, removeEmptyCoordRings } from '../helpers';\n\nimport MarkerLimits from '../Mixins/MarkerLimits';\n\n// Shit's getting complicated in here with Multipolygon Support. So here's a quick note about it:\n// Multipolygons with holes means lots of nested, multidimensional arrays.\n// In order to find a value inside such an array you need a path to adress it directly.\n// Example: var arr = [[['a', 'b'], ['c']]];\n// The indexPath to 'b' is [0, 0, 1]. The indexPath to 'c' is [0, 1, 0].\n// So I can get 'b' with: arr[0][0][1].\n// Got it? Now you know what is meant when you read \"indexPath\" around here. Have fun 👍\n\nEdit.Line = Edit.extend({\n includes: [MarkerLimits],\n _shape: 'Line',\n initialize(layer) {\n this._layer = layer;\n this._enabled = false;\n },\n enable(options) {\n L.Util.setOptions(this, options);\n\n this._map = this._layer._map;\n\n // cancel when map isn't available, this happens when the polygon is removed before this fires\n if (!this._map) {\n return;\n }\n\n // layer is not allowed to edit\n if (!this.options.allowEditing) {\n this.disable();\n return;\n }\n\n if (this.enabled()) {\n // if it was already enabled, disable first\n // we don't block enabling again because new options might be passed\n this.disable();\n }\n\n // change state\n this._enabled = true;\n\n // init markers\n this._initMarkers();\n\n this.applyOptions();\n\n // if shape gets removed from map, disable edit mode\n this._layer.on('remove', this.disable, this);\n\n if (!this.options.allowSelfIntersection) {\n this._layer.on(\n 'pm:vertexremoved',\n this._handleSelfIntersectionOnVertexRemoval,\n this\n );\n }\n\n if (!this.options.allowSelfIntersection) {\n if (this._layer.options.color !== '#f00000ff') {\n this.cachedColor = this._layer.options.color;\n this.isRed = false;\n } else {\n this.isRed = true;\n }\n this._handleLayerStyle();\n } else {\n this.cachedColor = undefined;\n }\n this._fireEnable();\n },\n disable() {\n // if it's not enabled, it doesn't need to be disabled\n if (!this.enabled()) {\n return;\n }\n\n // prevent disabling if polygon is being dragged\n if (this._dragging) {\n return;\n }\n this._enabled = false;\n this._markerGroup.clearLayers();\n this._markerGroup.removeFrom(this._map);\n\n // remove listener\n this._layer.off('remove', this.disable, this);\n\n if (!this.options.allowSelfIntersection) {\n this._layer.off(\n 'pm:vertexremoved',\n this._handleSelfIntersectionOnVertexRemoval,\n this\n );\n }\n\n // remove draggable class\n const el = this._layer._path\n ? this._layer._path\n : this._layer._renderer._container;\n L.DomUtil.removeClass(el, 'leaflet-pm-draggable');\n\n if (this._layerEdited) {\n this._fireUpdate();\n }\n this._layerEdited = false;\n this._fireDisable();\n },\n enabled() {\n return this._enabled;\n },\n toggleEdit(options) {\n if (!this.enabled()) {\n this.enable(options);\n } else {\n this.disable();\n }\n return this.enabled();\n },\n applyOptions() {\n if (this.options.snappable) {\n this._initSnappableMarkers();\n } else {\n this._disableSnapping();\n }\n },\n _initMarkers() {\n const map = this._map;\n const coords = this._layer.getLatLngs();\n\n // cleanup old ones first\n if (this._markerGroup) {\n this._markerGroup.clearLayers();\n }\n\n // add markerGroup to map, markerGroup includes regular and middle markers\n this._markerGroup = new L.FeatureGroup();\n this._markerGroup._pmTempLayer = true;\n\n // handle coord-rings (outer, inner, etc)\n const handleRing = (coordsArr) => {\n // if there is another coords ring, go a level deep and do this again\n if (Array.isArray(coordsArr[0])) {\n return coordsArr.map(handleRing, this);\n }\n\n // the marker array, it includes only the markers of vertexes (no middle markers)\n const ringArr = coordsArr.map(this._createMarker, this);\n\n if (this.options.hideMiddleMarkers !== true) {\n // create small markers in the middle of the regular markers\n coordsArr.map((v, k) => {\n // find the next index fist\n const nextIndex = this.isPolygon()\n ? (k + 1) % coordsArr.length\n : k + 1;\n // create the marker\n return this._createMiddleMarker(ringArr[k], ringArr[nextIndex]);\n });\n }\n\n return ringArr;\n };\n\n // create markers\n this._markers = handleRing(coords);\n\n // handle possible limitation: maximum number of markers\n this.filterMarkerGroup();\n\n // add markerGroup to map\n map.addLayer(this._markerGroup);\n },\n\n // creates initial markers for coordinates\n _createMarker(latlng) {\n const marker = new L.Marker(latlng, {\n draggable: true,\n icon: L.divIcon({ className: 'marker-icon' }),\n });\n this._setPane(marker, 'vertexPane');\n\n marker._pmTempLayer = true;\n\n if (this.options.rotate) {\n marker.on('dragstart', this._onRotateStart, this);\n marker.on('drag', this._onRotate, this);\n marker.on('dragend', this._onRotateEnd, this);\n } else {\n marker.on('click', this._onVertexClick, this);\n marker.on('dragstart', this._onMarkerDragStart, this);\n marker.on('move', this._onMarkerDrag, this);\n marker.on('dragend', this._onMarkerDragEnd, this);\n\n if (!this.options.preventMarkerRemoval) {\n marker.on(this.options.removeVertexOn, this._removeMarker, this);\n }\n }\n\n this._markerGroup.addLayer(marker);\n\n return marker;\n },\n\n // creates the middle markes between coordinates\n _createMiddleMarker(leftM, rightM) {\n // cancel if there are no two markers\n if (!leftM || !rightM) {\n return false;\n }\n\n const latlng = L.PM.Utils.calcMiddleLatLng(\n this._map,\n leftM.getLatLng(),\n rightM.getLatLng()\n );\n\n const middleMarker = this._createMarker(latlng);\n const middleIcon = L.divIcon({\n className: 'marker-icon marker-icon-middle',\n });\n middleMarker.setIcon(middleIcon);\n middleMarker.leftM = leftM;\n middleMarker.rightM = rightM;\n\n // save reference to this middle markers on the neighboor regular markers\n leftM._middleMarkerNext = middleMarker;\n rightM._middleMarkerPrev = middleMarker;\n\n middleMarker.on(this.options.addVertexOn, this._onMiddleMarkerClick, this);\n middleMarker.on('movestart', this._onMiddleMarkerMoveStart, this);\n\n return middleMarker;\n },\n _onMiddleMarkerClick(e) {\n const middleMarker = e.target;\n\n if (!this._vertexValidation('add', e)) {\n return;\n }\n // TODO: move the next two lines inside _addMarker() as soon as\n // https://github.com/Leaflet/Leaflet/issues/4484\n // is fixed\n const icon = L.divIcon({ className: 'marker-icon' });\n middleMarker.setIcon(icon);\n this._addMarker(middleMarker, middleMarker.leftM, middleMarker.rightM);\n },\n _onMiddleMarkerMoveStart(e) {\n const middleMarker = e.target;\n middleMarker.on('moveend', this._onMiddleMarkerMoveEnd, this);\n if (!this._vertexValidation('add', e)) {\n middleMarker.on('move', this._onMiddleMarkerMovePrevent, this);\n return;\n }\n\n middleMarker._dragging = true;\n // TODO: This is a workaround. Remove the moveend listener and\n // callback as soon as this is fixed:\n // https://github.com/Leaflet/Leaflet/issues/4484\n this._addMarker(middleMarker, middleMarker.leftM, middleMarker.rightM);\n },\n _onMiddleMarkerMovePrevent(e) {\n const middleMarker = e.target;\n this._vertexValidationDrag(middleMarker);\n },\n _onMiddleMarkerMoveEnd(e) {\n const middleMarker = e.target;\n middleMarker.off('move', this._onMiddleMarkerMovePrevent, this);\n middleMarker.off('moveend', this._onMiddleMarkerMoveEnd, this);\n if (!this._vertexValidationDragEnd(middleMarker)) {\n return;\n }\n const icon = L.divIcon({ className: 'marker-icon' });\n middleMarker.setIcon(icon);\n // timeout is needed else this._onVertexClick fires the event because it is called after deleting the flag\n setTimeout(() => {\n delete middleMarker._dragging;\n }, 100);\n },\n // adds a new marker from a middlemarker\n _addMarker(newM, leftM, rightM) {\n // first, make this middlemarker a regular marker\n newM.off('movestart', this._onMiddleMarkerMoveStart, this);\n newM.off(this.options.addVertexOn, this._onMiddleMarkerClick, this);\n // now, create the polygon coordinate point for that marker\n // and push into marker array\n // and associate polygon coordinate with marker coordinate\n const latlng = newM.getLatLng();\n const coords = this._layer._latlngs;\n\n // remove linked markers\n delete newM.leftM;\n delete newM.rightM;\n\n // the index path to the marker inside the multidimensional marker array\n const { indexPath, index, parentPath } = L.PM.Utils.findDeepMarkerIndex(\n this._markers,\n leftM\n );\n\n // define the coordsRing that is edited\n const coordsRing = indexPath.length > 1 ? get(coords, parentPath) : coords;\n\n // define the markers array that is edited\n const markerArr =\n indexPath.length > 1 ? get(this._markers, parentPath) : this._markers;\n\n // add coordinate to coordinate array\n coordsRing.splice(index + 1, 0, latlng);\n\n // add marker to marker array\n markerArr.splice(index + 1, 0, newM);\n\n // set new latlngs to update polygon\n this._layer.setLatLngs(coords);\n\n // create the new middlemarkers\n if (this.options.hideMiddleMarkers !== true) {\n this._createMiddleMarker(leftM, newM);\n this._createMiddleMarker(newM, rightM);\n }\n\n // fire edit event\n this._fireEdit();\n this._layerEdited = true;\n this._fireChange(this._layer.getLatLngs(), 'Edit');\n\n this._fireVertexAdded(\n newM,\n L.PM.Utils.findDeepMarkerIndex(this._markers, newM).indexPath,\n latlng\n );\n\n if (this.options.snappable) {\n this._initSnappableMarkers();\n }\n },\n\n hasSelfIntersection() {\n // check for self intersection of the layer and return true/false\n const selfIntersection = kinks(this._layer.toGeoJSON(15));\n return selfIntersection.features.length > 0;\n },\n\n _handleSelfIntersectionOnVertexRemoval() {\n // check for selfintersection again (mainly to reset the style)\n const selfIntersection = this._handleLayerStyle(true);\n\n if (selfIntersection) {\n // reset coordinates\n this._layer.setLatLngs(this._coordsBeforeEdit);\n this._coordsBeforeEdit = null;\n\n // re-enable markers for the new coords\n this._initMarkers();\n }\n },\n\n _handleLayerStyle(flash) {\n const layer = this._layer;\n\n let selfIntersection;\n let intersection;\n if (this.options.allowSelfIntersection) {\n selfIntersection = false;\n } else {\n intersection = kinks(this._layer.toGeoJSON(15));\n selfIntersection = intersection.features.length > 0;\n }\n\n if (selfIntersection) {\n if (\n !this.options.allowSelfIntersection &&\n this.options.allowSelfIntersectionEdit\n ) {\n this._updateDisabledMarkerStyle(this._markers, true);\n }\n\n if (this.isRed) {\n return selfIntersection;\n }\n\n // if it does self-intersect, mark or flash it red\n if (flash) {\n this._flashLayer();\n } else {\n layer.setStyle({ color: '#f00000ff' });\n this.isRed = true;\n }\n\n // fire intersect event\n this._fireIntersect(intersection);\n } else {\n // if not, reset the style to the default color\n layer.setStyle({ color: this.cachedColor });\n this.isRed = false;\n if (\n !this.options.allowSelfIntersection &&\n this.options.allowSelfIntersectionEdit\n ) {\n this._updateDisabledMarkerStyle(this._markers, false);\n }\n }\n return selfIntersection;\n },\n _flashLayer() {\n if (!this.cachedColor) {\n this.cachedColor = this._layer.options.color;\n }\n\n this._layer.setStyle({ color: '#f00000ff' });\n this.isRed = true;\n\n window.setTimeout(() => {\n this._layer.setStyle({ color: this.cachedColor });\n this.isRed = false;\n }, 200);\n },\n _updateDisabledMarkerStyle(markers, disabled) {\n markers.forEach((marker) => {\n if (Array.isArray(marker)) {\n this._updateDisabledMarkerStyle(marker, disabled);\n } else if (marker._icon) {\n if (disabled && !this._checkMarkerAllowedToDrag(marker)) {\n L.DomUtil.addClass(marker._icon, 'vertexmarker-disabled');\n } else {\n L.DomUtil.removeClass(marker._icon, 'vertexmarker-disabled');\n }\n }\n });\n },\n _removeMarker(e) {\n // the marker that should be removed\n const marker = e.target;\n\n if (!this._vertexValidation('remove', e)) {\n return;\n }\n\n // if self intersection isn't allowed, save the coords upon dragstart\n // in case we need to reset the layer\n if (!this.options.allowSelfIntersection) {\n this._coordsBeforeEdit = copyLatLngs(\n this._layer,\n this._layer.getLatLngs()\n );\n }\n\n // coords of the layer\n let coords = this._layer.getLatLngs();\n\n // the index path to the marker inside the multidimensional marker array\n const { indexPath, index, parentPath } = L.PM.Utils.findDeepMarkerIndex(\n this._markers,\n marker\n );\n\n // only continue if this is NOT a middle marker (those can't be deleted)\n if (!indexPath) {\n return;\n }\n\n // define the coordsRing that is edited\n const coordsRing = indexPath.length > 1 ? get(coords, parentPath) : coords;\n\n // define the markers array that is edited\n let markerArr =\n indexPath.length > 1 ? get(this._markers, parentPath) : this._markers;\n\n // prevent removal of the layer if the vertex count is below minimum\n if (!this.options.removeLayerBelowMinVertexCount) {\n // if on a line only 2 vertices left or on a polygon 3 vertices left, don't allow to delete\n if (\n coordsRing.length <= 2 ||\n (this.isPolygon() && coordsRing.length <= 3)\n ) {\n this._flashLayer();\n return;\n }\n }\n\n // remove coordinate\n coordsRing.splice(index, 1);\n\n // set new latlngs to the polygon\n this._layer.setLatLngs(coords);\n\n // if a polygon has less than 3 vertices, remove all of them. We will remove only one here, the if-clause after that will handle the rest\n if (this.isPolygon() && coordsRing.length <= 2) {\n coordsRing.splice(0, coordsRing.length);\n }\n\n let layerRemoved = false;\n // if the ring of the line has no coordinates left, remove the last coord too\n if (coordsRing.length <= 1) {\n coordsRing.splice(0, coordsRing.length);\n\n // Clean up MultiPolygon\n if (parentPath.length > 1 && indexPath.length > 1) {\n coords = removeEmptyCoordRings(coords);\n }\n\n // set new coords\n this._layer.setLatLngs(coords);\n\n // re-enable editing so unnecessary markers are removed\n this._initMarkers();\n layerRemoved = true;\n }\n\n // if no coords are left, remove the layer\n if (!hasValues(coords)) {\n this._layer.remove();\n }\n\n // remove all empty coord-rings\n coords = removeEmptyCoordRings(coords);\n this._layer.setLatLngs(coords);\n // remove empty marker arrays\n this._markers = removeEmptyCoordRings(this._markers);\n\n // No need to calculate the middle marker when the layer was removed\n if (!layerRemoved) {\n // get new markerArr because we cleaned up coords and markers array\n markerArr =\n indexPath.length > 1 ? get(this._markers, parentPath) : this._markers;\n\n // now handle the middle markers\n // remove the marker and the middlemarkers next to it from the map\n if (marker._middleMarkerPrev) {\n this._markerGroup.removeLayer(marker._middleMarkerPrev);\n this._removeFromCache(marker._middleMarkerPrev);\n }\n if (marker._middleMarkerNext) {\n this._markerGroup.removeLayer(marker._middleMarkerNext);\n this._removeFromCache(marker._middleMarkerNext);\n }\n\n // remove the marker from the map\n this._markerGroup.removeLayer(marker);\n this._removeFromCache(marker);\n\n if (markerArr) {\n let rightMarkerIndex;\n let leftMarkerIndex;\n\n if (this.isPolygon()) {\n // find neighbor marker-indexes\n rightMarkerIndex = (index + 1) % markerArr.length;\n leftMarkerIndex = (index + (markerArr.length - 1)) % markerArr.length;\n } else {\n // find neighbor marker-indexes\n leftMarkerIndex = index - 1 < 0 ? undefined : index - 1;\n rightMarkerIndex =\n index + 1 >= markerArr.length ? undefined : index + 1;\n }\n\n // don't create middlemarkers if there is only one marker left\n if (rightMarkerIndex !== leftMarkerIndex) {\n const leftM = markerArr[leftMarkerIndex];\n const rightM = markerArr[rightMarkerIndex];\n if (this.options.hideMiddleMarkers !== true) {\n this._createMiddleMarker(leftM, rightM);\n }\n }\n\n // remove the marker from the markers array\n markerArr.splice(index, 1);\n }\n }\n\n // fire edit event\n this._fireEdit();\n this._layerEdited = true;\n\n // fire vertex removal event\n // TODO: maybe fire latlng as well?\n this._fireVertexRemoved(marker, indexPath);\n this._fireChange(this._layer.getLatLngs(), 'Edit');\n },\n updatePolygonCoordsFromMarkerDrag(marker) {\n // update polygon coords\n const coords = this._layer.getLatLngs();\n\n // get marker latlng\n const latlng = marker.getLatLng();\n\n // get indexPath of Marker\n const { indexPath, index, parentPath } = L.PM.Utils.findDeepMarkerIndex(\n this._markers,\n marker\n );\n\n // update coord\n const parent = indexPath.length > 1 ? get(coords, parentPath) : coords;\n parent.splice(index, 1, latlng);\n\n // set new coords on layer\n this._layer.setLatLngs(coords);\n },\n\n _getNeighborMarkers(marker) {\n const { indexPath, index, parentPath } = L.PM.Utils.findDeepMarkerIndex(\n this._markers,\n marker\n );\n\n // the markers neighbors\n const markerArr =\n indexPath.length > 1 ? get(this._markers, parentPath) : this._markers;\n\n // find the indizes of next and previous markers\n const nextMarkerIndex = (index + 1) % markerArr.length;\n const prevMarkerIndex = (index + (markerArr.length - 1)) % markerArr.length;\n\n // get prev and next marker\n const prevMarker = markerArr[prevMarkerIndex];\n const nextMarker = markerArr[nextMarkerIndex];\n\n return { prevMarker, nextMarker };\n },\n _checkMarkerAllowedToDrag(marker) {\n const { prevMarker, nextMarker } = this._getNeighborMarkers(marker);\n\n const prevLine = L.polyline([prevMarker.getLatLng(), marker.getLatLng()]);\n const nextLine = L.polyline([marker.getLatLng(), nextMarker.getLatLng()]);\n\n let prevLineIntersectionLen = lineIntersect(\n this._layer.toGeoJSON(15),\n prevLine.toGeoJSON(15)\n ).features.length;\n let nextLineIntersectionLen = lineIntersect(\n this._layer.toGeoJSON(15),\n nextLine.toGeoJSON(15)\n ).features.length;\n\n // The first and last line has one intersection fewer because they are not connected\n if (marker.getLatLng() === this._markers[0][0].getLatLng()) {\n nextLineIntersectionLen += 1;\n } else if (\n marker.getLatLng() ===\n this._markers[0][this._markers[0].length - 1].getLatLng()\n ) {\n prevLineIntersectionLen += 1;\n }\n\n // <= 2 the start and end point of the line always intersecting because they have the same coords.\n if (prevLineIntersectionLen <= 2 && nextLineIntersectionLen <= 2) {\n return false;\n }\n return true;\n },\n _onMarkerDragStart(e) {\n const marker = e.target;\n\n // When intersection is true while calling enable(), the cachedColor is already set\n if (!this.cachedColor) {\n this.cachedColor = this._layer.options.color;\n }\n\n if (!this._vertexValidation('move', e)) {\n return;\n }\n\n const { indexPath } = L.PM.Utils.findDeepMarkerIndex(this._markers, marker);\n\n this._fireMarkerDragStart(e, indexPath);\n\n // if self intersection isn't allowed, save the coords upon dragstart\n // in case we need to reset the layer\n if (!this.options.allowSelfIntersection) {\n this._coordsBeforeEdit = copyLatLngs(\n this._layer,\n this._layer.getLatLngs()\n );\n }\n\n if (\n !this.options.allowSelfIntersection &&\n this.options.allowSelfIntersectionEdit &&\n this.hasSelfIntersection()\n ) {\n this._markerAllowedToDrag = this._checkMarkerAllowedToDrag(marker);\n } else {\n this._markerAllowedToDrag = null;\n }\n },\n _onMarkerDrag(e) {\n // dragged marker\n const marker = e.target;\n\n if (!this._vertexValidationDrag(marker)) {\n return;\n }\n\n const { indexPath, index, parentPath } = L.PM.Utils.findDeepMarkerIndex(\n this._markers,\n marker\n );\n\n // only continue if this is NOT a middle marker\n if (!indexPath) {\n return;\n }\n\n if (\n !this.options.allowSelfIntersection &&\n this.options.allowSelfIntersectionEdit &&\n this.hasSelfIntersection() &&\n this._markerAllowedToDrag === false\n ) {\n this._layer.setLatLngs(this._coordsBeforeEdit);\n // re-enable markers for the new coords\n this._initMarkers();\n // check for selfintersection again (mainly to reset the style)\n this._handleLayerStyle();\n return;\n }\n\n this.updatePolygonCoordsFromMarkerDrag(marker);\n\n // the dragged markers neighbors\n const markerArr =\n indexPath.length > 1 ? get(this._markers, parentPath) : this._markers;\n\n // find the indizes of next and previous markers\n const nextMarkerIndex = (index + 1) % markerArr.length;\n const prevMarkerIndex = (index + (markerArr.length - 1)) % markerArr.length;\n\n // update middle markers on the left and right\n // be aware that \"next\" and \"prev\" might be interchanged, depending on the geojson array\n const markerLatLng = marker.getLatLng();\n\n // get latlng of prev and next marker\n const prevMarkerLatLng = markerArr[prevMarkerIndex].getLatLng();\n const nextMarkerLatLng = markerArr[nextMarkerIndex].getLatLng();\n\n if (marker._middleMarkerNext) {\n const middleMarkerNextLatLng = L.PM.Utils.calcMiddleLatLng(\n this._map,\n markerLatLng,\n nextMarkerLatLng\n );\n marker._middleMarkerNext.setLatLng(middleMarkerNextLatLng);\n }\n\n if (marker._middleMarkerPrev) {\n const middleMarkerPrevLatLng = L.PM.Utils.calcMiddleLatLng(\n this._map,\n markerLatLng,\n prevMarkerLatLng\n );\n marker._middleMarkerPrev.setLatLng(middleMarkerPrevLatLng);\n }\n\n // if self intersection is not allowed, handle it\n if (!this.options.allowSelfIntersection) {\n this._handleLayerStyle();\n }\n this._fireMarkerDrag(e, indexPath);\n this._fireChange(this._layer.getLatLngs(), 'Edit');\n },\n _onMarkerDragEnd(e) {\n const marker = e.target;\n\n if (!this._vertexValidationDragEnd(marker)) {\n return;\n }\n\n const { indexPath } = L.PM.Utils.findDeepMarkerIndex(this._markers, marker);\n\n // if self intersection is not allowed but this edit caused a self intersection,\n // reset and cancel; do not fire events\n let intersection = this.hasSelfIntersection();\n if (\n intersection &&\n this.options.allowSelfIntersectionEdit &&\n this._markerAllowedToDrag\n ) {\n intersection = false;\n }\n\n const intersectionReset =\n !this.options.allowSelfIntersection && intersection;\n\n this._fireMarkerDragEnd(e, indexPath, intersectionReset);\n\n if (intersectionReset) {\n // reset coordinates\n this._layer.setLatLngs(this._coordsBeforeEdit);\n this._coordsBeforeEdit = null;\n\n // re-enable markers for the new coords\n this._initMarkers();\n\n if (this.options.snappable) {\n this._initSnappableMarkers();\n }\n\n // check for selfintersection again (mainly to reset the style)\n this._handleLayerStyle();\n\n this._fireLayerReset(e, indexPath);\n return;\n }\n if (\n !this.options.allowSelfIntersection &&\n this.options.allowSelfIntersectionEdit\n ) {\n this._handleLayerStyle();\n }\n // fire edit event\n this._fireEdit();\n this._layerEdited = true;\n this._fireChange(this._layer.getLatLngs(), 'Edit');\n },\n _onVertexClick(e) {\n const vertex = e.target;\n if (vertex._dragging) {\n return;\n }\n\n const { indexPath } = L.PM.Utils.findDeepMarkerIndex(this._markers, vertex);\n\n this._fireVertexClick(e, indexPath);\n },\n});\n","const MarkerLimits = {\n filterMarkerGroup() {\n // define cache of markers\n this.markerCache = [];\n this.createCache();\n\n // refresh cache when layer was edited (e.g. when a vertex was added or removed)\n this._layer.on('pm:edit', this.createCache, this);\n\n // apply filter for the first time\n this.applyLimitFilters({});\n\n if (!this.throttledApplyLimitFilters) {\n this.throttledApplyLimitFilters = L.Util.throttle(\n this.applyLimitFilters,\n 100,\n this\n );\n }\n\n // remove events when edit mode is disabled\n this._layer.on('pm:disable', this._removeMarkerLimitEvents, this);\n this._layer.on('remove', this._removeMarkerLimitEvents, this);\n\n // add markers closest to the mouse\n if (this.options.limitMarkersToCount > -1) {\n // re-init markers when a vertex is removed.\n // The reason is that syncing this cache with a removed marker was impossible to do\n this._layer.on('pm:vertexremoved', this._initMarkers, this);\n\n this._map.on('mousemove', this.throttledApplyLimitFilters, this);\n }\n },\n _removeMarkerLimitEvents() {\n this._map.off('mousemove', this.throttledApplyLimitFilters, this);\n this._layer.off('pm:edit', this.createCache, this);\n this._layer.off('pm:disable', this._removeMarkerLimitEvents, this);\n this._layer.off('pm:vertexremoved', this._initMarkers, this);\n },\n createCache() {\n const allMarkers = [...this._markerGroup.getLayers(), ...this.markerCache];\n this.markerCache = allMarkers.filter((v, i, s) => s.indexOf(v) === i);\n },\n _removeFromCache(marker) {\n const markerCacheIndex = this.markerCache.indexOf(marker);\n if (markerCacheIndex > -1) {\n this.markerCache.splice(markerCacheIndex, 1);\n }\n },\n renderLimits(markers) {\n this.markerCache.forEach((l) => {\n if (markers.includes(l)) {\n this._markerGroup.addLayer(l);\n } else {\n this._markerGroup.removeLayer(l);\n }\n });\n },\n applyLimitFilters({ latlng = { lat: 0, lng: 0 } }) {\n if (this._preventRenderMarkers) {\n return;\n }\n // find markers near the cursor\n const makersNearCursor = this._filterClosestMarkers(latlng);\n\n // all markers that we want to show\n const markersToAdd = [...makersNearCursor];\n\n this.renderLimits(markersToAdd);\n },\n _filterClosestMarkers(latlng) {\n const markers = [...this.markerCache];\n const limit = this.options.limitMarkersToCount;\n\n if (limit === -1) {\n return markers;\n }\n\n // sort markers by distance to cursor\n markers.sort((l, t) => {\n const distanceA = l._latlng.distanceTo(latlng);\n const distanceB = t._latlng.distanceTo(latlng);\n\n return distanceA - distanceB;\n });\n\n // reduce markers to number of limit\n const closest = markers.filter((l, i) => (limit > -1 ? i < limit : true));\n\n return closest;\n },\n _preventRenderMarkers: false,\n _preventRenderingMarkers(value) {\n this._preventRenderMarkers = !!value;\n },\n};\n\nexport default MarkerLimits;\n","import lineIntersect from '@turf/line-intersect';\nimport Edit from './L.PM.Edit';\n\nEdit.Polygon = Edit.Line.extend({\n _shape: 'Polygon',\n _checkMarkerAllowedToDrag(marker) {\n const { prevMarker, nextMarker } = this._getNeighborMarkers(marker);\n\n const prevLine = L.polyline([prevMarker.getLatLng(), marker.getLatLng()]);\n const nextLine = L.polyline([marker.getLatLng(), nextMarker.getLatLng()]);\n\n const prevLineIntersectionLen = lineIntersect(\n this._layer.toGeoJSON(15),\n prevLine.toGeoJSON(15)\n ).features.length;\n const nextLineIntersectionLen = lineIntersect(\n this._layer.toGeoJSON(15),\n nextLine.toGeoJSON(15)\n ).features.length;\n\n // <= 2 the start and end point of the line always intersecting because they have the same coords.\n if (prevLineIntersectionLen <= 2 && nextLineIntersectionLen <= 2) {\n return false;\n }\n return true;\n },\n});\n","// Corner detection based on Leaflet Draw's Edit.Rectangle.js Class:\n// https://github.com/Leaflet/Leaflet.draw/blob/master/src/edit/handler/Edit.Rectangle.js\nimport Edit from './L.PM.Edit';\nimport { calcAngle } from '../helpers';\n\nEdit.Rectangle = Edit.Polygon.extend({\n _shape: 'Rectangle',\n // initializes Rectangle Markers\n _initMarkers() {\n const map = this._map;\n const corners = this._findCorners();\n\n // cleanup old ones first\n if (this._markerGroup) {\n this._markerGroup.clearLayers();\n }\n\n // add markerGroup to map, markerGroup includes regular and middle markers\n this._markerGroup = new L.FeatureGroup();\n this._markerGroup._pmTempLayer = true;\n map.addLayer(this._markerGroup);\n\n // create markers for four corners of rectangle\n this._markers = [];\n\n // nest set of corner markers in a 2D array so that we can Cut this Rectangle, if needed\n this._markers[0] = corners.map(this._createMarker, this);\n\n // convenience alias, for better readability\n [this._cornerMarkers] = this._markers;\n\n // Update the marker latlngs if the rectangle is rotated\n this._layer.getLatLngs()[0].forEach((latlng, index) => {\n const marker = this._cornerMarkers.find((m) => m._index === index);\n if (marker) {\n marker.setLatLng(latlng);\n }\n });\n },\n applyOptions() {\n if (this.options.snappable) {\n this._initSnappableMarkers();\n } else {\n this._disableSnapping();\n }\n this._addMarkerEvents();\n },\n\n // creates initial markers for coordinates\n _createMarker(latlng, index) {\n const marker = new L.Marker(latlng, {\n draggable: true,\n icon: L.divIcon({ className: 'marker-icon' }),\n });\n this._setPane(marker, 'vertexPane');\n\n marker._origLatLng = latlng;\n marker._index = index;\n marker._pmTempLayer = true;\n\n marker.on('click', this._onVertexClick, this);\n\n this._markerGroup.addLayer(marker);\n\n return marker;\n },\n // Add marker events after adding the snapping events to the markers, beacause of the execution order\n _addMarkerEvents() {\n this._markers[0].forEach((marker) => {\n marker.on('dragstart', this._onMarkerDragStart, this);\n marker.on('drag', this._onMarkerDrag, this);\n marker.on('dragend', this._onMarkerDragEnd, this);\n\n // TODO: Can we remove this? The _removeMarker Event is a empty function\n if (!this.options.preventMarkerRemoval) {\n marker.on('contextmenu', this._removeMarker, this);\n }\n });\n },\n // Empty callback for 'contextmenu' binding set in L.PM.Edit.Line.js's _createMarker method (AKA, right-click on marker event)\n // (A Rectangle is designed to always remain a \"true\" rectangle -- if you want it editable, use Polygon Tool instead!!!)\n _removeMarker() {\n // The method, it does nothing!!!\n return null;\n },\n\n _onMarkerDragStart(e) {\n if (!this._vertexValidation('move', e)) {\n return;\n }\n\n // dragged marker\n const draggedMarker = e.target;\n // Store/update a reference to marker in opposite corner\n const corners = this._cornerMarkers;\n draggedMarker._oppositeCornerLatLng = corners\n .find((m) => m._index === (draggedMarker._index + 2) % 4)\n .getLatLng();\n\n // Automatically unsnap all markers on drag start (they'll snap back if close enough to another snappable object)\n // (Without this, it's occasionally possible for a marker to get stuck as 'snapped,' which prevents Rectangle resizing)\n draggedMarker._snapped = false;\n\n const { indexPath } = L.PM.Utils.findDeepMarkerIndex(\n this._markers,\n draggedMarker\n );\n\n this._fireMarkerDragStart(e, indexPath);\n },\n\n _onMarkerDrag(e) {\n // dragged marker\n const draggedMarker = e.target;\n\n if (!this._vertexValidationDrag(draggedMarker)) {\n return;\n }\n\n // only continue if this is NOT a middle marker (should NEVER be one, but this is just a safety check)\n if (draggedMarker._index === undefined) {\n return;\n }\n\n this._adjustRectangleForMarkerMove(draggedMarker);\n\n const { indexPath } = L.PM.Utils.findDeepMarkerIndex(\n this._markers,\n draggedMarker\n );\n this._fireMarkerDrag(e, indexPath);\n this._fireChange(this._layer.getLatLngs(), 'Edit');\n },\n\n _onMarkerDragEnd(e) {\n // dragged marker\n const draggedMarker = e.target;\n if (!this._vertexValidationDragEnd(draggedMarker)) {\n return;\n }\n\n // Clean-up data attributes\n this._cornerMarkers.forEach((m) => {\n delete m._oppositeCornerLatLng;\n });\n\n const { indexPath } = L.PM.Utils.findDeepMarkerIndex(\n this._markers,\n draggedMarker\n );\n this._fireMarkerDragEnd(e, indexPath);\n\n // fire edit event\n this._fireEdit();\n this._layerEdited = true;\n this._fireChange(this._layer.getLatLngs(), 'Edit');\n },\n\n // adjusts the rectangle's size and bounds whenever a marker is moved\n // params: movedMarker -- the Marker object\n _adjustRectangleForMarkerMove(movedMarker) {\n // update moved marker coordinates\n L.extend(movedMarker._origLatLng, movedMarker._latlng);\n\n // update rectangle boundaries, based on moved marker's new LatLng and cached opposite corner's LatLng\n const corners = L.PM.Utils._getRotatedRectangle(\n movedMarker.getLatLng(),\n movedMarker._oppositeCornerLatLng,\n this.getAngle(),\n this._map\n );\n this._layer.setLatLngs(corners);\n\n // Reposition the markers at each corner\n this._adjustAllMarkers();\n\n // Redraw the shape (to update altered rectangle)\n this._layer.redraw();\n },\n\n // adjusts the position of all Markers\n // params: markerLatLngs -- an array of exactly LatLng objects\n _adjustAllMarkers() {\n const markerLatLngs = this._layer.getLatLngs()[0];\n\n if (\n markerLatLngs &&\n markerLatLngs.length !== 4 &&\n markerLatLngs.length > 0\n ) {\n // The layers is currently to small and has not enough latlngs.\n // Leaflet destroys the valid Rectangle by removing the last latlng if the last and first latlng are equal. See: Leaflet#7464 V1.7.1\n\n // update all possible markers\n markerLatLngs.forEach((latlng, index) => {\n this._cornerMarkers[index].setLatLng(latlng);\n });\n\n // apply to all markers with no latlng on the layer, the first latlng\n const restMarkers = this._cornerMarkers.slice(markerLatLngs.length);\n restMarkers.forEach((marker) => {\n marker.setLatLng(markerLatLngs[0]);\n });\n } else if (!markerLatLngs || !markerLatLngs.length) {\n // eslint-disable-next-line\n console.error('The layer has no LatLngs');\n } else {\n this._cornerMarkers.forEach((marker) => {\n marker.setLatLng(markerLatLngs[marker._index]);\n });\n }\n },\n // finds the 4 corners of the current bounding box\n // returns array of 4 LatLng objects in this order: Northwest corner, Northeast corner, Southeast corner, Southwest corner\n _findCorners() {\n if (this._angle === undefined) {\n this.setInitAngle(\n calcAngle(\n this._map,\n this._layer.getLatLngs()[0][0],\n this._layer.getLatLngs()[0][1]\n ) || 0\n );\n }\n\n const latlngs = this._layer.getLatLngs()[0];\n return L.PM.Utils._getRotatedRectangle(\n latlngs[0],\n latlngs[2],\n this.getAngle(),\n this._map || this\n );\n },\n});\n","import Edit from './L.PM.Edit';\nimport { destinationOnLine } from '../helpers';\n\nEdit.CircleMarker = Edit.extend({\n _shape: 'CircleMarker',\n initialize(layer) {\n this._layer = layer;\n this._enabled = false;\n\n this._minRadiusOption = 'minRadiusCircleMarker';\n this._maxRadiusOption = 'maxRadiusCircleMarker';\n this._editableOption = 'resizeableCircleMarker';\n\n // create polygon around the circle border\n this._updateHiddenPolyCircle();\n },\n // TODO: remove default option in next major Release\n enable(options = { draggable: true, snappable: true }) {\n L.Util.setOptions(this, options);\n // TODO: remove with next major release\n if (this.options.editable) {\n this.options.resizeableCircleMarker = this.options.editable;\n delete this.options.editable;\n }\n\n // layer is not allowed to edit\n // cancel when map isn't available, this happens when it is removed before this fires\n if (!this.options.allowEditing || !this._layer._map) {\n this.disable();\n return;\n }\n\n this._map = this._layer._map;\n\n if (this.enabled()) {\n // if it was already enabled, disable first\n // we don't block enabling again because new options might be passed\n this.disable();\n }\n this.applyOptions();\n\n // if shape gets removed from map, disable edit mode\n this._layer.on('remove', this.disable, this);\n\n // change state\n this._enabled = true;\n\n this._extendingEnable();\n\n // create polygon around the circle border\n this._updateHiddenPolyCircle();\n\n this._fireEnable();\n },\n _extendingEnable() {\n // if CircleMarker is dragged while draw mode\n this._layer.on('pm:dragstart', this._onDragStart, this);\n this._layer.on('pm:drag', this._onMarkerDrag, this);\n this._layer.on('pm:dragend', this._onMarkerDragEnd, this);\n },\n disable() {\n // prevent disabling if layer is being dragged\n if (this.dragging()) {\n return;\n }\n\n // Add map if it is not already set. This happens when disable() is called before enable()\n if (!this._map) {\n this._map = this._layer._map;\n }\n\n if (!this._map) {\n return;\n }\n\n // if it's not enabled, it doesn't need to be disabled\n if (!this.enabled()) {\n return;\n }\n\n // disable dragging of non-editable circle\n if (this.layerDragEnabled()) {\n this.disableLayerDrag();\n }\n\n if (this.options[this._editableOption]) {\n if (this._helperLayers) {\n this._helperLayers.clearLayers();\n }\n this._map.off('move', this._syncMarkers, this);\n this._outerMarker.off('drag', this._handleOuterMarkerSnapping, this);\n } else {\n this._map.off('move', this._updateHiddenPolyCircle, this);\n }\n\n this._extendingDisable();\n\n this._layer.off('remove', this.disable, this);\n\n if (this._layerEdited) {\n this._fireUpdate();\n }\n this._layerEdited = false;\n this._fireDisable();\n\n this._enabled = false;\n },\n _extendingDisable() {\n this._layer.off('contextmenu', this._removeMarker, this);\n },\n enabled() {\n return this._enabled;\n },\n toggleEdit(options) {\n if (!this.enabled()) {\n this.enable(options);\n } else {\n this.disable();\n }\n },\n applyOptions() {\n if (this.options[this._editableOption]) {\n this._initMarkers();\n this._map.on('move', this._syncMarkers, this);\n\n // init snapping in different ways\n if (this.options.snappable) {\n this._initSnappableMarkers();\n // update marker latlng when snapped latlng radius is out of min/max\n this._outerMarker.on('drag', this._handleOuterMarkerSnapping, this);\n // sync the hintline with hint marker\n this._outerMarker.on('move', this._syncHintLine, this);\n this._outerMarker.on('move', this._syncCircleRadius, this);\n this._centerMarker.on('move', this._moveCircle, this);\n } else {\n this._disableSnapping();\n }\n } else {\n if (this.options.draggable) {\n this.enableLayerDrag();\n }\n // only update the circle border poly\n this._map.on('move', this._updateHiddenPolyCircle, this);\n\n if (this.options.snappable) {\n this._initSnappableMarkersDrag();\n } else {\n this._disableSnappingDrag();\n }\n }\n\n this._extendingApplyOptions();\n },\n _extendingApplyOptions() {\n // enable removal for the marker\n if (!this.options.preventMarkerRemoval) {\n this._layer.on('contextmenu', this._removeMarker, this);\n }\n },\n _initMarkers() {\n const map = this._map;\n\n // cleanup old ones first\n if (this._helperLayers) {\n this._helperLayers.clearLayers();\n }\n\n // add markerGroup to map, markerGroup includes regular and middle markers\n this._helperLayers = new L.FeatureGroup();\n this._helperLayers._pmTempLayer = true;\n this._helperLayers.addTo(map);\n\n // create marker for each coordinate\n const center = this._layer.getLatLng();\n const radius = this._layer._radius;\n\n const outer = this._getLatLngOnCircle(center, radius);\n\n this._centerMarker = this._createCenterMarker(center);\n this._outerMarker = this._createOuterMarker(outer);\n this._markers = [this._centerMarker, this._outerMarker];\n this._createHintLine(this._centerMarker, this._outerMarker);\n },\n _getLatLngOnCircle(center, radius) {\n const pointA = this._map.project(center);\n const pointB = L.point(pointA.x + radius, pointA.y);\n return this._map.unproject(pointB);\n },\n _createHintLine(markerA, markerB) {\n const A = markerA.getLatLng();\n const B = markerB.getLatLng();\n this._hintline = L.polyline([A, B], this.options.hintlineStyle);\n this._setPane(this._hintline, 'layerPane');\n this._hintline._pmTempLayer = true;\n this._helperLayers.addLayer(this._hintline);\n },\n _createCenterMarker(latlng) {\n const marker = this._createMarker(latlng);\n if (this.options.draggable) {\n L.DomUtil.addClass(marker._icon, 'leaflet-pm-draggable');\n } else {\n marker.dragging.disable();\n }\n return marker;\n },\n _createOuterMarker(latlng) {\n const marker = this._createMarker(latlng);\n marker.on('drag', this._resizeCircle, this);\n return marker;\n },\n _createMarker(latlng) {\n const marker = new L.Marker(latlng, {\n draggable: true,\n icon: L.divIcon({ className: 'marker-icon' }),\n });\n this._setPane(marker, 'vertexPane');\n\n marker._origLatLng = latlng;\n marker._pmTempLayer = true;\n\n marker.on('dragstart', this._onMarkerDragStart, this);\n marker.on('drag', this._onMarkerDrag, this);\n marker.on('dragend', this._onMarkerDragEnd, this);\n marker.on('click', this._onVertexClick, this);\n\n this._helperLayers.addLayer(marker);\n\n return marker;\n },\n\n _moveCircle(e) {\n const draggedMarker = e.target;\n if (draggedMarker._cancelDragEventChain) {\n return;\n }\n\n const center = this._centerMarker.getLatLng();\n this._layer.setLatLng(center);\n\n const radius = this._layer._radius;\n\n const outer = this._getLatLngOnCircle(center, radius);\n // don't call .setLatLng() because it fires the `move` event and then the radius is changed because of _syncCircleRadius #892\n this._outerMarker._latlng = outer;\n this._outerMarker.update();\n this._syncHintLine();\n\n this._updateHiddenPolyCircle();\n\n this._fireCenterPlaced('Edit');\n this._fireChange(this._layer.getLatLng(), 'Edit');\n },\n _syncMarkers() {\n const center = this._layer.getLatLng();\n const radius = this._layer._radius;\n const outer = this._getLatLngOnCircle(center, radius);\n this._outerMarker.setLatLng(outer);\n this._centerMarker.setLatLng(center);\n this._syncHintLine();\n this._updateHiddenPolyCircle();\n },\n _resizeCircle() {\n this._outerMarker.setLatLng(this._getNewDestinationOfOuterMarker());\n this._syncHintLine();\n this._syncCircleRadius();\n },\n _syncCircleRadius() {\n const A = this._centerMarker.getLatLng();\n const B = this._outerMarker.getLatLng();\n\n const distance = this._distanceCalculation(A, B);\n\n if (\n this.options[this._minRadiusOption] &&\n distance < this.options[this._minRadiusOption]\n ) {\n this._layer.setRadius(this.options[this._minRadiusOption]);\n } else if (\n this.options[this._maxRadiusOption] &&\n distance > this.options[this._maxRadiusOption]\n ) {\n this._layer.setRadius(this.options[this._maxRadiusOption]);\n } else {\n this._layer.setRadius(distance);\n }\n\n this._updateHiddenPolyCircle();\n this._fireChange(this._layer.getLatLng(), 'Edit');\n },\n _syncHintLine() {\n const A = this._centerMarker.getLatLng();\n const B = this._outerMarker.getLatLng();\n // set coords for hintline from marker to last vertex of drawin polyline\n this._hintline.setLatLngs([A, B]);\n },\n _removeMarker() {\n if (this.options[this._editableOption]) {\n this.disable();\n }\n this._layer.remove();\n this._fireRemove(this._layer);\n this._fireRemove(this._map, this._layer);\n },\n _onDragStart() {\n this._map.pm.Draw.CircleMarker._layerIsDragging = true;\n },\n _onMarkerDragStart(e) {\n if (!this._vertexValidation('move', e)) {\n return;\n }\n\n this._fireMarkerDragStart(e);\n },\n _onMarkerDrag(e) {\n // dragged marker\n const draggedMarker = e.target;\n if (\n draggedMarker instanceof L.Marker &&\n !this._vertexValidationDrag(draggedMarker)\n ) {\n return;\n }\n\n this._fireMarkerDrag(e);\n },\n _onMarkerDragEnd(e) {\n this._extedingMarkerDragEnd();\n\n // dragged marker\n const draggedMarker = e.target;\n if (!this._vertexValidationDragEnd(draggedMarker)) {\n return;\n }\n if (this.options[this._editableOption]) {\n this._fireEdit();\n this._layerEdited = true;\n }\n this._fireMarkerDragEnd(e);\n },\n _extedingMarkerDragEnd() {\n this._map.pm.Draw.CircleMarker._layerIsDragging = false;\n },\n // _initSnappableMarkers when option editable is not true\n _initSnappableMarkersDrag() {\n const marker = this._layer;\n\n this.options.snapDistance = this.options.snapDistance || 30;\n this.options.snapSegment =\n this.options.snapSegment === undefined ? true : this.options.snapSegment;\n\n marker.off('pm:drag', this._handleSnapping, this);\n marker.on('pm:drag', this._handleSnapping, this);\n\n marker.off('pm:dragend', this._cleanupSnapping, this);\n marker.on('pm:dragend', this._cleanupSnapping, this);\n\n marker.off('pm:dragstart', this._unsnap, this);\n marker.on('pm:dragstart', this._unsnap, this);\n },\n // _disableSnapping when option editable is not true\n _disableSnappingDrag() {\n const marker = this._layer;\n\n marker.off('pm:drag', this._handleSnapping, this);\n marker.off('pm:dragend', this._cleanupSnapping, this);\n marker.off('pm:dragstart', this._unsnap, this);\n },\n _updateHiddenPolyCircle() {\n const map = this._layer._map || this._map;\n if (map) {\n const radius = L.PM.Utils.pxRadiusToMeterRadius(\n this._layer.getRadius(),\n map,\n this._layer.getLatLng()\n );\n const _layer = L.circle(this._layer.getLatLng(), this._layer.options);\n _layer.setRadius(radius);\n\n const crsSimple = map && map.pm._isCRSSimple();\n if (this._hiddenPolyCircle) {\n this._hiddenPolyCircle.setLatLngs(\n L.PM.Utils.circleToPolygon(_layer, 200, !crsSimple).getLatLngs()\n );\n } else {\n this._hiddenPolyCircle = L.PM.Utils.circleToPolygon(\n _layer,\n 200,\n !crsSimple\n );\n }\n\n if (!this._hiddenPolyCircle._parentCopy) {\n this._hiddenPolyCircle._parentCopy = this._layer;\n }\n }\n },\n _getNewDestinationOfOuterMarker() {\n const latlng = this._centerMarker.getLatLng();\n let secondLatLng = this._outerMarker.getLatLng();\n\n const distance = this._distanceCalculation(latlng, secondLatLng);\n\n if (\n this.options[this._minRadiusOption] &&\n distance < this.options[this._minRadiusOption]\n ) {\n secondLatLng = destinationOnLine(\n this._map,\n latlng,\n secondLatLng,\n this._getMinDistanceInMeter(latlng)\n );\n } else if (\n this.options[this._maxRadiusOption] &&\n distance > this.options[this._maxRadiusOption]\n ) {\n secondLatLng = destinationOnLine(\n this._map,\n latlng,\n secondLatLng,\n this._getMaxDistanceInMeter(latlng)\n );\n }\n return secondLatLng;\n },\n _handleOuterMarkerSnapping() {\n if (this._outerMarker._snapped) {\n const latlng = this._centerMarker.getLatLng();\n const secondLatLng = this._outerMarker.getLatLng();\n const distance = this._distanceCalculation(latlng, secondLatLng);\n if (\n this.options[this._minRadiusOption] &&\n distance < this.options[this._minRadiusOption]\n ) {\n this._outerMarker.setLatLng(this._outerMarker._orgLatLng);\n } else if (\n this.options[this._maxRadiusOption] &&\n distance > this.options[this._maxRadiusOption]\n ) {\n this._outerMarker.setLatLng(this._outerMarker._orgLatLng);\n }\n }\n // calculate the new latlng of marker if radius is out of min/max\n this._outerMarker.setLatLng(this._getNewDestinationOfOuterMarker());\n },\n _distanceCalculation(A, B) {\n return this._map.project(A).distanceTo(this._map.project(B));\n },\n _getMinDistanceInMeter(latlng) {\n return L.PM.Utils.pxRadiusToMeterRadius(\n this.options[this._minRadiusOption],\n this._map,\n latlng\n );\n },\n _getMaxDistanceInMeter(latlng) {\n return L.PM.Utils.pxRadiusToMeterRadius(\n this.options[this._maxRadiusOption],\n this._map,\n latlng\n );\n },\n _onVertexClick(e) {\n const vertex = e.target;\n if (vertex._dragging) {\n return;\n }\n\n this._fireVertexClick(e, undefined);\n },\n});\n","import Edit from './L.PM.Edit';\n\nEdit.Circle = Edit.CircleMarker.extend({\n _shape: 'Circle',\n initialize(layer) {\n this._layer = layer;\n this._enabled = false;\n\n this._minRadiusOption = 'minRadiusCircle';\n this._maxRadiusOption = 'maxRadiusCircle';\n this._editableOption = 'resizableCircle';\n // create polygon around the circle border\n this._updateHiddenPolyCircle();\n },\n enable(options) {\n // TODO: this can be removed after the default options of CircleMarker.enable are removed\n L.PM.Edit.CircleMarker.prototype.enable.call(this, options || {});\n },\n _extendingEnable() {},\n _extendingDisable() {\n this._layer.off('remove', this.disable, this);\n\n // remove draggable class\n const el = this._layer._path\n ? this._layer._path\n : this._layer._renderer._container;\n L.DomUtil.removeClass(el, 'leaflet-pm-draggable');\n },\n _extendingApplyOptions() {},\n _syncMarkers() {},\n _removeMarker() {},\n _onDragStart() {},\n _extedingMarkerDragEnd() {},\n _updateHiddenPolyCircle() {\n const crsSimple = this._map && this._map.pm._isCRSSimple();\n if (this._hiddenPolyCircle) {\n this._hiddenPolyCircle.setLatLngs(\n L.PM.Utils.circleToPolygon(this._layer, 200, !crsSimple).getLatLngs()\n );\n } else {\n this._hiddenPolyCircle = L.PM.Utils.circleToPolygon(\n this._layer,\n 200,\n !crsSimple\n );\n }\n\n if (!this._hiddenPolyCircle._parentCopy) {\n this._hiddenPolyCircle._parentCopy = this._layer;\n }\n },\n _distanceCalculation(A, B) {\n return this._map.distance(A, B);\n },\n _getMinDistanceInMeter() {\n return this.options[this._minRadiusOption];\n },\n _getMaxDistanceInMeter() {\n return this.options[this._maxRadiusOption];\n },\n _onVertexClick(e) {\n const vertex = e.target;\n if (vertex._dragging) {\n return;\n }\n\n this._fireVertexClick(e, undefined);\n },\n});\n","import Edit from './L.PM.Edit';\n\nEdit.ImageOverlay = Edit.extend({\n _shape: 'ImageOverlay',\n initialize(layer) {\n this._layer = layer;\n this._enabled = false;\n },\n toggleEdit(options) {\n if (!this.enabled()) {\n this.enable(options);\n } else {\n this.disable();\n }\n },\n enabled() {\n return this._enabled;\n },\n // TODO: remove default option in next major Release\n enable(options = { draggable: true, snappable: true }) {\n L.Util.setOptions(this, options);\n this._map = this._layer._map;\n // cancel when map isn't available, this happens when the polygon is removed before this fires\n if (!this._map) {\n return;\n }\n\n // layer is not allowed to edit\n if (!this.options.allowEditing) {\n this.disable();\n return;\n }\n\n if (!this.enabled()) {\n // if it was already enabled, disable first\n // we don't block enabling again because new options might be passed\n this.disable();\n }\n\n this.enableLayerDrag();\n\n // if shape gets removed from map, disable edit mode\n this._layer.on('remove', this.disable, this);\n\n // change state\n this._enabled = true;\n\n // create markers for four corners of ImageOverlay\n this._otherSnapLayers = this._findCorners();\n\n this._fireEnable();\n },\n disable() {\n // prevent disabling if layer is being dragged\n if (this._dragging) {\n return;\n }\n\n // Add map if it is not already set. This happens when disable() is called before enable()\n if (!this._map) {\n this._map = this._layer._map;\n }\n // disable dragging, as this could have been active even without being enabled\n this.disableLayerDrag();\n\n // remove listener\n this._layer.off('remove', this.disable, this);\n\n // only fire events if it was enabled before\n if (!this.enabled()) {\n if (this._layerEdited) {\n this._fireUpdate();\n }\n this._layerEdited = false;\n this._fireDisable();\n }\n\n this._enabled = false;\n },\n _findCorners() {\n const corners = this._layer.getBounds();\n\n const northwest = corners.getNorthWest();\n const northeast = corners.getNorthEast();\n const southeast = corners.getSouthEast();\n const southwest = corners.getSouthWest();\n\n return [northwest, northeast, southeast, southwest];\n },\n});\n","import Edit from './L.PM.Edit';\n\nEdit.Text = Edit.extend({\n _shape: 'Text',\n initialize(layer) {\n this._layer = layer;\n this._enabled = false;\n },\n enable(options) {\n L.Util.setOptions(this, options);\n\n if (!this.textArea) {\n return;\n }\n\n // layer is not allowed to edit\n if (!this.options.allowEditing || !this._layer._map) {\n this.disable();\n return;\n }\n\n this._map = this._layer._map;\n\n if (this.enabled()) {\n this.disable();\n }\n this.applyOptions();\n\n this._safeToCacheDragState = true;\n\n this._focusChange();\n this.textArea.readOnly = false;\n this.textArea.classList.remove('pm-disabled');\n\n // if shape gets removed from map, disable edit mode\n this._layer.on('remove', this.disable, this);\n L.DomEvent.on(this.textArea, 'input', this._autoResize, this);\n L.DomEvent.on(this.textArea, 'focus', this._focusChange, this);\n L.DomEvent.on(this.textArea, 'blur', this._focusChange, this);\n this._layer.on('dblclick', L.DomEvent.stop);\n\n L.DomEvent.off(this.textArea, 'mousedown', this._preventTextSelection);\n\n this._enabled = true;\n\n this._fireEnable();\n },\n disable() {\n // if it's not enabled, it doesn't need to be disabled\n if (!this.enabled()) {\n return;\n }\n\n // remove listener\n this._layer.off('remove', this.disable, this);\n L.DomEvent.off(this.textArea, 'input', this._autoResize, this);\n L.DomEvent.off(this.textArea, 'focus', this._focusChange, this);\n L.DomEvent.off(this.textArea, 'blur', this._focusChange, this);\n L.DomEvent.off(document, 'click', this._documentClick, this);\n\n this._focusChange();\n this.textArea.readOnly = true;\n this.textArea.classList.add('pm-disabled');\n\n // remove selection\n const focusedElement = document.activeElement;\n // Chrome needs the focus on the element to change the selection\n this.textArea.focus();\n this.textArea.selectionStart = 0;\n this.textArea.selectionEnd = 0;\n L.DomEvent.on(this.textArea, 'mousedown', this._preventTextSelection);\n focusedElement.focus();\n\n this._disableOnBlurActive = false;\n\n if (this._layerEdited) {\n this._fireUpdate();\n }\n this._layerEdited = false;\n this._fireDisable();\n\n this._enabled = false;\n },\n enabled() {\n return this._enabled;\n },\n toggleEdit(options) {\n if (!this.enabled()) {\n this.enable(options);\n } else {\n this.disable();\n }\n },\n applyOptions() {\n if (this.options.snappable) {\n this._initSnappableMarkers();\n } else {\n this._disableSnapping();\n }\n },\n // overwrite initSnappableMarkers from Snapping.js Mixin\n _initSnappableMarkers() {\n const marker = this._layer;\n\n this.options.snapDistance = this.options.snapDistance || 30;\n this.options.snapSegment =\n this.options.snapSegment === undefined ? true : this.options.snapSegment;\n\n marker.off('pm:drag', this._handleSnapping, this);\n marker.on('pm:drag', this._handleSnapping, this);\n\n marker.off('pm:dragend', this._cleanupSnapping, this);\n marker.on('pm:dragend', this._cleanupSnapping, this);\n\n marker.off('pm:dragstart', this._unsnap, this);\n marker.on('pm:dragstart', this._unsnap, this);\n },\n _disableSnapping() {\n const marker = this._layer;\n marker.off('pm:drag', this._handleSnapping, this);\n marker.off('pm:dragend', this._cleanupSnapping, this);\n marker.off('pm:dragstart', this._unsnap, this);\n },\n _autoResize() {\n this.textArea.style.height = '1px';\n this.textArea.style.width = '1px';\n const height =\n this.textArea.scrollHeight > 21 ? this.textArea.scrollHeight : 21;\n const width =\n this.textArea.scrollWidth > 16 ? this.textArea.scrollWidth : 16;\n this.textArea.style.height = `${height}px`;\n this.textArea.style.width = `${width}px`;\n this._layer.options.text = this.getText();\n this._fireTextChange(this.getText());\n },\n\n _disableOnBlur() {\n this._disableOnBlurActive = true;\n // we need this timeout because else the place click event is triggered here too.\n setTimeout(() => {\n if (this.enabled()) {\n L.DomEvent.on(document, 'click', this._documentClick, this);\n }\n }, 100);\n },\n _documentClick(e) {\n if (e.target !== this.textArea) {\n this.disable();\n if (!this.getText() && this.options.removeIfEmpty) {\n this.remove();\n }\n }\n },\n\n _focusChange(e = {}) {\n const focusAlreadySet = this._hasFocus;\n this._hasFocus = e.type === 'focus';\n if (!focusAlreadySet !== !this._hasFocus) {\n if (this._hasFocus) {\n this._applyFocus();\n this._focusText = this.getText();\n this._fireTextFocus();\n } else {\n this._removeFocus();\n this._fireTextBlur();\n if (this._focusText !== this.getText()) {\n this._fireEdit();\n this._layerEdited = true;\n }\n }\n }\n },\n _applyFocus() {\n this.textArea.classList.add('pm-hasfocus');\n\n if (this._map.dragging) {\n // save current map dragging state\n if (this._safeToCacheDragState) {\n this._originalMapDragState = this._map.dragging._enabled;\n // don't cache the state again until another mouse up is registered\n this._safeToCacheDragState = false;\n }\n this._map.dragging.disable();\n }\n },\n _removeFocus() {\n if (this._map.dragging) {\n if (this._originalMapDragState) {\n this._map.dragging.enable();\n }\n this._safeToCacheDragState = true;\n }\n\n this.textArea.classList.remove('pm-hasfocus');\n },\n\n focus() {\n if (!this.enabled()) {\n throw new TypeError('Layer is not enabled');\n }\n this.textArea.focus();\n },\n\n blur() {\n if (!this.enabled()) {\n throw new TypeError('Layer is not enabled');\n }\n this.textArea.blur();\n if (this._disableOnBlurActive) {\n this.disable();\n }\n },\n\n hasFocus() {\n return this._hasFocus;\n },\n\n getElement() {\n return this.textArea;\n },\n\n setText(text) {\n this.textArea.value = text;\n this._autoResize();\n },\n\n getText() {\n return this.textArea.value;\n },\n\n _initTextMarker() {\n this.textArea = L.PM.Draw.Text.prototype._createTextArea.call(this);\n if (this.options.className) {\n const cssClasses = this.options.className.split(' ');\n this.textArea.classList.add(...cssClasses);\n }\n const textAreaIcon = L.PM.Draw.Text.prototype._createTextIcon.call(\n this,\n this.textArea\n );\n this._layer.setIcon(textAreaIcon);\n\n this._layer.once('add', this._createTextMarker, this);\n },\n\n _createTextMarker(enable = false) {\n this._layer.off('add', this._createTextMarker, this);\n\n this._layer.getElement().tabIndex = -1;\n\n this.textArea.wrap = 'off';\n this.textArea.style.overflow = 'hidden';\n this.textArea.style.height = L.DomUtil.getStyle(this.textArea, 'font-size');\n this.textArea.style.width = '1px';\n\n if (this._layer.options.text) {\n this.setText(this._layer.options.text);\n }\n\n this._autoResize();\n\n if (enable === true) {\n // enable editing for the marker\n this.enable();\n this.focus();\n this._disableOnBlur();\n }\n },\n\n // Chrome ignores `user-select: none`, so we need to disable text selection manually\n _preventTextSelection(e) {\n e.preventDefault();\n },\n});\n","/**\n * Copyright (c) https://github.com/w8r/Leaflet.Path.Transform\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n */\n\n/**\n * @class L.PM.Matrix\n *\n * @param {Number} a\n * @param {Number} b\n * @param {Number} c\n * @param {Number} d\n * @param {Number} e\n * @param {Number} f\n */\nconst Matrix = function Matrix(a, b, c, d, e, f) {\n /**\n * @type {Array.}\n */\n this._matrix = [a, b, c, d, e, f];\n};\n\nMatrix.init = () => new L.PM.Matrix(1, 0, 0, 1, 0, 0);\n\nMatrix.prototype = {\n /**\n * @param {L.Point} point\n * @return {L.Point}\n */\n transform(point) {\n return this._transform(point.clone());\n },\n\n /**\n * Destructive\n *\n * [ x ] = [ a b tx ] [ x ] = [ a * x + b * y + tx ]\n * [ y ] = [ c d ty ] [ y ] = [ c * x + d * y + ty ]\n *\n * @param {L.Point} point\n * @return {L.Point}\n */\n _transform(point) {\n const matrix = this._matrix;\n const { x, y } = point;\n point.x = matrix[0] * x + matrix[1] * y + matrix[4];\n point.y = matrix[2] * x + matrix[3] * y + matrix[5];\n return point;\n },\n\n /**\n * @param {L.Point} point\n * @return {L.Point}\n */\n untransform(point) {\n const matrix = this._matrix;\n return new L.Point(\n (point.x / matrix[0] - matrix[4]) / matrix[0],\n (point.y / matrix[2] - matrix[5]) / matrix[2]\n );\n },\n\n /**\n * @return {L.PM.Matrix}\n */\n clone() {\n const matrix = this._matrix;\n return new L.PM.Matrix(\n matrix[0],\n matrix[1],\n matrix[2],\n matrix[3],\n matrix[4],\n matrix[5]\n );\n },\n\n /**\n * @param {L.Point|Number} translate\n * @return {L.PM.Matrix|L.Point}\n */\n translate(translate) {\n if (translate === undefined) {\n return new L.Point(this._matrix[4], this._matrix[5]);\n }\n\n let translateX;\n let translateY;\n if (typeof translate === 'number') {\n translateX = translate;\n translateY = translate;\n } else {\n translateX = translate.x;\n translateY = translate.y;\n }\n\n return this._add(1, 0, 0, 1, translateX, translateY);\n },\n\n /**\n * @param {L.Point|Number} scale\n * @param {L.Point|Number} origin\n * @return {L.PM.Matrix|L.Point}\n */\n scale(scale, origin) {\n if (scale === undefined) {\n return new L.Point(this._matrix[0], this._matrix[3]);\n }\n\n let scaleX;\n let scaleY;\n origin = origin || L.point(0, 0);\n if (typeof scale === 'number') {\n scaleX = scale;\n scaleY = scale;\n } else {\n scaleX = scale.x;\n scaleY = scale.y;\n }\n\n return this._add(scaleX, 0, 0, scaleY, origin.x, origin.y)._add(\n 1,\n 0,\n 0,\n 1,\n -origin.x,\n -origin.y\n );\n },\n\n /**\n * m00 m01 x - m00 * x - m01 * y\n * m10 m11 y - m10 * x - m11 * y\n * @param {Number} angle\n * @param {L.Point=} origin\n * @return {L.PM.Matrix}\n */\n rotate(angle, origin) {\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n\n origin = origin || new L.Point(0, 0);\n\n return this._add(cos, sin, -sin, cos, origin.x, origin.y)._add(\n 1,\n 0,\n 0,\n 1,\n -origin.x,\n -origin.y\n );\n },\n\n /**\n * Invert rotation\n * @return {L.PM.Matrix}\n */\n flip() {\n this._matrix[1] *= -1;\n this._matrix[2] *= -1;\n return this;\n },\n\n /**\n * @param {Number|L.PM.Matrix} a\n * @param {Number} b\n * @param {Number} c\n * @param {Number} d\n * @param {Number} e\n * @param {Number} f\n */\n _add(a, b, c, d, e, f) {\n const result = [[], [], []];\n let src = this._matrix;\n const m = [\n [src[0], src[2], src[4]],\n [src[1], src[3], src[5]],\n [0, 0, 1],\n ];\n let other = [\n [a, c, e],\n [b, d, f],\n [0, 0, 1],\n ];\n let val;\n\n if (a && a instanceof L.PM.Matrix) {\n src = a._matrix;\n other = [\n [src[0], src[2], src[4]],\n [src[1], src[3], src[5]],\n [0, 0, 1],\n ];\n }\n\n for (let i = 0; i < 3; i += 1) {\n for (let j = 0; j < 3; j += 1) {\n val = 0;\n for (let k = 0; k < 3; k += 1) {\n val += m[i][k] * other[k][j];\n }\n result[i][j] = val;\n }\n }\n\n this._matrix = [\n result[0][0],\n result[1][0],\n result[0][1],\n result[1][1],\n result[0][2],\n result[1][2],\n ];\n return this;\n },\n};\n\nexport default Matrix;\n","import { createGeodesicPolygon, getTranslation } from './helpers';\nimport { _toLatLng, _toPoint } from './helpers/ModeHelper';\n\nconst Utils = {\n calcMiddleLatLng(map, latlng1, latlng2) {\n // calculate the middle coordinates between two markers\n\n const p1 = map.project(latlng1);\n const p2 = map.project(latlng2);\n\n return map.unproject(p1._add(p2)._divideBy(2));\n },\n findLayers(map) {\n let layers = [];\n map.eachLayer((layer) => {\n if (\n layer instanceof L.Polyline ||\n layer instanceof L.Marker ||\n layer instanceof L.Circle ||\n layer instanceof L.CircleMarker ||\n layer instanceof L.ImageOverlay\n ) {\n layers.push(layer);\n }\n });\n\n // filter out layers that don't have the leaflet-geoman instance\n layers = layers.filter((layer) => !!layer.pm);\n\n // filter out everything that's leaflet-geoman specific temporary stuff\n layers = layers.filter((layer) => !layer._pmTempLayer);\n\n // filter out everything that ignore leaflet-geoman\n layers = layers.filter(\n (layer) =>\n (!L.PM.optIn && !layer.options.pmIgnore) || // if optIn is not set / true and pmIgnore is not set / true (default)\n (L.PM.optIn && layer.options.pmIgnore === false) // if optIn is true and pmIgnore is false);\n );\n\n return layers;\n },\n circleToPolygon(circle, sides = 60, withBearing = true) {\n const origin = circle.getLatLng();\n const radius = circle.getRadius();\n const polys = createGeodesicPolygon(origin, radius, sides, 0, withBearing); // these are the points that make up the circle\n const polygon = [];\n for (let i = 0; i < polys.length; i += 1) {\n const geometry = [polys[i].lat, polys[i].lng];\n polygon.push(geometry);\n }\n return L.polygon(polygon, circle.options);\n },\n disablePopup(layer) {\n if (layer.getPopup()) {\n layer._tempPopupCopy = layer.getPopup();\n layer.unbindPopup();\n }\n },\n enablePopup(layer) {\n if (layer._tempPopupCopy) {\n layer.bindPopup(layer._tempPopupCopy);\n delete layer._tempPopupCopy;\n }\n },\n _fireEvent(layer, type, data, propagate = false) {\n layer.fire(type, data, propagate);\n\n // fire event to all parent layers\n const { groups } = this.getAllParentGroups(layer);\n groups.forEach((group) => {\n group.fire(type, data, propagate);\n });\n },\n getAllParentGroups(layer) {\n const groupIds = [];\n const groups = [];\n\n // get every group layer once\n const loopThroughParents = (_layer) => {\n for (const _id in _layer._eventParents) {\n if (groupIds.indexOf(_id) === -1) {\n groupIds.push(_id);\n const group = _layer._eventParents[_id];\n groups.push(group);\n loopThroughParents(group);\n }\n }\n };\n\n // check if the last group fetch is under 1 sec, then we use the groups from before\n if (\n !layer._pmLastGroupFetch ||\n !layer._pmLastGroupFetch.time ||\n new Date().getTime() - layer._pmLastGroupFetch.time > 1000\n ) {\n loopThroughParents(layer);\n layer._pmLastGroupFetch = {\n time: new Date().getTime(),\n groups,\n groupIds,\n };\n return {\n groupIds,\n groups,\n };\n }\n return {\n groups: layer._pmLastGroupFetch.groups,\n groupIds: layer._pmLastGroupFetch.groupIds,\n };\n },\n createGeodesicPolygon,\n getTranslation,\n findDeepCoordIndex(arr, latlng, exact = true) {\n // find latlng in arr and return its location as path\n // thanks for the function, Felix Heck\n let result;\n\n const run = (path) => (v, i) => {\n const iRes = path.concat(i);\n\n if (exact) {\n if (v.lat && v.lat === latlng.lat && v.lng === latlng.lng) {\n result = iRes;\n return true;\n }\n } else if (v.lat && L.latLng(v).equals(latlng)) {\n result = iRes;\n return true;\n }\n\n return Array.isArray(v) && v.some(run(iRes));\n };\n arr.some(run([]));\n\n let returnVal = {};\n\n if (result) {\n returnVal = {\n indexPath: result,\n index: result[result.length - 1],\n parentPath: result.slice(0, result.length - 1),\n };\n }\n\n return returnVal;\n },\n findDeepMarkerIndex(arr, marker) {\n // thanks for the function, Felix Heck\n let result;\n\n const run = (path) => (v, i) => {\n const iRes = path.concat(i);\n\n if (v._leaflet_id === marker._leaflet_id) {\n result = iRes;\n return true;\n }\n\n return Array.isArray(v) && v.some(run(iRes));\n };\n arr.some(run([]));\n\n let returnVal = {};\n\n if (result) {\n returnVal = {\n indexPath: result,\n index: result[result.length - 1],\n parentPath: result.slice(0, result.length - 1),\n };\n }\n\n return returnVal;\n },\n _getIndexFromSegment(coords, segment) {\n if (segment && segment.length === 2) {\n const indexA = this.findDeepCoordIndex(coords, segment[0]);\n const indexB = this.findDeepCoordIndex(coords, segment[1]);\n let newIndex = Math.max(indexA.index, indexB.index);\n if ((indexA.index === 0 || indexB.index === 0) && newIndex !== 1) {\n newIndex += 1;\n }\n return {\n indexA,\n indexB,\n newIndex,\n indexPath: indexA.indexPath,\n parentPath: indexA.parentPath,\n };\n }\n return null;\n },\n // Returns the corners of the rectangle with a given rotation\n // degrees: Between marker A and the marker counterclockwise before. Same for marker B\n _getRotatedRectangle(A, B, rotation, map) {\n const startPoint = _toPoint(map, A);\n const endPoint = _toPoint(map, B);\n const theta = (rotation * Math.PI) / 180;\n const cos = Math.cos(theta);\n const sin = Math.sin(theta);\n\n const width =\n (endPoint.x - startPoint.x) * cos + (endPoint.y - startPoint.y) * sin;\n const height =\n (endPoint.y - startPoint.y) * cos - (endPoint.x - startPoint.x) * sin;\n const x0 = width * cos + startPoint.x;\n const y0 = width * sin + startPoint.y;\n const x1 = -height * sin + startPoint.x;\n const y1 = height * cos + startPoint.y;\n\n const p0 = _toLatLng(map, startPoint);\n const p1 = _toLatLng(map, { x: x0, y: y0 });\n const p2 = _toLatLng(map, endPoint);\n const p3 = _toLatLng(map, { x: x1, y: y1 });\n return [p0, p1, p2, p3];\n },\n pxRadiusToMeterRadius(radiusInPx, map, center) {\n const pointA = map.project(center);\n const pointB = L.point(pointA.x + radiusInPx, pointA.y);\n return map.distance(map.unproject(pointB), center);\n },\n};\n\nexport default Utils;\n","/* A Leaflet Plugin For Editing Geometry Layers in Leaflet 1.0\n * Copyright (C) Geoman.io and Sumit Kumar - All Rights Reserved\n * Unauthorized copying of this file, via any medium is strictly prohibited\n * Proprietary and confidential\n * Written by Sumit Kumar , January 2020\n * Twitter: @TweetsOfSumit\n * OSS Repo: https://github.com/geoman-io/leaflet-geoman\n * Get Pro: https://geoman.io\n */\n\nimport './polyfills';\nimport packageInfo from '../../package.json';\n\nimport Map from './L.PM.Map';\nimport Toolbar from './Toolbar/L.PM.Toolbar';\n\nimport Draw from './Draw/L.PM.Draw';\nimport './Draw/L.PM.Draw.Marker';\nimport './Draw/L.PM.Draw.Line';\nimport './Draw/L.PM.Draw.Polygon';\nimport './Draw/L.PM.Draw.Rectangle';\nimport './Draw/L.PM.Draw.CircleMarker';\nimport './Draw/L.PM.Draw.Circle';\nimport './Draw/L.PM.Draw.Cut';\nimport './Draw/L.PM.Draw.Text';\n\nimport Edit from './Edit/L.PM.Edit';\nimport './Edit/L.PM.Edit.LayerGroup';\nimport './Edit/L.PM.Edit.Marker';\nimport './Edit/L.PM.Edit.Line';\nimport './Edit/L.PM.Edit.Polygon';\nimport './Edit/L.PM.Edit.Rectangle';\nimport './Edit/L.PM.Edit.CircleMarker';\nimport './Edit/L.PM.Edit.Circle';\nimport './Edit/L.PM.Edit.ImageOverlay';\nimport './Edit/L.PM.Edit.Text';\n\nimport '../css/layers.css';\nimport '../css/controls.css';\n\nimport Matrix from './helpers/Matrix';\n\nimport Utils from './L.PM.Utils';\n\nL.PM = L.PM || {\n version: packageInfo.version,\n Map,\n Toolbar,\n Draw,\n Edit,\n Utils,\n Matrix,\n activeLang: 'en',\n optIn: false,\n initialize(options) {\n this.addInitHooks(options);\n },\n setOptIn(value) {\n this.optIn = !!value;\n },\n addInitHooks() {\n function initMap() {\n this.pm = undefined;\n\n if (L.PM.optIn) {\n if (this.options.pmIgnore === false) {\n this.pm = new L.PM.Map(this);\n }\n } else if (!this.options.pmIgnore) {\n this.pm = new L.PM.Map(this);\n }\n\n if (this.pm) {\n this.pm.setGlobalOptions({});\n }\n }\n\n L.Map.addInitHook(initMap);\n\n function initLayerGroup() {\n this.pm = undefined;\n if (L.PM.optIn) {\n if (this.options.pmIgnore === false) {\n this.pm = new L.PM.Edit.LayerGroup(this);\n }\n } else if (!this.options.pmIgnore) {\n this.pm = new L.PM.Edit.LayerGroup(this);\n }\n }\n\n L.LayerGroup.addInitHook(initLayerGroup);\n\n function initMarker() {\n this.pm = undefined;\n\n if (L.PM.optIn) {\n if (this.options.pmIgnore === false) {\n if (this.options.textMarker) {\n this.pm = new L.PM.Edit.Text(this);\n if (!this.options._textMarkerOverPM) {\n this.pm._initTextMarker();\n }\n delete this.options._textMarkerOverPM;\n } else {\n this.pm = new L.PM.Edit.Marker(this);\n }\n }\n } else if (!this.options.pmIgnore) {\n if (this.options.textMarker) {\n this.pm = new L.PM.Edit.Text(this);\n if (!this.options._textMarkerOverPM) {\n this.pm._initTextMarker();\n }\n delete this.options._textMarkerOverPM;\n } else {\n this.pm = new L.PM.Edit.Marker(this);\n }\n }\n }\n L.Marker.addInitHook(initMarker);\n\n function initCircleMarker() {\n this.pm = undefined;\n\n if (L.PM.optIn) {\n if (this.options.pmIgnore === false) {\n this.pm = new L.PM.Edit.CircleMarker(this);\n }\n } else if (!this.options.pmIgnore) {\n this.pm = new L.PM.Edit.CircleMarker(this);\n }\n }\n L.CircleMarker.addInitHook(initCircleMarker);\n\n function initPolyline() {\n this.pm = undefined;\n\n if (L.PM.optIn) {\n if (this.options.pmIgnore === false) {\n this.pm = new L.PM.Edit.Line(this);\n }\n } else if (!this.options.pmIgnore) {\n this.pm = new L.PM.Edit.Line(this);\n }\n }\n\n L.Polyline.addInitHook(initPolyline);\n\n function initPolygon() {\n this.pm = undefined;\n\n if (L.PM.optIn) {\n if (this.options.pmIgnore === false) {\n this.pm = new L.PM.Edit.Polygon(this);\n }\n } else if (!this.options.pmIgnore) {\n this.pm = new L.PM.Edit.Polygon(this);\n }\n }\n\n L.Polygon.addInitHook(initPolygon);\n\n function initRectangle() {\n this.pm = undefined;\n\n if (L.PM.optIn) {\n if (this.options.pmIgnore === false) {\n this.pm = new L.PM.Edit.Rectangle(this);\n }\n } else if (!this.options.pmIgnore) {\n this.pm = new L.PM.Edit.Rectangle(this);\n }\n }\n\n L.Rectangle.addInitHook(initRectangle);\n\n function initCircle() {\n this.pm = undefined;\n\n if (L.PM.optIn) {\n if (this.options.pmIgnore === false) {\n this.pm = new L.PM.Edit.Circle(this);\n }\n } else if (!this.options.pmIgnore) {\n this.pm = new L.PM.Edit.Circle(this);\n }\n }\n\n L.Circle.addInitHook(initCircle);\n\n function initImageOverlay() {\n this.pm = undefined;\n\n if (L.PM.optIn) {\n if (this.options.pmIgnore === false) {\n this.pm = new L.PM.Edit.ImageOverlay(this);\n }\n } else if (!this.options.pmIgnore) {\n this.pm = new L.PM.Edit.ImageOverlay(this);\n }\n }\n\n L.ImageOverlay.addInitHook(initImageOverlay);\n },\n reInitLayer(layer) {\n if (layer instanceof L.LayerGroup) {\n layer.eachLayer((_layer) => {\n this.reInitLayer(_layer);\n });\n }\n if (layer.pm) {\n // PM is already added to the layer\n } else if (L.PM.optIn && layer.options.pmIgnore !== false) {\n // Opt-In is true and pmIgnore is not false\n } else if (layer.options.pmIgnore) {\n // pmIgnore is true\n } else if (layer instanceof L.Map) {\n layer.pm = new L.PM.Map(layer);\n } else if (layer instanceof L.Marker) {\n if (layer.options.textMarker) {\n layer.pm = new L.PM.Edit.Text(layer);\n layer.pm._initTextMarker();\n layer.pm._createTextMarker(false);\n } else {\n layer.pm = new L.PM.Edit.Marker(layer);\n }\n } else if (layer instanceof L.Circle) {\n layer.pm = new L.PM.Edit.Circle(layer);\n } else if (layer instanceof L.CircleMarker) {\n layer.pm = new L.PM.Edit.CircleMarker(layer);\n } else if (layer instanceof L.Rectangle) {\n layer.pm = new L.PM.Edit.Rectangle(layer);\n } else if (layer instanceof L.Polygon) {\n layer.pm = new L.PM.Edit.Polygon(layer);\n } else if (layer instanceof L.Polyline) {\n layer.pm = new L.PM.Edit.Line(layer);\n } else if (layer instanceof L.LayerGroup) {\n layer.pm = new L.PM.Edit.LayerGroup(layer);\n } else if (layer instanceof L.ImageOverlay) {\n layer.pm = new L.PM.Edit.ImageOverlay(layer);\n }\n },\n};\n\nif (L.version === '1.7.1') {\n // Canvas Mode: After dragging the map the target layer can't be dragged anymore until it is clicked\n // https://github.com/Leaflet/Leaflet/issues/7775 a fix is already merged for the Leaflet 1.8.0 version\n L.Canvas.include({\n _onClick(e) {\n const point = this._map.mouseEventToLayerPoint(e);\n let layer;\n let clickedLayer;\n\n for (let order = this._drawFirst; order; order = order.next) {\n layer = order.layer;\n if (layer.options.interactive && layer._containsPoint(point)) {\n // changing e.type !== 'preclick' to e.type === 'preclick' fix the issue\n if (\n !(e.type === 'click' || e.type === 'preclick') ||\n !this._map._draggableMoved(layer)\n ) {\n clickedLayer = layer;\n }\n }\n }\n if (clickedLayer) {\n L.DomEvent.fakeStop(e);\n this._fireEvent([clickedLayer], e);\n }\n },\n });\n}\n\n// initialize leaflet-geoman\nL.PM.initialize();\n","// Adapted from https://github.com/Flet/prettier-bytes/\n// Changing 1000 bytes to 1024, so we can keep uppercase KB vs kB\n// ISC License (c) Dan Flettre https://github.com/Flet/prettier-bytes/blob/master/LICENSE\nmodule.exports = function prettierBytes (num) {\n if (typeof num !== 'number' || isNaN(num)) {\n throw new TypeError('Expected a number, got ' + typeof num)\n }\n\n var neg = num < 0\n var units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n\n if (neg) {\n num = -num\n }\n\n if (num < 1) {\n return (neg ? '-' : '') + num + ' B'\n }\n\n var exponent = Math.min(Math.floor(Math.log(num) / Math.log(1024)), units.length - 1)\n num = Number(num / Math.pow(1024, exponent))\n var unit = units[exponent]\n\n if (num >= 10 || num % 1 === 0) {\n // Do not show decimals when the number is two-digit, or if the number has no\n // decimal component.\n return (neg ? '-' : '') + num.toFixed(0) + ' ' + unit\n } else {\n return (neg ? '-' : '') + num.toFixed(1) + ' ' + unit\n }\n}\n","'use strict';\n\nfunction _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === \"function\" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== \"function\") { throw new TypeError(\"Super expression must either be null or a function\"); } if (typeof _cache !== \"undefined\") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf(\"[native code]\") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nvar AuthError = /*#__PURE__*/function (_Error) {\n _inheritsLoose(AuthError, _Error);\n\n function AuthError() {\n var _this;\n\n _this = _Error.call(this, 'Authorization required') || this;\n _this.name = 'AuthError';\n _this.isAuthError = true;\n return _this;\n }\n\n return AuthError;\n}( /*#__PURE__*/_wrapNativeSuper(Error));\n\nmodule.exports = AuthError;","'use strict';\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nvar qsStringify = require('qs-stringify');\n\nvar URL = require('url-parse');\n\nvar RequestClient = require('./RequestClient');\n\nvar tokenStorage = require('./tokenStorage');\n\nvar _getName = function _getName(id) {\n return id.split('-').map(function (s) {\n return s.charAt(0).toUpperCase() + s.slice(1);\n }).join(' ');\n};\n\nmodule.exports = /*#__PURE__*/function (_RequestClient) {\n _inheritsLoose(Provider, _RequestClient);\n\n function Provider(uppy, opts) {\n var _this;\n\n _this = _RequestClient.call(this, uppy, opts) || this;\n _this.provider = opts.provider;\n _this.id = _this.provider;\n _this.name = _this.opts.name || _getName(_this.id);\n _this.pluginId = _this.opts.pluginId;\n _this.tokenKey = \"companion-\" + _this.pluginId + \"-auth-token\";\n _this.companionKeysParams = _this.opts.companionKeysParams;\n _this.preAuthToken = null;\n return _this;\n }\n\n var _proto = Provider.prototype;\n\n _proto.headers = function headers() {\n var _this2 = this;\n\n return Promise.all([_RequestClient.prototype.headers.call(this), this.getAuthToken()]).then(function (_ref) {\n var headers = _ref[0],\n token = _ref[1];\n var authHeaders = {};\n\n if (token) {\n authHeaders['uppy-auth-token'] = token;\n }\n\n if (_this2.companionKeysParams) {\n authHeaders['uppy-credentials-params'] = btoa(JSON.stringify({\n params: _this2.companionKeysParams\n }));\n }\n\n return _extends({}, headers, authHeaders);\n });\n };\n\n _proto.onReceiveResponse = function onReceiveResponse(response) {\n response = _RequestClient.prototype.onReceiveResponse.call(this, response);\n var plugin = this.uppy.getPlugin(this.pluginId);\n var oldAuthenticated = plugin.getPluginState().authenticated;\n var authenticated = oldAuthenticated ? response.status !== 401 : response.status < 400;\n plugin.setPluginState({\n authenticated: authenticated\n });\n return response;\n } // @todo(i.olarewaju) consider whether or not this method should be exposed\n ;\n\n _proto.setAuthToken = function setAuthToken(token) {\n return this.uppy.getPlugin(this.pluginId).storage.setItem(this.tokenKey, token);\n };\n\n _proto.getAuthToken = function getAuthToken() {\n return this.uppy.getPlugin(this.pluginId).storage.getItem(this.tokenKey);\n };\n\n _proto.authUrl = function authUrl(queries) {\n if (queries === void 0) {\n queries = {};\n }\n\n if (this.preAuthToken) {\n queries.uppyPreAuthToken = this.preAuthToken;\n }\n\n var strigifiedQueries = qsStringify(queries);\n strigifiedQueries = strigifiedQueries ? \"?\" + strigifiedQueries : strigifiedQueries;\n return this.hostname + \"/\" + this.id + \"/connect\" + strigifiedQueries;\n };\n\n _proto.fileUrl = function fileUrl(id) {\n return this.hostname + \"/\" + this.id + \"/get/\" + id;\n };\n\n _proto.fetchPreAuthToken = function fetchPreAuthToken() {\n var _this3 = this;\n\n if (!this.companionKeysParams) {\n return Promise.resolve();\n }\n\n return this.post(this.id + \"/preauth/\", {\n params: this.companionKeysParams\n }).then(function (res) {\n _this3.preAuthToken = res.token;\n }).catch(function (err) {\n _this3.uppy.log(\"[CompanionClient] unable to fetch preAuthToken \" + err, 'warning');\n });\n };\n\n _proto.list = function list(directory) {\n return this.get(this.id + \"/list/\" + (directory || ''));\n };\n\n _proto.logout = function logout() {\n var _this4 = this;\n\n return this.get(this.id + \"/logout\").then(function (response) {\n return Promise.all([response, _this4.uppy.getPlugin(_this4.pluginId).storage.removeItem(_this4.tokenKey)]);\n }).then(function (_ref2) {\n var response = _ref2[0];\n return response;\n });\n };\n\n Provider.initPlugin = function initPlugin(plugin, opts, defaultOpts) {\n plugin.type = 'acquirer';\n plugin.files = [];\n\n if (defaultOpts) {\n plugin.opts = _extends({}, defaultOpts, opts);\n }\n\n if (opts.serverUrl || opts.serverPattern) {\n throw new Error('`serverUrl` and `serverPattern` have been renamed to `companionUrl` and `companionAllowedHosts` respectively in the 0.30.5 release. Please consult the docs (for example, https://uppy.io/docs/instagram/ for the Instagram plugin) and use the updated options.`');\n }\n\n if (opts.companionAllowedHosts) {\n var pattern = opts.companionAllowedHosts; // validate companionAllowedHosts param\n\n if (typeof pattern !== 'string' && !Array.isArray(pattern) && !(pattern instanceof RegExp)) {\n throw new TypeError(plugin.id + \": the option \\\"companionAllowedHosts\\\" must be one of string, Array, RegExp\");\n }\n\n plugin.opts.companionAllowedHosts = pattern;\n } else {\n // does not start with https://\n if (/^(?!https?:\\/\\/).*$/i.test(opts.companionUrl)) {\n plugin.opts.companionAllowedHosts = \"https://\" + opts.companionUrl.replace(/^\\/\\//, '');\n } else {\n plugin.opts.companionAllowedHosts = new URL(opts.companionUrl).origin;\n }\n }\n\n plugin.storage = plugin.opts.storage || tokenStorage;\n };\n\n return Provider;\n}(RequestClient);","'use strict';\n\nvar _class, _temp;\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar AuthError = require('./AuthError');\n\nvar fetchWithNetworkError = require('@uppy/utils/lib/fetchWithNetworkError'); // Remove the trailing slash so we can always safely append /xyz.\n\n\nfunction stripSlash(url) {\n return url.replace(/\\/$/, '');\n}\n\nmodule.exports = (_temp = _class = /*#__PURE__*/function () {\n function RequestClient(uppy, opts) {\n this.uppy = uppy;\n this.opts = opts;\n this.onReceiveResponse = this.onReceiveResponse.bind(this);\n this.allowedHeaders = ['accept', 'content-type', 'uppy-auth-token'];\n this.preflightDone = false;\n }\n\n var _proto = RequestClient.prototype;\n\n _proto.headers = function headers() {\n var userHeaders = this.opts.companionHeaders || this.opts.serverHeaders || {};\n return Promise.resolve(_extends({}, this.defaultHeaders, userHeaders));\n };\n\n _proto._getPostResponseFunc = function _getPostResponseFunc(skip) {\n var _this = this;\n\n return function (response) {\n if (!skip) {\n return _this.onReceiveResponse(response);\n }\n\n return response;\n };\n };\n\n _proto.onReceiveResponse = function onReceiveResponse(response) {\n var state = this.uppy.getState();\n var companion = state.companion || {};\n var host = this.opts.companionUrl;\n var headers = response.headers; // Store the self-identified domain name for the Companion instance we just hit.\n\n if (headers.has('i-am') && headers.get('i-am') !== companion[host]) {\n var _extends2;\n\n this.uppy.setState({\n companion: _extends({}, companion, (_extends2 = {}, _extends2[host] = headers.get('i-am'), _extends2))\n });\n }\n\n return response;\n };\n\n _proto._getUrl = function _getUrl(url) {\n if (/^(https?:|)\\/\\//.test(url)) {\n return url;\n }\n\n return this.hostname + \"/\" + url;\n };\n\n _proto._json = function _json(res) {\n if (res.status === 401) {\n throw new AuthError();\n }\n\n if (res.status < 200 || res.status > 300) {\n var errMsg = \"Failed request with status: \" + res.status + \". \" + res.statusText;\n return res.json().then(function (errData) {\n errMsg = errData.message ? errMsg + \" message: \" + errData.message : errMsg;\n errMsg = errData.requestId ? errMsg + \" request-Id: \" + errData.requestId : errMsg;\n throw new Error(errMsg);\n }).catch(function () {\n throw new Error(errMsg);\n });\n }\n\n return res.json();\n };\n\n _proto.preflight = function preflight(path) {\n var _this2 = this;\n\n if (this.preflightDone) {\n return Promise.resolve(this.allowedHeaders.slice());\n }\n\n return fetch(this._getUrl(path), {\n method: 'OPTIONS'\n }).then(function (response) {\n if (response.headers.has('access-control-allow-headers')) {\n _this2.allowedHeaders = response.headers.get('access-control-allow-headers').split(',').map(function (headerName) {\n return headerName.trim().toLowerCase();\n });\n }\n\n _this2.preflightDone = true;\n return _this2.allowedHeaders.slice();\n }).catch(function (err) {\n _this2.uppy.log(\"[CompanionClient] unable to make preflight request \" + err, 'warning');\n\n _this2.preflightDone = true;\n return _this2.allowedHeaders.slice();\n });\n };\n\n _proto.preflightAndHeaders = function preflightAndHeaders(path) {\n var _this3 = this;\n\n return Promise.all([this.preflight(path), this.headers()]).then(function (_ref) {\n var allowedHeaders = _ref[0],\n headers = _ref[1];\n // filter to keep only allowed Headers\n Object.keys(headers).forEach(function (header) {\n if (allowedHeaders.indexOf(header.toLowerCase()) === -1) {\n _this3.uppy.log(\"[CompanionClient] excluding unallowed header \" + header);\n\n delete headers[header];\n }\n });\n return headers;\n });\n };\n\n _proto.get = function get(path, skipPostResponse) {\n var _this4 = this;\n\n return this.preflightAndHeaders(path).then(function (headers) {\n return fetchWithNetworkError(_this4._getUrl(path), {\n method: 'get',\n headers: headers,\n credentials: _this4.opts.companionCookiesRule || 'same-origin'\n });\n }).then(this._getPostResponseFunc(skipPostResponse)).then(function (res) {\n return _this4._json(res);\n }).catch(function (err) {\n if (!err.isAuthError) {\n err.message = \"Could not get \" + _this4._getUrl(path) + \". \" + err.message;\n }\n\n return Promise.reject(err);\n });\n };\n\n _proto.post = function post(path, data, skipPostResponse) {\n var _this5 = this;\n\n return this.preflightAndHeaders(path).then(function (headers) {\n return fetchWithNetworkError(_this5._getUrl(path), {\n method: 'post',\n headers: headers,\n credentials: _this5.opts.companionCookiesRule || 'same-origin',\n body: JSON.stringify(data)\n });\n }).then(this._getPostResponseFunc(skipPostResponse)).then(function (res) {\n return _this5._json(res);\n }).catch(function (err) {\n if (!err.isAuthError) {\n err.message = \"Could not post \" + _this5._getUrl(path) + \". \" + err.message;\n }\n\n return Promise.reject(err);\n });\n };\n\n _proto.delete = function _delete(path, data, skipPostResponse) {\n var _this6 = this;\n\n return this.preflightAndHeaders(path).then(function (headers) {\n return fetchWithNetworkError(_this6.hostname + \"/\" + path, {\n method: 'delete',\n headers: headers,\n credentials: _this6.opts.companionCookiesRule || 'same-origin',\n body: data ? JSON.stringify(data) : null\n });\n }).then(this._getPostResponseFunc(skipPostResponse)).then(function (res) {\n return _this6._json(res);\n }).catch(function (err) {\n if (!err.isAuthError) {\n err.message = \"Could not delete \" + _this6._getUrl(path) + \". \" + err.message;\n }\n\n return Promise.reject(err);\n });\n };\n\n _createClass(RequestClient, [{\n key: \"hostname\",\n get: function get() {\n var _this$uppy$getState = this.uppy.getState(),\n companion = _this$uppy$getState.companion;\n\n var host = this.opts.companionUrl;\n return stripSlash(companion && companion[host] ? companion[host] : host);\n }\n }, {\n key: \"defaultHeaders\",\n get: function get() {\n return {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'Uppy-Versions': \"@uppy/companion-client=\" + RequestClient.VERSION\n };\n }\n }]);\n\n return RequestClient;\n}(), _class.VERSION = \"1.10.2\", _temp);","'use strict';\n\nfunction _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nvar RequestClient = require('./RequestClient');\n\nvar _getName = function _getName(id) {\n return id.split('-').map(function (s) {\n return s.charAt(0).toUpperCase() + s.slice(1);\n }).join(' ');\n};\n\nmodule.exports = /*#__PURE__*/function (_RequestClient) {\n _inheritsLoose(SearchProvider, _RequestClient);\n\n function SearchProvider(uppy, opts) {\n var _this;\n\n _this = _RequestClient.call(this, uppy, opts) || this;\n _this.provider = opts.provider;\n _this.id = _this.provider;\n _this.name = _this.opts.name || _getName(_this.id);\n _this.pluginId = _this.opts.pluginId;\n return _this;\n }\n\n var _proto = SearchProvider.prototype;\n\n _proto.fileUrl = function fileUrl(id) {\n return this.hostname + \"/search/\" + this.id + \"/get/\" + id;\n };\n\n _proto.search = function search(text, queries) {\n queries = queries ? \"&\" + queries : '';\n return this.get(\"search/\" + this.id + \"/list?q=\" + encodeURIComponent(text) + queries);\n };\n\n return SearchProvider;\n}(RequestClient);","var ee = require('namespace-emitter');\n\nmodule.exports = /*#__PURE__*/function () {\n function UppySocket(opts) {\n this.opts = opts;\n this._queued = [];\n this.isOpen = false;\n this.emitter = ee();\n this._handleMessage = this._handleMessage.bind(this);\n this.close = this.close.bind(this);\n this.emit = this.emit.bind(this);\n this.on = this.on.bind(this);\n this.once = this.once.bind(this);\n this.send = this.send.bind(this);\n\n if (!opts || opts.autoOpen !== false) {\n this.open();\n }\n }\n\n var _proto = UppySocket.prototype;\n\n _proto.open = function open() {\n var _this = this;\n\n this.socket = new WebSocket(this.opts.target);\n\n this.socket.onopen = function (e) {\n _this.isOpen = true;\n\n while (_this._queued.length > 0 && _this.isOpen) {\n var first = _this._queued[0];\n\n _this.send(first.action, first.payload);\n\n _this._queued = _this._queued.slice(1);\n }\n };\n\n this.socket.onclose = function (e) {\n _this.isOpen = false;\n };\n\n this.socket.onmessage = this._handleMessage;\n };\n\n _proto.close = function close() {\n if (this.socket) {\n this.socket.close();\n }\n };\n\n _proto.send = function send(action, payload) {\n // attach uuid\n if (!this.isOpen) {\n this._queued.push({\n action: action,\n payload: payload\n });\n\n return;\n }\n\n this.socket.send(JSON.stringify({\n action: action,\n payload: payload\n }));\n };\n\n _proto.on = function on(action, handler) {\n this.emitter.on(action, handler);\n };\n\n _proto.emit = function emit(action, payload) {\n this.emitter.emit(action, payload);\n };\n\n _proto.once = function once(action, handler) {\n this.emitter.once(action, handler);\n };\n\n _proto._handleMessage = function _handleMessage(e) {\n try {\n var message = JSON.parse(e.data);\n this.emit(message.action, message.payload);\n } catch (err) {\n console.log(err);\n }\n };\n\n return UppySocket;\n}();","'use strict';\n/**\n * Manages communications with Companion\n */\n\nvar RequestClient = require('./RequestClient');\n\nvar Provider = require('./Provider');\n\nvar SearchProvider = require('./SearchProvider');\n\nvar Socket = require('./Socket');\n\nmodule.exports = {\n RequestClient: RequestClient,\n Provider: Provider,\n SearchProvider: SearchProvider,\n Socket: Socket\n};","'use strict';\n/**\n * This module serves as an Async wrapper for LocalStorage\n */\n\nmodule.exports.setItem = function (key, value) {\n return new Promise(function (resolve) {\n localStorage.setItem(key, value);\n resolve();\n });\n};\n\nmodule.exports.getItem = function (key) {\n return Promise.resolve(localStorage.getItem(key));\n};\n\nmodule.exports.removeItem = function (key) {\n return new Promise(function (resolve) {\n localStorage.removeItem(key);\n resolve();\n });\n};","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nvar preact = require('preact');\n\nvar findDOMElement = require('@uppy/utils/lib/findDOMElement');\n/**\n * Defer a frequent call to the microtask queue.\n */\n\n\nfunction debounce(fn) {\n var calling = null;\n var latestArgs = null;\n return function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n latestArgs = args;\n\n if (!calling) {\n calling = Promise.resolve().then(function () {\n calling = null; // At this point `args` may be different from the most\n // recent state, if multiple calls happened since this task\n // was queued. So we use the `latestArgs`, which definitely\n // is the most recent call.\n\n return fn.apply(void 0, latestArgs);\n });\n }\n\n return calling;\n };\n}\n/**\n * Boilerplate that all Plugins share - and should not be used\n * directly. It also shows which methods final plugins should implement/override,\n * this deciding on structure.\n *\n * @param {object} main Uppy core object\n * @param {object} object with plugin options\n * @returns {Array|string} files or success/fail message\n */\n\n\nmodule.exports = /*#__PURE__*/function () {\n function Plugin(uppy, opts) {\n this.uppy = uppy;\n this.opts = opts || {};\n this.update = this.update.bind(this);\n this.mount = this.mount.bind(this);\n this.install = this.install.bind(this);\n this.uninstall = this.uninstall.bind(this);\n }\n\n var _proto = Plugin.prototype;\n\n _proto.getPluginState = function getPluginState() {\n var _this$uppy$getState = this.uppy.getState(),\n plugins = _this$uppy$getState.plugins;\n\n return plugins[this.id] || {};\n };\n\n _proto.setPluginState = function setPluginState(update) {\n var _extends2;\n\n var _this$uppy$getState2 = this.uppy.getState(),\n plugins = _this$uppy$getState2.plugins;\n\n this.uppy.setState({\n plugins: _extends({}, plugins, (_extends2 = {}, _extends2[this.id] = _extends({}, plugins[this.id], update), _extends2))\n });\n };\n\n _proto.setOptions = function setOptions(newOpts) {\n this.opts = _extends({}, this.opts, newOpts);\n this.setPluginState(); // so that UI re-renders with new options\n };\n\n _proto.update = function update(state) {\n if (typeof this.el === 'undefined') {\n return;\n }\n\n if (this._updateUI) {\n this._updateUI(state);\n }\n } // Called after every state update, after everything's mounted. Debounced.\n ;\n\n _proto.afterUpdate = function afterUpdate() {}\n /**\n * Called when plugin is mounted, whether in DOM or into another plugin.\n * Needed because sometimes plugins are mounted separately/after `install`,\n * so this.el and this.parent might not be available in `install`.\n * This is the case with @uppy/react plugins, for example.\n */\n ;\n\n _proto.onMount = function onMount() {}\n /**\n * Check if supplied `target` is a DOM element or an `object`.\n * If it’s an object — target is a plugin, and we search `plugins`\n * for a plugin with same name and return its target.\n *\n * @param {string|object} target\n *\n */\n ;\n\n _proto.mount = function mount(target, plugin) {\n var _this = this;\n\n var callerPluginName = plugin.id;\n var targetElement = findDOMElement(target);\n\n if (targetElement) {\n this.isTargetDOMEl = true; // API for plugins that require a synchronous rerender.\n\n this.rerender = function (state) {\n // plugin could be removed, but this.rerender is debounced below,\n // so it could still be called even after uppy.removePlugin or uppy.close\n // hence the check\n if (!_this.uppy.getPlugin(_this.id)) return;\n _this.el = preact.render(_this.render(state), targetElement, _this.el);\n\n _this.afterUpdate();\n };\n\n this._updateUI = debounce(this.rerender);\n this.uppy.log(\"Installing \" + callerPluginName + \" to a DOM element '\" + target + \"'\"); // clear everything inside the target container\n\n if (this.opts.replaceTargetContent) {\n targetElement.innerHTML = '';\n }\n\n this.el = preact.render(this.render(this.uppy.getState()), targetElement);\n this.onMount();\n return this.el;\n }\n\n var targetPlugin;\n\n if (typeof target === 'object' && target instanceof Plugin) {\n // Targeting a plugin *instance*\n targetPlugin = target;\n } else if (typeof target === 'function') {\n // Targeting a plugin type\n var Target = target; // Find the target plugin instance.\n\n this.uppy.iteratePlugins(function (plugin) {\n if (plugin instanceof Target) {\n targetPlugin = plugin;\n return false;\n }\n });\n }\n\n if (targetPlugin) {\n this.uppy.log(\"Installing \" + callerPluginName + \" to \" + targetPlugin.id);\n this.parent = targetPlugin;\n this.el = targetPlugin.addTarget(plugin);\n this.onMount();\n return this.el;\n }\n\n this.uppy.log(\"Not installing \" + callerPluginName);\n var message = \"Invalid target option given to \" + callerPluginName + \".\";\n\n if (typeof target === 'function') {\n message += ' The given target is not a Plugin class. ' + 'Please check that you\\'re not specifying a React Component instead of a plugin. ' + 'If you are using @uppy/* packages directly, make sure you have only 1 version of @uppy/core installed: ' + 'run `npm ls @uppy/core` on the command line and verify that all the versions match and are deduped correctly.';\n } else {\n message += 'If you meant to target an HTML element, please make sure that the element exists. ' + 'Check that the