foliplus 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- foliplus/Fullscreen.py +58 -0
- foliplus/HeatmapControl.py +118 -0
- foliplus/LayerControl.py +77 -0
- foliplus/MapSearch.py +49 -0
- foliplus/MeasureControl.py +57 -0
- foliplus/ScaleControl.py +48 -0
- foliplus/__init__.py +17 -0
- foliplus/_cdn.py +16 -0
- foliplus/_typing.py +3 -0
- foliplus/base.py +104 -0
- foliplus/css/HeatmapControl.css +391 -0
- foliplus/css/LayerControl.css +232 -0
- foliplus/css/MapSearch.css +100 -0
- foliplus/css/MeasureControl.css +71 -0
- foliplus/css/ScaleControl.css +33 -0
- foliplus/css/common.css +222 -0
- foliplus/css/panel.css +180 -0
- foliplus/js/Fullscreen.js +87 -0
- foliplus/js/HeatmapControl.js +953 -0
- foliplus/js/LayerControl.js +754 -0
- foliplus/js/MapSearch.js +192 -0
- foliplus/js/MeasureControl.js +975 -0
- foliplus/js/ScaleControl.js +28 -0
- foliplus/js/runtime.js +414 -0
- foliplus/locale/__init__.py +208 -0
- foliplus/locale/en.json +75 -0
- foliplus/locale/zh.json +75 -0
- foliplus-0.1.0.dist-info/METADATA +45 -0
- foliplus-0.1.0.dist-info/RECORD +32 -0
- foliplus-0.1.0.dist-info/WHEEL +5 -0
- foliplus-0.1.0.dist-info/licenses/LICENSE +21 -0
- foliplus-0.1.0.dist-info/top_level.txt +1 -0
foliplus/Fullscreen.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from ._cdn import LEAFLET_FULLSCREEN
|
|
4
|
+
from ._typing import Position
|
|
5
|
+
from .base import BaseControl
|
|
6
|
+
from .locale import LocaleConfig
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Fullscreen(BaseControl):
|
|
10
|
+
"""Fullscreen control that hides other map components when entering fullscreen.
|
|
11
|
+
|
|
12
|
+
When toggling fullscreen, other controls (HeatmapControl, LayerControl, ScaleControl
|
|
13
|
+
, MapSearch, MeasureControl, etc.), inside ``.leaflet-control-container`` are
|
|
14
|
+
automatically hidden/shown for a cleaner view.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
position : str, default "bottomright"
|
|
19
|
+
One of ``"topleft"``, ``"topright"``, ``"bottomleft"``, ``"bottomright"``.
|
|
20
|
+
|
|
21
|
+
hide_self : bool, default True
|
|
22
|
+
Whether to hide the fullscreen button itself after entering fullscreen.
|
|
23
|
+
Users can exit via the ``Esc`` key.
|
|
24
|
+
|
|
25
|
+
locale : str or LocaleConfig, optional
|
|
26
|
+
Language code (``"en"``, ``"zh"``) or a :class:`LocaleConfig` instance.
|
|
27
|
+
Defaults to auto-detection, falling back to English.
|
|
28
|
+
|
|
29
|
+
Examples
|
|
30
|
+
--------
|
|
31
|
+
>>> import folium
|
|
32
|
+
>>> from foliplus import Fullscreen
|
|
33
|
+
>>> m = folium.Map()
|
|
34
|
+
>>> Fullscreen().add_to(m)
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
default_js = [
|
|
38
|
+
(
|
|
39
|
+
"Control.Fullscreen.js",
|
|
40
|
+
f"https://cdn.jsdelivr.net/npm/leaflet.fullscreen@{LEAFLET_FULLSCREEN}/Control.FullScreen.min.js",
|
|
41
|
+
)
|
|
42
|
+
]
|
|
43
|
+
default_css = [
|
|
44
|
+
(
|
|
45
|
+
"Control.FullScreen.css",
|
|
46
|
+
f"https://cdn.jsdelivr.net/npm/leaflet.fullscreen@{LEAFLET_FULLSCREEN}/Control.FullScreen.css",
|
|
47
|
+
)
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
def __init__(
|
|
51
|
+
self,
|
|
52
|
+
position: Position = "bottomright",
|
|
53
|
+
hide_self: bool = True,
|
|
54
|
+
locale: str | LocaleConfig | None = None,
|
|
55
|
+
):
|
|
56
|
+
super().__init__(position=position, locale=locale)
|
|
57
|
+
self.hide_self = hide_self
|
|
58
|
+
self._template = self._get_template(js_file="Fullscreen.js")
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from ._cdn import CHROMA_JS, H3_JS, SIMPLE_STATISTICS
|
|
6
|
+
from ._typing import Position
|
|
7
|
+
from .base import BaseControl
|
|
8
|
+
from .locale import LocaleConfig
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class HeatmapControl(BaseControl):
|
|
12
|
+
"""H3 hexbin aggregation heatmap control.
|
|
13
|
+
|
|
14
|
+
Auto-discovers point layers (`Marker` / `CircleMarker` / `GeoJSON` Point) and
|
|
15
|
+
aggregates them into H3 hexagons in real-time via h3-js. Resolution auto-adjusts
|
|
16
|
+
with zoom.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
position : str, default "topleft"
|
|
21
|
+
One of ``"topleft"``, ``"topright"``, ``"bottomleft"``, ``"bottomright"``.
|
|
22
|
+
|
|
23
|
+
color_scheme : str, default "Greens"
|
|
24
|
+
Default color scheme name. Supports chroma.js / ColorBrewer palettes: ``Blues``,
|
|
25
|
+
``Greens``, ``Reds``, ``Oranges``, ``Purples``, ``YlOrRd``, ``Viridis``.
|
|
26
|
+
|
|
27
|
+
method : Literal["jenks", "quantile", "equal", "heads"], default "jenks"
|
|
28
|
+
Default classification method.
|
|
29
|
+
|
|
30
|
+
n_classes : int, default 6
|
|
31
|
+
Number of classification classes, range 2-9.
|
|
32
|
+
|
|
33
|
+
agg : Literal["count", "sum", "avg", "min", "max"], default "count"
|
|
34
|
+
Default aggregation method.
|
|
35
|
+
|
|
36
|
+
schemes : list[str], optional
|
|
37
|
+
List of available color scheme names. Can include custom hex values like
|
|
38
|
+
``["#f00", "#0f0", "#00f"]``.
|
|
39
|
+
|
|
40
|
+
style : dict, optional
|
|
41
|
+
Grid style overrides. Supported keys:
|
|
42
|
+
- ``border_weight`` (float, default 1.5): border width
|
|
43
|
+
- ``border_color`` (str, default "#333333"): border color
|
|
44
|
+
- ``fill_opacity`` (float, default 0.7): fill opacity
|
|
45
|
+
- ``border_opacity`` (float, default 0.9): border opacity
|
|
46
|
+
- ``label_show`` (bool, default True): show aggregated value at hex center
|
|
47
|
+
- ``label_size`` (int, default 11): label font size
|
|
48
|
+
- ``label_color`` (str, default "#fff"): label color
|
|
49
|
+
- ``label_format`` (str, default "auto"): number format —
|
|
50
|
+
``"auto"`` (10K/1K suffix), ``"int"``, ``"comma"`` (thousands separator)
|
|
51
|
+
|
|
52
|
+
locale : str or LocaleConfig, optional
|
|
53
|
+
Language code (``"en"``, ``"zh"``) or a :class:`LocaleConfig` instance.
|
|
54
|
+
Defaults to auto-detection, falling back to English.
|
|
55
|
+
|
|
56
|
+
Examples
|
|
57
|
+
--------
|
|
58
|
+
>>> import folium
|
|
59
|
+
>>> from foliplus import HeatmapControl
|
|
60
|
+
>>> m = folium.Map()
|
|
61
|
+
>>> HeatmapControl().add_to(m)
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
default_js = [
|
|
65
|
+
("h3-js", f"https://cdn.jsdelivr.net/npm/h3-js@{H3_JS}/dist/h3-js.umd.js"),
|
|
66
|
+
(
|
|
67
|
+
"simple-statistics",
|
|
68
|
+
f"https://cdn.jsdelivr.net/npm/simple-statistics@{SIMPLE_STATISTICS}/dist/simple-statistics.min.js",
|
|
69
|
+
),
|
|
70
|
+
(
|
|
71
|
+
"chroma-js",
|
|
72
|
+
f"https://cdn.jsdelivr.net/npm/chroma-js@{CHROMA_JS}/chroma.min.js",
|
|
73
|
+
),
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
def __init__(
|
|
77
|
+
self,
|
|
78
|
+
position: Position = "topleft",
|
|
79
|
+
color_scheme: str = "Greens",
|
|
80
|
+
method: Literal["jenks", "quantile", "equal", "heads"] = "jenks",
|
|
81
|
+
n_classes: int = 6,
|
|
82
|
+
agg: Literal["count", "sum", "avg", "min", "max"] = "count",
|
|
83
|
+
schemes: list[str] | None = None,
|
|
84
|
+
style: dict | None = None,
|
|
85
|
+
locale: str | LocaleConfig | None = None,
|
|
86
|
+
):
|
|
87
|
+
super().__init__(position=position, locale=locale)
|
|
88
|
+
self._template = self._get_template(
|
|
89
|
+
js_file="HeatmapControl.js", css_file="HeatmapControl.css", use_panel=True
|
|
90
|
+
)
|
|
91
|
+
self.color_scheme = color_scheme
|
|
92
|
+
self.method = method
|
|
93
|
+
self.n_classes = n_classes
|
|
94
|
+
self.agg = agg
|
|
95
|
+
self.schemes = schemes or [
|
|
96
|
+
"Blues",
|
|
97
|
+
"Greens",
|
|
98
|
+
"Reds",
|
|
99
|
+
"Oranges",
|
|
100
|
+
"Purples",
|
|
101
|
+
"YlOrRd",
|
|
102
|
+
"Viridis",
|
|
103
|
+
]
|
|
104
|
+
self.style = {
|
|
105
|
+
"border_weight": 1.5,
|
|
106
|
+
"border_color": "#333333",
|
|
107
|
+
"fill_opacity": 0.7,
|
|
108
|
+
"border_opacity": 0.9,
|
|
109
|
+
"label_show": True,
|
|
110
|
+
"label_size": 11,
|
|
111
|
+
"label_color": "#fff",
|
|
112
|
+
"label_format": "auto",
|
|
113
|
+
} | (style or {})
|
|
114
|
+
|
|
115
|
+
# CDN versions for JS dynamic loader
|
|
116
|
+
self._h3_version = H3_JS
|
|
117
|
+
self._ss_version = SIMPLE_STATISTICS
|
|
118
|
+
self._chroma_version = CHROMA_JS
|
foliplus/LayerControl.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections import OrderedDict
|
|
4
|
+
|
|
5
|
+
from folium.map import Layer
|
|
6
|
+
|
|
7
|
+
from ._typing import Position
|
|
8
|
+
from .base import BaseControl
|
|
9
|
+
from .locale import LocaleConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class LayerControl(BaseControl):
|
|
13
|
+
"""Layer control with geometry-type icons, drag-and-drop order, and a collapsible
|
|
14
|
+
panel.
|
|
15
|
+
|
|
16
|
+
Replaces Folium's default layer control with:
|
|
17
|
+
- 📐 Geometry-type icons for quick layer identification.
|
|
18
|
+
- 🔀 Drag-and-drop reordering, synced to Leaflet render order.
|
|
19
|
+
- ✅ Multi-select checkboxes with z-index stacking.
|
|
20
|
+
- 🎨 Color picker to replace base maps with a solid background color.
|
|
21
|
+
- 📂 Collapsible panel consistent with other foliplus controls.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
position : str, default "topleft"
|
|
26
|
+
One of ``"topleft"``, ``"topright"``, ``"bottomleft"``, ``"bottomright"``.
|
|
27
|
+
|
|
28
|
+
locale : str or LocaleConfig, optional
|
|
29
|
+
Language code (``"en"``, ``"zh"``) or a :class:`LocaleConfig` instance.
|
|
30
|
+
Defaults to auto-detection, falling back to English.
|
|
31
|
+
|
|
32
|
+
Notes
|
|
33
|
+
-----
|
|
34
|
+
Layer identification relies on ``map._layers`` and the ``window`` global variable at
|
|
35
|
+
runtime. The initial layer list is collected during rendering by traversing the
|
|
36
|
+
parent map's children.
|
|
37
|
+
|
|
38
|
+
Examples
|
|
39
|
+
--------
|
|
40
|
+
>>> import folium
|
|
41
|
+
>>> from foliplus import LayerControl
|
|
42
|
+
>>> m = folium.Map()
|
|
43
|
+
>>> LayerControl().add_to(m)
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(
|
|
47
|
+
self,
|
|
48
|
+
position: Position = "topleft",
|
|
49
|
+
locale: str | LocaleConfig | None = None,
|
|
50
|
+
):
|
|
51
|
+
super().__init__(position=position, locale=locale)
|
|
52
|
+
self.base_layers: OrderedDict[str, str] = OrderedDict()
|
|
53
|
+
self.overlays: OrderedDict[str, str] = OrderedDict()
|
|
54
|
+
self._template = self._get_template(
|
|
55
|
+
js_file="LayerControl.js", css_file="LayerControl.css", use_panel=True
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def render(self, **kwargs):
|
|
59
|
+
"""Collect layers from the parent map before rendering.
|
|
60
|
+
|
|
61
|
+
Traverses the parent map's ``_children`` to find ``Layer`` instances, then
|
|
62
|
+
populates ``self.base_layers`` and ``self.overlays`` according to each layer's
|
|
63
|
+
``overlay`` flag.
|
|
64
|
+
"""
|
|
65
|
+
self.base_layers.clear()
|
|
66
|
+
self.overlays.clear()
|
|
67
|
+
for item in self._parent._children.values():
|
|
68
|
+
if not isinstance(item, Layer) or not item.control:
|
|
69
|
+
continue
|
|
70
|
+
|
|
71
|
+
key = item.layer_name
|
|
72
|
+
if not item.overlay:
|
|
73
|
+
self.base_layers[key] = item.get_name()
|
|
74
|
+
else:
|
|
75
|
+
self.overlays[key] = item.get_name()
|
|
76
|
+
|
|
77
|
+
super().render(**kwargs)
|
foliplus/MapSearch.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from ._typing import Position
|
|
4
|
+
from .base import BaseControl
|
|
5
|
+
from .locale import LocaleConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MapSearch(BaseControl):
|
|
9
|
+
"""Map search control with coordinate and address lookup modes.
|
|
10
|
+
|
|
11
|
+
Adds a collapsible search box to the map supporting two modes:
|
|
12
|
+
|
|
13
|
+
- 📍 **Coordinate search** (default): enter latitude/longitude to fly to and place a
|
|
14
|
+
marker.
|
|
15
|
+
- 🌐 **Address search**: enter a keyword and geocode via Nominatim.
|
|
16
|
+
|
|
17
|
+
Switch between modes via the tool button inside the expanded panel.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
zoom : int, default 15
|
|
22
|
+
Zoom level after coordinate search. Typically 1-18.
|
|
23
|
+
|
|
24
|
+
position : str, default "topleft"
|
|
25
|
+
One of ``"topleft"``, ``"topright"``, ``"bottomleft"``, ``"bottomright"``.
|
|
26
|
+
|
|
27
|
+
locale : str or LocaleConfig, optional
|
|
28
|
+
Language code (``"en"``, ``"zh"``) or a :class:`LocaleConfig` instance.
|
|
29
|
+
Defaults to auto-detection, falling back to English.
|
|
30
|
+
|
|
31
|
+
Examples
|
|
32
|
+
--------
|
|
33
|
+
>>> import folium
|
|
34
|
+
>>> from foliplus import MapSearch
|
|
35
|
+
>>> m = folium.Map()
|
|
36
|
+
>>> MapSearch().add_to(m)
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
zoom: int = 15,
|
|
42
|
+
position: Position = "topleft",
|
|
43
|
+
locale: str | LocaleConfig | None = None,
|
|
44
|
+
):
|
|
45
|
+
super().__init__(position=position, locale=locale)
|
|
46
|
+
self.zoom = zoom
|
|
47
|
+
self._template = self._get_template(
|
|
48
|
+
js_file="MapSearch.js", css_file="MapSearch.css"
|
|
49
|
+
)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from ._cdn import GCOORD
|
|
4
|
+
from ._typing import Position
|
|
5
|
+
from .base import BaseControl
|
|
6
|
+
from .locale import LocaleConfig
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MeasureControl(BaseControl):
|
|
10
|
+
"""Measurement tools control with locate, distance, and circle drawing modes.
|
|
11
|
+
|
|
12
|
+
Click the icon to expand the toolbar, then click a button to activate a mode:
|
|
13
|
+
|
|
14
|
+
- 📍 **Locate**: click to place a marker showing coordinates and reverse-geocoded
|
|
15
|
+
address. Click the popup or the × on the marker to delete it.
|
|
16
|
+
- 📏 **Distance**: click to draw a polyline. Segment and total distances update
|
|
17
|
+
in real-time. Double-click / right-click / click the last point to finish.
|
|
18
|
+
- ⭕ **Circle**: first click sets the center; move the mouse to set the radius;
|
|
19
|
+
second click confirms.
|
|
20
|
+
- 🗑️ **Clear**: remove all measurement layers at once.
|
|
21
|
+
|
|
22
|
+
After drawing a line or circle: click the object to toggle labels and × buttons;
|
|
23
|
+
click empty map space to hide × buttons.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
position : str, default "bottomright"
|
|
28
|
+
One of ``"topleft"``, ``"topright"``, ``"bottomleft"``, ``"bottomright"``.
|
|
29
|
+
|
|
30
|
+
locale : str or LocaleConfig, optional
|
|
31
|
+
Language code (``"en"``, ``"zh"``) or a :class:`LocaleConfig` instance.
|
|
32
|
+
Defaults to auto-detection, falling back to English.
|
|
33
|
+
|
|
34
|
+
Examples
|
|
35
|
+
--------
|
|
36
|
+
>>> import folium
|
|
37
|
+
>>> from foliplus import MeasureControl
|
|
38
|
+
>>> m = folium.Map()
|
|
39
|
+
>>> MeasureControl().add_to(m)
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
default_js = [
|
|
43
|
+
(
|
|
44
|
+
"gcoord",
|
|
45
|
+
f"https://cdn.jsdelivr.net/npm/gcoord@{GCOORD}/dist/gcoord.global.prod.js",
|
|
46
|
+
),
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
position: Position = "bottomright",
|
|
52
|
+
locale: str | LocaleConfig | None = None,
|
|
53
|
+
):
|
|
54
|
+
super().__init__(position=position, locale=locale)
|
|
55
|
+
self._template = self._get_template(
|
|
56
|
+
js_file="MeasureControl.js", css_file="MeasureControl.css"
|
|
57
|
+
)
|
foliplus/ScaleControl.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from ._typing import Position
|
|
4
|
+
from .base import BaseControl
|
|
5
|
+
from .locale import LocaleConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ScaleControl(BaseControl):
|
|
9
|
+
"""Scale control with metric units and optional zoom level display.
|
|
10
|
+
|
|
11
|
+
Adds a scale bar to the map with an optional current zoom level label.
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
position : str, default "bottomleft"
|
|
16
|
+
One of ``"topleft"``, ``"topright"``, ``"bottomleft"``, ``"bottomright"``.
|
|
17
|
+
|
|
18
|
+
metric : bool, default True
|
|
19
|
+
Whether to show metric units (meters / kilometers).
|
|
20
|
+
|
|
21
|
+
show_zoom : bool, default True
|
|
22
|
+
Whether to show the current map zoom level.
|
|
23
|
+
|
|
24
|
+
locale : str or LocaleConfig, optional
|
|
25
|
+
Language code (``"en"``, ``"zh"``) or a :class:`LocaleConfig` instance.
|
|
26
|
+
Defaults to auto-detection, falling back to English.
|
|
27
|
+
|
|
28
|
+
Examples
|
|
29
|
+
--------
|
|
30
|
+
>>> import folium
|
|
31
|
+
>>> from foliplus import ScaleControl
|
|
32
|
+
>>> m = folium.Map()
|
|
33
|
+
>>> ScaleControl().add_to(m)
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
position: Position = "bottomleft",
|
|
39
|
+
metric: bool = True,
|
|
40
|
+
show_zoom: bool = True,
|
|
41
|
+
locale: str | LocaleConfig | None = None,
|
|
42
|
+
):
|
|
43
|
+
super().__init__(position=position, locale=locale)
|
|
44
|
+
self.metric = metric
|
|
45
|
+
self.show_zoom = show_zoom
|
|
46
|
+
self._template = self._get_template(
|
|
47
|
+
js_file="ScaleControl.js", css_file="ScaleControl.css"
|
|
48
|
+
)
|
foliplus/__init__.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from .Fullscreen import Fullscreen
|
|
2
|
+
from .HeatmapControl import HeatmapControl
|
|
3
|
+
from .LayerControl import LayerControl
|
|
4
|
+
from .MapSearch import MapSearch
|
|
5
|
+
from .MeasureControl import MeasureControl
|
|
6
|
+
from .ScaleControl import ScaleControl
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"Fullscreen",
|
|
10
|
+
"HeatmapControl",
|
|
11
|
+
"LayerControl",
|
|
12
|
+
"MapSearch",
|
|
13
|
+
"MeasureControl",
|
|
14
|
+
"ScaleControl",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
__version__ = "0.1.0"
|
foliplus/_cdn.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Centralized CDN version management.
|
|
2
|
+
|
|
3
|
+
All CDN dependency versions are defined here. Bump a version in one place to update it
|
|
4
|
+
across all controls.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Fullscreen
|
|
8
|
+
LEAFLET_FULLSCREEN = "3"
|
|
9
|
+
|
|
10
|
+
# HeatmapControl
|
|
11
|
+
H3_JS = "4"
|
|
12
|
+
SIMPLE_STATISTICS = "7"
|
|
13
|
+
CHROMA_JS = "2"
|
|
14
|
+
|
|
15
|
+
# MeasureControl
|
|
16
|
+
GCOORD = "1"
|
foliplus/_typing.py
ADDED
foliplus/base.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from textwrap import dedent
|
|
5
|
+
|
|
6
|
+
from folium import MacroElement
|
|
7
|
+
from folium.elements import JSCSSMixin
|
|
8
|
+
from jinja2 import Template
|
|
9
|
+
|
|
10
|
+
from ._cdn import GCOORD
|
|
11
|
+
from ._typing import Position
|
|
12
|
+
from .locale import LocaleConfig, resolve_locale
|
|
13
|
+
|
|
14
|
+
src_dir = Path(__file__).parent
|
|
15
|
+
js_dir = src_dir / "js"
|
|
16
|
+
css_dir = src_dir / "css"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BaseControl(JSCSSMixin, MacroElement):
|
|
20
|
+
"""Base class for all foliplus controls.
|
|
21
|
+
|
|
22
|
+
Handles resource loading (CSS/JS), template injection, and localization. All
|
|
23
|
+
foliplus components (Fullscreen, HeatmapControl, LayerControl, etc.) inherit from
|
|
24
|
+
this class.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
position : str, default "topleft"
|
|
29
|
+
One of ``"topleft"``, ``"topright"``, ``"bottomleft"``, ``"bottomright"``.
|
|
30
|
+
|
|
31
|
+
locale : str or LocaleConfig, optional
|
|
32
|
+
Language code (``"en"``, ``"zh"``) or a :class:`LocaleConfig` instance.
|
|
33
|
+
Defaults to auto-detection, falling back to English.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
_common = css_dir.joinpath("common.css").read_text(encoding="utf-8")
|
|
37
|
+
_panel = css_dir.joinpath("panel.css").read_text(encoding="utf-8")
|
|
38
|
+
_runtime = js_dir.joinpath("runtime.js").read_text(encoding="utf-8")
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
position: Position = "topleft",
|
|
43
|
+
locale: str | LocaleConfig | None = None,
|
|
44
|
+
):
|
|
45
|
+
super().__init__()
|
|
46
|
+
self._name = self.__class__.__name__
|
|
47
|
+
self.position = position
|
|
48
|
+
self.locale = resolve_locale(locale)
|
|
49
|
+
self._gcoord_version = GCOORD
|
|
50
|
+
|
|
51
|
+
def _get_js(self, filename: str) -> str:
|
|
52
|
+
return js_dir.joinpath(filename).read_text(encoding="utf-8")
|
|
53
|
+
|
|
54
|
+
def _get_css(self, filename: str) -> str:
|
|
55
|
+
return css_dir.joinpath(filename).read_text(encoding="utf-8")
|
|
56
|
+
|
|
57
|
+
def _get_template(
|
|
58
|
+
self,
|
|
59
|
+
*,
|
|
60
|
+
js_file: str | None = None,
|
|
61
|
+
css_file: str | None = None,
|
|
62
|
+
use_panel: bool = False,
|
|
63
|
+
) -> Template:
|
|
64
|
+
"""Build a Jinja2 template with shared CSS/JS + component assets.
|
|
65
|
+
|
|
66
|
+
Injects ``common.css``, ``panel.css`` (if ``use_panel=True``), ``runtime.js``,
|
|
67
|
+
and the specified component JS/CSS files into a Jinja2 macro pair
|
|
68
|
+
(``html`` / ``script``) for folium's rendering pipeline.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
js_file : str, optional
|
|
73
|
+
Component JS filename (e.g. ``"LayerControl.js"``).
|
|
74
|
+
css_file : str, optional
|
|
75
|
+
Component CSS filename (e.g. ``"LayerControl.css"``).
|
|
76
|
+
use_panel : bool, default False
|
|
77
|
+
Whether to include shared panel CSS.
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
Template
|
|
82
|
+
A Jinja2 ``Template`` instance ready for folium rendering.
|
|
83
|
+
"""
|
|
84
|
+
js_runtime = self._get_js(js_file) if js_file else ""
|
|
85
|
+
css_common = self._get_css(css_file) if css_file else ""
|
|
86
|
+
css_panel = self._panel if use_panel else ""
|
|
87
|
+
locale_table = self.locale.get_js_table()
|
|
88
|
+
|
|
89
|
+
return Template(
|
|
90
|
+
dedent(f"""\
|
|
91
|
+
{{% macro html(this, kwargs) %}}
|
|
92
|
+
<style>
|
|
93
|
+
{self._common}
|
|
94
|
+
{css_panel}
|
|
95
|
+
{css_common}
|
|
96
|
+
</style>
|
|
97
|
+
{{% endmacro %}}
|
|
98
|
+
|
|
99
|
+
{{% macro script(this, kwargs) %}}
|
|
100
|
+
var _LOCALE = window._LOCALE || {locale_table};
|
|
101
|
+
{self._runtime}
|
|
102
|
+
{js_runtime}
|
|
103
|
+
{{% endmacro %}}""")
|
|
104
|
+
)
|