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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions src/components/LMap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,9 @@ function useOptions() {

const fitBoundsOptions = computed((): FitBoundsOptions => {
const result: FitBoundsOptions = zoomPanOptions.value
if (props.padding) {
result.padding = props.padding
}
if (props.paddingTopLeft) {
result.paddingTopLeft = props.paddingTopLeft
}
if (props.paddingBottomRight) {
result.paddingBottomRight = props.paddingBottomRight
}
result.padding = props.padding ? props.padding : undefined
result.paddingTopLeft = props.paddingTopLeft ? props.paddingTopLeft : undefined
result.paddingBottomRight = props.paddingBottomRight ? props.paddingBottomRight : undefined
return result
})
return { zoomPanOptions, fitBoundsOptions }
Expand Down Expand Up @@ -245,13 +239,13 @@ function useMethods() {
const boundsChanged = !oldBounds.equals(newBounds, 0) // set maxMargin to 0 - check exact equals
if (boundsChanged) {
lastSetBounds.value = newBounds
leafletObject.value!.fitBounds(newBounds)
fitBounds(newBounds)
}
}

const lastSetCenter = ref<LatLng>()
function setCenter(center: [number, number]) {
if (center == null) {
if (!center) {
return
}
const newCenter = new LatLng(...center)
Expand Down
13 changes: 7 additions & 6 deletions src/components/LMarker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ import {
provide,
ref,
useAttrs,
useSlots,
useSlots
} from 'vue'
import {
assertInject,
bindEventHandlers,
cancelDebounces,
isFunction,
propsBinder,
remapEvents,
remapEvents
} from '@/utils'
import {
AddLayerInjection,
CanSetParentHtmlInjection,
SetIconInjection,
SetParentHtmlInjection,
SetParentHtmlInjection
} from '@/types/injectionKeys'
import { DivIcon, Icon, type LeafletEventHandlerFnMap, Marker } from 'leaflet'
import { debounce } from 'ts-debounce'
Expand All @@ -30,7 +30,7 @@ import {
type MarkerProps,
markerPropsDefaults,
setupMarker,
shouldBlankIcon,
shouldBlankIcon
} from '@/functions/marker'

/**
Expand Down Expand Up @@ -67,12 +67,13 @@ function useMarker() {
function useEvents() {
const { listeners } = remapEvents(useAttrs())
const eventHandlers: LeafletEventHandlerFnMap = {
move: debounce(methods.latLngSync),
move: debounce(methods.latLngSync)
}
return { listeners, eventHandlers }
}

onMounted(async () => {
// TODO this causes in vitest: [Vue warn]: Slot "default" invoked outside of the render function: this will not track dependencies used in the slot. Invoke the slot function inside the render function instead.
if (shouldBlankIcon(useSlots())) {
options.icon = new DivIcon({ className: '' })
}
Expand All @@ -84,7 +85,7 @@ function useMarker() {
addLayer({
...props,
...methods,
leafletObject: leafletObject.value,
leafletObject: leafletObject.value
})
ready.value = true
nextTick(() => emit('ready', leafletObject.value!))
Expand Down
2 changes: 1 addition & 1 deletion src/components/LPopup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function usePopup() {
propsBinder(methods, leafletObject.value, props)
const { listeners } = remapEvents(useAttrs())
leafletObject.value.on(listeners)
leafletObject.value.setContent(props.content || root.value || '')
leafletObject.value.setContent(props.content || root.value!)
bindPopup(leafletObject.value)
nextTick(() => emit('ready', leafletObject.value!))
})
Expand Down
5 changes: 4 additions & 1 deletion src/components/LRectangle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ function useRectangle() {
const { options, methods } = setupRectangle(props, leafletObject, emit)

onMounted(async () => {
if (!props.bounds && !props.latLngs) {
throw new Error("Specify bounds or LatLngs for a valid rectangle.")
}
const bounds = props.bounds
? new LatLngBounds(props.bounds)
: new LatLngBounds(props.latLngs || [])
: new LatLngBounds(props.latLngs!)
leafletObject.value = markRaw<Rectangle>(new Rectangle(bounds, options))

const { listeners } = remapEvents(useAttrs())
Expand Down
2 changes: 1 addition & 1 deletion src/components/LTooltip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function useTooltip() {
propsBinder(methods, leafletObject.value, props)
const { listeners } = remapEvents(useAttrs())
leafletObject.value.on(listeners)
leafletObject.value.setContent(props.content || root.value || '')
leafletObject.value.setContent(props.content || root.value!)
bindTooltip(leafletObject.value)
nextTick(() => emit('ready', leafletObject.value!))
})
Expand Down
10 changes: 10 additions & 0 deletions src/functions/geoJSON.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,22 @@ export const setupGeoJSON = (
setOptionsStyle(newVal: PathOptions | StyleFunction) {
leafletRef.value?.setStyle(newVal)
},
/* v8 ignore start - unreachable code, marked for removal */
/**
* TODO remove unused code
* @deprecated unreachable code ?
*/
getGeoJSONData() {
return leafletRef.value?.toGeoJSON()
},
/**
* TODO remove unused code
* @deprecated unreachable code ?
*/
getBounds() {
return leafletRef.value?.getBounds()
},
/* v8 ignore end */
}

return { options, methods }
Expand Down
6 changes: 6 additions & 0 deletions src/functions/gridLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,15 @@ export const setupGridLayer = <T extends GridLayer>(

const methods = {
...layerMethods,
/* v8 ignore start - unreachable code, marked for removal */
/**
* TODO remove unused code
* @deprecated unreachable code ?
*/
setTileComponent() {
leafletRef.value?.redraw()
},
/* v8 ignore end */
}

onUnmounted(() => {
Expand Down
12 changes: 11 additions & 1 deletion src/functions/imageOverlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,37 +107,47 @@ export const setupImageOverlay = (
setBounds(bounds: LatLngBounds) {
return leafletRef.value?.setBounds(bounds)
},
/* v8 ignore start - unreachable code, marked for removal */
/**
* Get the bounds that this ImageOverlay covers
* TODO remove unused code
* @deprecated unreachable code ?
*/
getBounds(): LatLngBounds | undefined {
return leafletRef.value?.getBounds()
},
/**
* Returns the instance of HTMLImageElement used by this overlay.
* TODO remove unused code
* @deprecated unreachable code ?
*/
getElement(): HTMLElement | undefined {
return leafletRef.value?.getElement()
},
/**
* Brings the layer to the top of all overlays.
* TODO remove unused code
* @deprecated unreachable code ?
*/
bringToFront() {
return leafletRef.value?.bringToFront()
},
/**
* Brings the layer to the bottom of all overlays.
* TODO remove unused code
* @deprecated unreachable code ?
*/
bringToBack() {
return leafletRef.value?.bringToBack()
},
/* v8 ignore end */
/**
* Changes the zIndex of the image overlay.
* @param {number} zIndex
*/
setZIndex(zIndex: number) {
return leafletRef.value?.setZIndex(zIndex)
},
}
}

return { options, methods }
Expand Down
4 changes: 2 additions & 2 deletions src/functions/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ export const setupLayer = <T extends Layer>(
function updateVisibleProp(value: boolean) {
emit('update:visible', value)
}
const addThisLayer = () => addLayer({ leafletObject: leafletRef.value, updateVisibleProp })
const addThisLayer = () => addLayer({ leafletObject: leafletRef.value, updateVisibleProp, layerType: props.layerType })
const removeThisLayer = () =>
removeLayer({ leafletObject: leafletRef.value, updateVisibleProp })
removeLayer({ leafletObject: leafletRef.value, updateVisibleProp, layerType: props.layerType })

const methods = {
...componentMethods,
Expand Down
6 changes: 3 additions & 3 deletions src/functions/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ export interface MapProps extends ComponentProps<MapOptions> {
*/
maxZoom?: number
/**
* The paddingBottomRight of the map
* The paddingBottomRight of the map. Applies only when LMap.fitBounds is called.
* @reactive native
*/
paddingBottomRight?: PointExpression
/**
* The paddingTopLeft of the map
* The paddingTopLeft of the map. Applies only when LMap.fitBounds is called.
* @reactive native
*/
paddingTopLeft?: PointExpression
/**
* The padding of the map
* The padding of the map. Applies only when LMap.fitBounds is called.
* @reactive native
*/
padding?: PointExpression
Expand Down
6 changes: 6 additions & 0 deletions src/functions/polygon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,15 @@ export const setupPolygon = (

const methods = {
...polylineMethods,
/* v8 ignore start - unreachable code, marked for removal */
/**
* TODO remove unused code
* @deprecated unreachable code ?
*/
toGeoJSON(precision: number | false) {
return leafletRef.value?.toGeoJSON(precision)
}
/* v8 ignore stop */
}

return { options, methods }
Expand Down
6 changes: 6 additions & 0 deletions src/functions/polyline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,15 @@ export const setupPolyline = (
setNoClip(noClip: boolean) {
leafletRef.value?.setStyle({ noClip } as PolylineOptions) // TYPES remove cast
},
/* v8 ignore start - unreachable code, marked for removal */
/**
* TODO remove unused code
* @deprecated unreachable code ?
*/
addLatLng(latLng: LatLngExpression) {
leafletRef.value?.addLatLng(latLng)
}
/* v8 ignore stop */
}

return { options, methods }
Expand Down
2 changes: 1 addition & 1 deletion src/lib.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './components';
export * from './components'
2 changes: 1 addition & 1 deletion src/types/interfaces/IControlDefinition.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Control } from 'leaflet'
import type { Control } from 'leaflet'
import type { ILayerDefinition } from '@/types/interfaces/ILayerDefinition.ts'

export interface IControlDefinition<T extends Control = Control> {
Expand Down
2 changes: 1 addition & 1 deletion src/types/interfaces/ILayerDefinition.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { LayerType } from '../enums/LayerType'
import { type Layer } from 'leaflet'
import type { Layer } from 'leaflet'

export interface ILayerDefinition<T extends Layer = Layer> {
name?: string
Expand Down
4 changes: 2 additions & 2 deletions src/types/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from "./IControlDefinition";
export * from "./ILayerDefinition";
export * from './IControlDefinition'
export * from './ILayerDefinition'
9 changes: 7 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ export const isFunction = (x: unknown) => typeof x === 'function'
* @param methods
* @param leafletElement
* @param props the relevant Vue component props
* @return array of unbounded prop keys
*/
export const propsBinder = (methods: Readonly<FunctionMap>, leafletElement: PropertyMap, props: Readonly<PropertyMap>) => {
//propsBinderScope.run(() => {
const unboundedProps: string[] = []
for (const key in props) {
/* v8 ignore next */
if (vueLeafletConfig.experimental.skipUndefinedProps && props[key] === undefined) continue
const setMethodName = 'set' + capitalizeFirstLetter(key)
const setterMethod = methods[setMethodName]
Expand All @@ -82,12 +85,13 @@ export const propsBinder = (methods: Readonly<FunctionMap>, leafletElement: Prop
leafletElement[setMethodName](newVal)
}
)
} else if (key !== 'options' && import.meta.env.vitest) {
console.warn(`No setter for '${key}'`)
} else if (key !== 'options') {
unboundedProps.push(key)
}
}
//})
// propsBinderScope.log('Active watchers:', devScope.effects.length)
return unboundedProps
}

export const propsToLeafletOptions = <T extends object>(
Expand Down Expand Up @@ -137,6 +141,7 @@ export const remapEvents = (contextAttrs: Record<string, unknown>): ListenersAnd
// TODO It seems like Icon.Default is now IconDefault in leaflet v2
export const resetWebpackIcon = async (Icon) => {
//export const resetWebpackIcon = async (Icon: typeof IconDefault) => {
/* v8 ignore next */
if (!vueLeafletConfig.experimental.useResetWebpackIcon) return
const modules = await Promise.all([
import('leaflet/dist/images/marker-icon-2x.png'),
Expand Down
23 changes: 23 additions & 0 deletions tests/exports/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
### 📦 Export Integrity Tests

This folder contains tests that validate the structure and accessibility of public exports — such as those defined in
`lib.ts` or `components/index.ts`. These tests ensure that all components, utilities, and modules are properly exposed
and can be imported without error.

> ⚠️ **Important note on coverage:**
> Code coverage tools may report artificially high coverage when running export tests. This happens because files are
> marked as "covered" simply by being imported — even if none of their internal logic is executed. As a result, components
> may appear to have 100% coverage despite not being functionally tested.

### ✅ For accurate coverage reporting

To ensure meaningful coverage metrics, run your **unit and integration tests separately** and **exclude export-only
tests** from coverage analysis. You can do this by updating your `vitest.config.ts` like so:

```ts
coverage: {
exclude: ['tests/exports/**']
}
```

This keeps your coverage report focused on actual logic execution, not just import validation.
31 changes: 31 additions & 0 deletions tests/exports/lib.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as lib from '../../src/lib'
import { describe, expect, it } from 'vitest'

describe('lib', () => {
it('should export the components', () => {
expect(lib.LCircle).toBeDefined()
expect(lib.LCircleMarker).toBeDefined()
expect(lib.LControl).toBeDefined()
expect(lib.LControlAttribution).toBeDefined()
expect(lib.LControlLayers).toBeDefined()
expect(lib.LControlScale).toBeDefined()
expect(lib.LControlZoom).toBeDefined()
expect(lib.LFeatureGroup).toBeDefined()
expect(lib.LGeoJson).toBeDefined()
expect(lib.LGridLayer).toBeDefined()
expect(lib.LIcon).toBeDefined()
expect(lib.LImageOverlay).toBeDefined()
expect(lib.LLayerGroup).toBeDefined()
expect(lib.LMap).toBeDefined()
expect(lib.LMarker).toBeDefined()
expect(lib.LPolygon).toBeDefined()
expect(lib.LPolyline).toBeDefined()
expect(lib.LPopup).toBeDefined()
expect(lib.LRectangle).toBeDefined()
expect(lib.LSVGOverlay).toBeDefined()
expect(lib.LTileLayer).toBeDefined()
expect(lib.LTooltip).toBeDefined()
expect(lib.LVideoOverlay).toBeDefined()
expect(lib.LWmsTileLayer).toBeDefined()
})
})
Loading