From ddacf585454eae308563129a4938acc778091d11 Mon Sep 17 00:00:00 2001 From: Adam Levin Date: Thu, 20 Mar 2025 10:45:37 -0400 Subject: [PATCH 1/7] feat: Adds a decorator to collect metadata from the new ETL pipeline Metadata is collected from docstrings and function runtime. Adds new info to the docstrings of functions in the new ETL pipeline. Adds testing of the new provide_metadata() decorator --- data/src/new_etl/classes/featurelayer.py | 26 +- data/src/new_etl/data_utils/access_process.py | 12 + .../data_utils/city_owned_properties.py | 16 + .../new_etl/data_utils/community_gardens.py | 24 +- .../src/new_etl/data_utils/conservatorship.py | 17 +- .../new_etl/data_utils/contig_neighbors.py | 15 +- data/src/new_etl/data_utils/council_dists.py | 14 +- data/src/new_etl/data_utils/delinquencies.py | 20 + .../src/new_etl/data_utils/dev_probability.py | 19 +- data/src/new_etl/data_utils/drug_crimes.py | 21 +- data/src/new_etl/data_utils/gun_crimes.py | 20 +- .../new_etl/data_utils/imm_dang_buildings.py | 14 + data/src/new_etl/data_utils/li_complaints.py | 18 + data/src/new_etl/data_utils/li_violations.py | 21 +- data/src/new_etl/data_utils/nbhoods.py | 18 +- data/src/new_etl/data_utils/negligent_devs.py | 13 + data/src/new_etl/data_utils/opa_properties.py | 27 +- data/src/new_etl/data_utils/owner_type.py | 12 + data/src/new_etl/data_utils/park_priority.py | 22 +- data/src/new_etl/data_utils/phs_properties.py | 11 + data/src/new_etl/data_utils/ppr_properties.py | 24 +- data/src/new_etl/data_utils/priority_level.py | 14 + data/src/new_etl/data_utils/pwd_parcels.py | 17 +- data/src/new_etl/data_utils/rco_geoms.py | 21 +- .../new_etl/data_utils/tactical_urbanism.py | 11 + data/src/new_etl/data_utils/tree_canopy.py | 21 +- .../new_etl/data_utils/unsafe_buildings.py | 14 + .../new_etl/data_utils/vacant_properties.py | 22 +- data/src/new_etl/metadata/metadata_utils.py | 278 ++++++++++++ data/src/test/test_metadata_utils.py | 404 ++++++++++++++++++ 30 files changed, 1151 insertions(+), 35 deletions(-) create mode 100644 data/src/new_etl/metadata/metadata_utils.py create mode 100644 data/src/test/test_metadata_utils.py diff --git a/data/src/new_etl/classes/featurelayer.py b/data/src/new_etl/classes/featurelayer.py index 9e5fd08b..9d42f584 100644 --- a/data/src/new_etl/classes/featurelayer.py +++ b/data/src/new_etl/classes/featurelayer.py @@ -2,11 +2,20 @@ import os import subprocess import traceback +from concurrent.futures import ThreadPoolExecutor, as_completed import geopandas as gpd import pandas as pd import requests import sqlalchemy as sa +from config.psql import conn, local_engine +from google.cloud import storage +from google.cloud.storage.bucket import Bucket +from new_etl.database import to_postgis_with_schema +from new_etl.loaders import load_carto_data, load_esri_data +from shapely import wkb +from tqdm import tqdm + from config.config import ( FORCE_RELOAD, USE_CRS, @@ -14,15 +23,6 @@ min_tiles_file_size_in_bytes, write_production_tiles_file, ) -from config.psql import conn, local_engine -from google.cloud import storage -from google.cloud.storage.bucket import Bucket -from shapely import wkb -from concurrent.futures import ThreadPoolExecutor, as_completed -from tqdm import tqdm - -from new_etl.loaders import load_esri_data, load_carto_data -from new_etl.database import to_postgis_with_schema log.basicConfig(level=log_level) @@ -33,8 +33,8 @@ def google_cloud_bucket() -> Bucket: Returns: Bucket: the gcp bucket """ - credentials_path = os.path.expanduser("/app/service-account-key.json") + credentials_path = os.path.expanduser("/app/service-account-key.json") if not os.path.exists(credentials_path): raise FileNotFoundError(f"Credentials file not found at {credentials_path}") @@ -63,7 +63,12 @@ def __init__( cols: list[str] = None, max_workers=os.cpu_count(), chunk_size=100000, + collected_metadata=None, ): + if collected_metadata is None: + self.collected_metadata = [] + else: + self.collected_metadata = collected_metadata self.name = name self.esri_rest_urls = ( [esri_rest_urls] if isinstance(esri_rest_urls, str) else esri_rest_urls @@ -84,7 +89,6 @@ def __init__( inputs = [self.esri_rest_urls, self.carto_sql_queries, self.gdf] non_none_inputs = [i for i in inputs if i is not None] - if len(non_none_inputs) > 0: self.type = ( "esri" diff --git a/data/src/new_etl/data_utils/access_process.py b/data/src/new_etl/data_utils/access_process.py index ae3af8e6..235acbb9 100644 --- a/data/src/new_etl/data_utils/access_process.py +++ b/data/src/new_etl/data_utils/access_process.py @@ -1,6 +1,9 @@ from typing import Any +from new_etl.metadata.metadata_utils import provide_metadata + +@provide_metadata() def access_process(dataset: Any) -> Any: """ Process a dataset to determine the access process for each property based on @@ -13,6 +16,15 @@ def access_process(dataset: Any) -> Any: Returns: Any: The updated dataset with an additional "access_process" column. + Tagline: + Assigns access processes + + Columns added: + access_process (str): The access process for each property based on city ownership and market value. + + Primary Feature Layer Columns Referenced: + city_owner_agency, market_value + Side Effects: Prints the distribution of the "access_process" column. """ diff --git a/data/src/new_etl/data_utils/city_owned_properties.py b/data/src/new_etl/data_utils/city_owned_properties.py index 7e967712..3b714daf 100644 --- a/data/src/new_etl/data_utils/city_owned_properties.py +++ b/data/src/new_etl/data_utils/city_owned_properties.py @@ -1,7 +1,9 @@ from ..classes.featurelayer import FeatureLayer from ..constants.services import CITY_OWNED_PROPERTIES_TO_LOAD +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def city_owned_properties(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Processes city-owned property data by joining it with the primary feature layer, @@ -15,6 +17,20 @@ def city_owned_properties(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The updated primary feature layer with processed city ownership information. + + Columns added: + city_owner_agency (str): The agency that owns the city property. + side_yard_eligible (str): Indicates if the property is eligible for the side yard program. + + Primary Feature Layer Columns Referenced: + opa_id, owner_1, owner2 + + Tagline: + Categorizes City Owned Properties + + Source: + https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/LAMAAssets/FeatureServer/0/ + """ city_owned_properties = FeatureLayer( name="City Owned Properties", diff --git a/data/src/new_etl/data_utils/community_gardens.py b/data/src/new_etl/data_utils/community_gardens.py index 80fa00df..ba72d9b3 100644 --- a/data/src/new_etl/data_utils/community_gardens.py +++ b/data/src/new_etl/data_utils/community_gardens.py @@ -1,13 +1,35 @@ +from config.config import USE_CRS + from ..classes.featurelayer import FeatureLayer from ..constants.services import COMMUNITY_GARDENS_TO_LOAD -from config.config import USE_CRS +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def community_gardens(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Updates the 'vacant' column in the primary feature layer to ensure community gardens are marked as not vacant. This protects known community gardens from being categorized as vacant, preventing potential predatory development. + + Args: + primary_featurelayer (FeatureLayer): The feature layer containing property data. + + Returns: + FeatureLayer: The input feature layer with the 'vacant' column updated to False + for parcels containing community gardens. + + Tagline: + Mark Community Gardens as Not Vacant + + Columns updated: + vacant: Updated to False for parcels containing community gardens. + + Primary Feature Layer Columns Referenced: + opa_id, vacant + + Source: + https://services2.arcgis.com/qjOOiLCYeUtwT7x7/arcgis/rest/services/PHS_NGT_Supported_Current_view/FeatureServer/0/ """ if "vacant" not in primary_featurelayer.gdf.columns: raise ValueError("The 'vacant' column is missing in the primary feature layer.") diff --git a/data/src/new_etl/data_utils/conservatorship.py b/data/src/new_etl/data_utils/conservatorship.py index 4e53c0fe..559664c0 100644 --- a/data/src/new_etl/data_utils/conservatorship.py +++ b/data/src/new_etl/data_utils/conservatorship.py @@ -1,7 +1,10 @@ -from ..classes.featurelayer import FeatureLayer import datetime -from dateutil.parser import parse + import pytz +from dateutil.parser import parse + +from ..classes.featurelayer import FeatureLayer +from ..metadata.metadata_utils import provide_metadata est = pytz.timezone("US/Eastern") six_months_ago = (datetime.datetime.now() - datetime.timedelta(days=180)).astimezone( @@ -9,6 +12,7 @@ ) +@provide_metadata() def conservatorship(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Determines conservatorship eligibility for properties in a feature layer. @@ -16,6 +20,15 @@ def conservatorship(primary_featurelayer: FeatureLayer) -> FeatureLayer: Args: primary_featurelayer (FeatureLayer): A feature layer containing property data in a GeoDataFrame (`gdf`). + Columns Added: + conservatorship (str): Indicates whether each property qualifies for conservatorship ("Yes" or "No"). + + Primary Feature Layer Columns Referenced: + city_owner_agency, sheriff_sale, market_value, all_violations_past_year, sale_date + + Tagline: + Identify conservatorship-eligible properties + Returns: FeatureLayer: The input feature layer with an added "conservatorship" column indicating whether each property qualifies for conservatorship ("Yes" or "No"). diff --git a/data/src/new_etl/data_utils/contig_neighbors.py b/data/src/new_etl/data_utils/contig_neighbors.py index c05f9d4c..80eb385d 100644 --- a/data/src/new_etl/data_utils/contig_neighbors.py +++ b/data/src/new_etl/data_utils/contig_neighbors.py @@ -1,10 +1,14 @@ import warnings + import networkx as nx -from libpysal.weights import Queen import numpy as np +from libpysal.weights import Queen + from ..classes.featurelayer import FeatureLayer +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def contig_neighbors(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Calculates the number of contiguous vacant neighbors for each property in a feature layer. @@ -15,6 +19,15 @@ def contig_neighbors(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with an added "n_contiguous" column indicating the number of contiguous vacant neighbors for each property. + + Tagline: + Count vacant neighbors + + Columns Added: + n_contiguous (int): The number of contiguous vacant neighbors for each property. + + Primary Feature Layer Columns Referenced: + opa_id, vacant """ # Create a filtered dataframe with only vacant properties and polygon geometries vacant_parcels = primary_featurelayer.gdf.loc[ diff --git a/data/src/new_etl/data_utils/council_dists.py b/data/src/new_etl/data_utils/council_dists.py index 74709709..100c7009 100644 --- a/data/src/new_etl/data_utils/council_dists.py +++ b/data/src/new_etl/data_utils/council_dists.py @@ -1,10 +1,13 @@ +import pandas as pd + from ..classes.featurelayer import FeatureLayer from ..constants.services import COUNCIL_DISTRICTS_TO_LOAD -import pandas as pd +from ..metadata.metadata_utils import provide_metadata pd.set_option("future.no_silent_downcasting", True) +@provide_metadata() def council_dists(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Associates properties in the primary feature layer with council districts @@ -16,6 +19,15 @@ def council_dists(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with properties spatially joined to council districts, ensuring no duplicate entries. + + Tagline: + Assigns council districts + + Columns added: + district (str): The council district associated with the property. + + Primary Feature Layer Columns Referenced: + opa_id, geometry """ # Load council districts council_dists = FeatureLayer( diff --git a/data/src/new_etl/data_utils/delinquencies.py b/data/src/new_etl/data_utils/delinquencies.py index 700372b2..0701289a 100644 --- a/data/src/new_etl/data_utils/delinquencies.py +++ b/data/src/new_etl/data_utils/delinquencies.py @@ -1,7 +1,9 @@ from ..classes.featurelayer import FeatureLayer from ..constants.services import DELINQUENCIES_QUERY +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def delinquencies(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Adds property tax delinquency information to the primary feature layer by @@ -13,6 +15,24 @@ def delinquencies(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with added columns for tax delinquency information, including total due, actionable status, payment agreements, and more. + + Tagline: + Summarize tax delinquencies + + Source: + https://phl.carto.com/api/v2/sql + + Columns Added: + total_due (float): Total amount owed. + most_recent_year_owed (str): Most recent year owed. + num_years_owed (int): Number of years owed. + payment_agreement (str): Indicates if there is a payment agreement. + is_actionable (str): Flag for actionable tax delinquency. + sheriff_sale (str): Indicates if the property is at risk of sheriff sale. + total_assessment (float): Total property assessment. + + Primary Feature Layer Columns Referenced: + opa_id """ tax_delinquencies = FeatureLayer( name="Property Tax Delinquencies", diff --git a/data/src/new_etl/data_utils/dev_probability.py b/data/src/new_etl/data_utils/dev_probability.py index 325b2e04..f69c51b5 100644 --- a/data/src/new_etl/data_utils/dev_probability.py +++ b/data/src/new_etl/data_utils/dev_probability.py @@ -2,11 +2,15 @@ import jenkspy import pandas as pd import requests + +from config.config import USE_CRS + from ..classes.featurelayer import FeatureLayer from ..constants.services import CENSUS_BGS_URL, PERMITS_QUERY -from config.config import USE_CRS +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def dev_probability(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Calculates development probability based on permit counts and assigns @@ -19,6 +23,19 @@ def dev_probability(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with added spatial join data for development probability and ranks. + + Tagline: + Calculate development probability + + Columns Added: + permit_count (int): The number of permits issued in the census block group. + dev_rank (str): The development rank of the census block group. + + Primary Feature Layer Columns Referenced: + opa_id, geometry + + Source: + https://phl.carto.com/api/v2/sql """ census_bgs_gdf = gpd.read_file(CENSUS_BGS_URL) census_bgs_gdf = census_bgs_gdf.to_crs(USE_CRS) diff --git a/data/src/new_etl/data_utils/drug_crimes.py b/data/src/new_etl/data_utils/drug_crimes.py index 479ac08a..a14c51e8 100644 --- a/data/src/new_etl/data_utils/drug_crimes.py +++ b/data/src/new_etl/data_utils/drug_crimes.py @@ -1,8 +1,11 @@ +from new_etl.data_utils.kde import apply_kde_to_primary + from ..classes.featurelayer import FeatureLayer from ..constants.services import DRUGCRIME_SQL_QUERY -from new_etl.data_utils.kde import apply_kde_to_primary +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def drug_crimes(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Applies kernel density estimation (KDE) analysis for drug crimes to the primary feature layer. @@ -12,6 +15,22 @@ def drug_crimes(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with KDE analysis results for drug crimes. + + Tagline: + Density analysis for drug crimes + + Columns added: + drug_crimes_density (float): KDE density of drug crimes. + drug_crimes_density_zscore (float): Z-score of drug crime density. + drug_crimes_density_label (str): Categorized density level. + drug_crimes_density_percentile (float): Percentile rank of density. + + Primary Feature Layer Columns Referenced: + geometry + + Source: + https://phl.carto.com/api/v2/sql + """ return apply_kde_to_primary( primary_featurelayer, "Drug Crimes", DRUGCRIME_SQL_QUERY diff --git a/data/src/new_etl/data_utils/gun_crimes.py b/data/src/new_etl/data_utils/gun_crimes.py index e9f2d1fd..1bfd8da5 100644 --- a/data/src/new_etl/data_utils/gun_crimes.py +++ b/data/src/new_etl/data_utils/gun_crimes.py @@ -1,8 +1,11 @@ +from new_etl.data_utils.kde import apply_kde_to_primary + from ..classes.featurelayer import FeatureLayer from ..constants.services import GUNCRIME_SQL_QUERY -from new_etl.data_utils.kde import apply_kde_to_primary +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def gun_crimes(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Applies kernel density estimation (KDE) analysis for gun crimes to the primary feature layer. @@ -12,5 +15,20 @@ def gun_crimes(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with KDE analysis results for gun crimes. + + Tagline: + Analyzes gun crime density + + Columns added: + gun_crimes_density (float): KDE density of gun crimes. + gun_crimes_density_zscore (float): Z-score of gun crime density. + gun_crimes_density_label (str): Categorized density level. + gun_crimes_density_percentile (float): Percentile rank of density. + + Primary Feature Layer Columns Referenced: + geometry + + Source: + https://phl.carto.com/api/v2/sql """ return apply_kde_to_primary(primary_featurelayer, "Gun Crimes", GUNCRIME_SQL_QUERY) diff --git a/data/src/new_etl/data_utils/imm_dang_buildings.py b/data/src/new_etl/data_utils/imm_dang_buildings.py index 5163be63..415046fa 100644 --- a/data/src/new_etl/data_utils/imm_dang_buildings.py +++ b/data/src/new_etl/data_utils/imm_dang_buildings.py @@ -1,7 +1,9 @@ from ..classes.featurelayer import FeatureLayer from ..constants.services import IMMINENT_DANGER_BUILDINGS_QUERY +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def imm_dang_buildings(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Adds information about imminently dangerous buildings to the primary feature layer @@ -13,6 +15,18 @@ def imm_dang_buildings(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with an added "imm_dang_building" column, indicating whether each property is categorized as imminently dangerous ("Y" or "N"). + + Tagline: + Identify imminently dangerous buildings + + Columns Added: + imm_dang_building (str): Indicates whether each property is categorized as imminently dangerous ("Y" or "N"). + + Primary Feature Layer Columns Referenced: + opa_id + + Source: + https://phl.carto.com/api/v2/sql """ imm_dang_buildings = FeatureLayer( name="Imminently Dangerous Buildings", diff --git a/data/src/new_etl/data_utils/li_complaints.py b/data/src/new_etl/data_utils/li_complaints.py index 3778cd23..c4fb3d3a 100644 --- a/data/src/new_etl/data_utils/li_complaints.py +++ b/data/src/new_etl/data_utils/li_complaints.py @@ -1,8 +1,10 @@ from ..classes.featurelayer import FeatureLayer from ..constants.services import COMPLAINTS_SQL_QUERY from ..data_utils.kde import apply_kde_to_primary +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def li_complaints(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Applies kernel density estimation (KDE) analysis for L&I complaints to the primary feature layer. @@ -13,6 +15,22 @@ def li_complaints(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with KDE analysis results for L&I complaints, including density and derived metrics. + + Tagline: + Analyzes L&I complaint density + + Columns added: + l_and_i_complaints_density (float): KDE density of complaints. + l_and_i_complaints_density_zscore (float): Z-score of complaint density. + l_and_i_complaints_density_label (str): Categorized density level. + l_and_i_complaints_density_percentile (float): Percentile rank of density. + + Primary Feature Layer Columns Referenced: + geometry + + Source: + https://phl.carto.com/api/v2/sql + """ return apply_kde_to_primary( primary_featurelayer, "L and I Complaints", COMPLAINTS_SQL_QUERY diff --git a/data/src/new_etl/data_utils/li_violations.py b/data/src/new_etl/data_utils/li_violations.py index efd52db5..d53fec85 100644 --- a/data/src/new_etl/data_utils/li_violations.py +++ b/data/src/new_etl/data_utils/li_violations.py @@ -1,10 +1,14 @@ -import pandas as pd -import geopandas as gpd from typing import List + +import geopandas as gpd +import pandas as pd + from ..classes.featurelayer import FeatureLayer from ..constants.services import VIOLATIONS_SQL_QUERY +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def li_violations(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Process L&I (Licenses and Inspections) data for violations. @@ -18,6 +22,19 @@ def li_violations(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The primary feature layer updated with L&I data. + + Tagline: + Counts L&I violations + + Columns added: + all_violations_past_year (int): Total violations in the past year. + open_violations_past_year (int): Open violations in the past year. + + Source: + https://phl.carto.com/api/v2/sql + + Primary Feature Layer Columns Referenced: + opa_id """ keywords: List[str] = [ "dumping", diff --git a/data/src/new_etl/data_utils/nbhoods.py b/data/src/new_etl/data_utils/nbhoods.py index 31c1f0a3..854df31c 100644 --- a/data/src/new_etl/data_utils/nbhoods.py +++ b/data/src/new_etl/data_utils/nbhoods.py @@ -1,9 +1,13 @@ import geopandas as gpd + +from config.config import USE_CRS + from ..classes.featurelayer import FeatureLayer from ..constants.services import NBHOODS_URL -from config.config import USE_CRS +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def nbhoods(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Adds neighborhood information to the primary feature layer by performing a spatial join @@ -15,6 +19,18 @@ def nbhoods(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with an added "neighborhood" column, containing the name of the neighborhood for each property. + + Tagline: + Assigns neighborhoods + + Columns added: + neighborhood (str): The name of the neighborhood associated with the property. + + Primary Feature Layer Columns Referenced: + opa_id, geometry + + Source: + https://raw.githubusercontent.com/opendataphilly/open-geo-data/master/philadelphia-neighborhoods/philadelphia-neighborhoods.geojson """ phl_nbhoods = gpd.read_file(NBHOODS_URL) diff --git a/data/src/new_etl/data_utils/negligent_devs.py b/data/src/new_etl/data_utils/negligent_devs.py index 194eb2cc..26609d46 100644 --- a/data/src/new_etl/data_utils/negligent_devs.py +++ b/data/src/new_etl/data_utils/negligent_devs.py @@ -1,6 +1,8 @@ from ..classes.featurelayer import FeatureLayer +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def negligent_devs(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Identifies negligent developers based on the number of vacant properties owned @@ -9,6 +11,17 @@ def negligent_devs(primary_featurelayer: FeatureLayer) -> FeatureLayer: Args: primary_featurelayer (FeatureLayer): The feature layer containing property data. + Columns Added: + negligent_dev (bool): non-city owned entities owning 5+ vacant properties + n_total_properties_owned (int): Total number of properties owned by the developer + n_vacant_properties_owned (int): Number of vacant properties owned by the developer + + Primary Feature Layer Columns Referenced: + opa_id, vacant, city_owner_agency, standardized_address + + Tagline: + Identify negligent developers + Returns: FeatureLayer: The input feature layer with additional columns for total properties owned, vacant properties owned, and a "negligent_dev" flag. diff --git a/data/src/new_etl/data_utils/opa_properties.py b/data/src/new_etl/data_utils/opa_properties.py index 5b6ce34c..08894ac9 100644 --- a/data/src/new_etl/data_utils/opa_properties.py +++ b/data/src/new_etl/data_utils/opa_properties.py @@ -1,5 +1,8 @@ -import pandas as pd import re + +import pandas as pd +from new_etl.metadata.metadata_utils import provide_metadata + from ..classes.featurelayer import FeatureLayer from ..constants.services import OPA_PROPERTIES_QUERY @@ -75,12 +78,33 @@ def create_standardized_address(row: pd.Series) -> str: return standardized_address.lower() +@provide_metadata() def opa_properties() -> FeatureLayer: """ Loads and processes OPA property data, standardizing addresses and cleaning geometries. Returns: FeatureLayer: A feature layer containing processed OPA property data. + + Columns Added: + opa_id (int): the OPA ID of the property + market_value (float): the market value from the OPA data + sale_date (str): the date of the last sale + sale_price (float): the price of the last sale + parcel_type (str): "Land" or "Building" + zip_code (str): The zip code of the property + zoning (str): The zoning of the property + owner_1 (str): The first owner of the property + owner_2 (str): The second owner of the property + building_code_description (str): The building code description + standardized_address (str): A standardized mailing address + geometry (geometry): The geometry of the property + + Source: + https://phl.carto.com/api/v2/sql + + Tagline: + Load OPA data """ opa = FeatureLayer( name="OPA Properties", @@ -104,7 +128,6 @@ def opa_properties() -> FeatureLayer: "zoning", ], ) - # Rename columns opa.gdf = opa.gdf.rename(columns={"parcel_number": "opa_id"}) diff --git a/data/src/new_etl/data_utils/owner_type.py b/data/src/new_etl/data_utils/owner_type.py index bcae8e00..b899ebc5 100644 --- a/data/src/new_etl/data_utils/owner_type.py +++ b/data/src/new_etl/data_utils/owner_type.py @@ -1,7 +1,10 @@ import pandas as pd + from ..classes.featurelayer import FeatureLayer +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def owner_type(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Determines the ownership type for each property in the primary feature layer based on @@ -15,6 +18,15 @@ def owner_type(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The updated feature layer with the 'owner_type' column added. + + Tagline: + Assigns ownership types + + Columns added: + owner_type (str): The ownership type of the property: Public, Business (LLC) or Individual. + + Primary Feature Layer Columns Referenced: + opa_id, owner_1, owner_2, city_owner_agency """ owner_types = [] diff --git a/data/src/new_etl/data_utils/park_priority.py b/data/src/new_etl/data_utils/park_priority.py index a35b652e..4c47b314 100644 --- a/data/src/new_etl/data_utils/park_priority.py +++ b/data/src/new_etl/data_utils/park_priority.py @@ -4,12 +4,15 @@ from typing import List, Union import geopandas as gpd +import pyogrio import requests from bs4 import BeautifulSoup -from ..classes.featurelayer import FeatureLayer -from config.config import USE_CRS from tqdm import tqdm -import pyogrio + +from config.config import USE_CRS + +from ..classes.featurelayer import FeatureLayer +from ..metadata.metadata_utils import provide_metadata def get_latest_shapefile_url() -> str: @@ -84,6 +87,7 @@ def download_and_process_shapefile( return phl_parks +@provide_metadata() def park_priority(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Downloads and processes park priority data, then joins it with the primary feature layer. @@ -93,6 +97,18 @@ def park_priority(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The primary feature layer with park priority data joined. + + Tagline: + Labels high-priority park areas. + + Columns Added: + park_priority (int): The park priority score. + + Primary Feature Layer Columns Referenced: + opa_id, geometry + + Source: + https://www.tpl.org/park-data-downloads """ park_url: str = get_latest_shapefile_url() print(f"Downloading park priority data from: {park_url}") diff --git a/data/src/new_etl/data_utils/phs_properties.py b/data/src/new_etl/data_utils/phs_properties.py index fb0f20be..1410e457 100644 --- a/data/src/new_etl/data_utils/phs_properties.py +++ b/data/src/new_etl/data_utils/phs_properties.py @@ -1,7 +1,9 @@ from ..classes.featurelayer import FeatureLayer from ..constants.services import PHS_LAYERS_TO_LOAD +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def phs_properties(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Perform a spatial join between the primary feature layer and the PHS properties layer, @@ -13,6 +15,15 @@ def phs_properties(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The updated primary feature layer with the 'phs_care_program' column. + + Tagline: + Identifies PHS Care properties + + Columns added: + phs_care_program (str): The PHS care program associated with the property. + + Primary Feature Layer Columns Referenced: + opa_id, geometry """ phs_properties = FeatureLayer( diff --git a/data/src/new_etl/data_utils/ppr_properties.py b/data/src/new_etl/data_utils/ppr_properties.py index 84c16a8b..7394e2cb 100644 --- a/data/src/new_etl/data_utils/ppr_properties.py +++ b/data/src/new_etl/data_utils/ppr_properties.py @@ -1,11 +1,16 @@ import io + import geopandas as gpd import requests + +from config.config import USE_CRS + from ..classes.featurelayer import FeatureLayer from ..constants.services import PPR_PROPERTIES_TO_LOAD -from config.config import USE_CRS +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def ppr_properties(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Updates the 'vacant' column in the primary feature layer to ensure PPR properties @@ -17,6 +22,23 @@ def ppr_properties(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The updated primary feature layer. + + Columns Updated: + vacant: Updated to False for PPR properties. + + Tagline: + Mark Parks as Not Vacant + + Source: + https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/PPR_Properties/FeatureServer/0 + + Known Issues: + If the Ersi REST URL is not available the function + will fall back to loading the data from a GeoJSON URL + https://opendata.arcgis.com/datasets/d52445160ab14380a673e5849203eb64_0.geojson + + Primary Feature Layer Columns Referenced: + opa_id, geometry, vacant, public_name """ fallback_url = "https://opendata.arcgis.com/datasets/d52445160ab14380a673e5849203eb64_0.geojson" diff --git a/data/src/new_etl/data_utils/priority_level.py b/data/src/new_etl/data_utils/priority_level.py index 6c0525c6..90e29da3 100644 --- a/data/src/new_etl/data_utils/priority_level.py +++ b/data/src/new_etl/data_utils/priority_level.py @@ -1,7 +1,10 @@ import pandas as pd +from new_etl.metadata.metadata_utils import provide_metadata + from ..classes.featurelayer import FeatureLayer +@provide_metadata() def priority_level(dataset: FeatureLayer) -> FeatureLayer: """ Determines priority levels for properties based on gun crime density, @@ -13,6 +16,17 @@ def priority_level(dataset: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with an added "priority_level" column, indicating the priority for each property as "Low", "Medium", or "High". + + Columns Added: + priority_level (str): The priority level ( "Low", "Medium", or "High") of the property + based on gun crime density, violations, tree canopy gaps, and PHS Landcare status. + + Tagline: + Add priority levels + + Source: + gun_crimes_density_zscore, all_violations_past_year, l_and_i_complaints_density_zscore, + tree_canopy_gap, phs_care_program columns in the primary feature layer. """ priority_levels = [] for idx, row in dataset.gdf.iterrows(): diff --git a/data/src/new_etl/data_utils/pwd_parcels.py b/data/src/new_etl/data_utils/pwd_parcels.py index 0bde9b59..1cc46c61 100644 --- a/data/src/new_etl/data_utils/pwd_parcels.py +++ b/data/src/new_etl/data_utils/pwd_parcels.py @@ -1,8 +1,11 @@ +import geopandas as gpd + from ..classes.featurelayer import FeatureLayer from ..constants.services import PWD_PARCELS_QUERY -import geopandas as gpd +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def pwd_parcels(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Updates the primary feature layer by replacing its geometry column with validated @@ -15,6 +18,18 @@ def pwd_parcels(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The updated primary feature layer with geometries replaced by those from PWD parcels or retained from the original layer if no match. + + Columns Updated: + geometry: The geometry column is updated with validated geometries from PWD parcels. + + Primary Feature Layer Columns Referenced: + opa_id, geometry + + Tagline: + Improve geometry with PWD parcels data. + + Source: + https://phl.carto.com/api/v2/sql """ # Load PWD parcels pwd_parcels = FeatureLayer( diff --git a/data/src/new_etl/data_utils/rco_geoms.py b/data/src/new_etl/data_utils/rco_geoms.py index 504a8d90..3b294656 100644 --- a/data/src/new_etl/data_utils/rco_geoms.py +++ b/data/src/new_etl/data_utils/rco_geoms.py @@ -1,10 +1,13 @@ +import pandas as pd + from ..classes.featurelayer import FeatureLayer from ..constants.services import RCOS_LAYERS_TO_LOAD -import pandas as pd +from ..metadata.metadata_utils import provide_metadata pd.set_option("future.no_silent_downcasting", True) +@provide_metadata() def rco_geoms(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Adds Registered Community Organization (RCO) information to the primary feature layer @@ -16,6 +19,22 @@ def rco_geoms(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with added RCO-related columns, including aggregated RCO information and names. + + Tagline: + Assigns Community Org Info + + Columns added: + rco_names (str): Names of RCOs associated with the property. + rco_info (str): Additional RCO-related information. + + Source: + "https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/Zoning_RCO/FeatureServer/0/" + + Notes: + Modifies various columns. Fillna and infer_objects is applied to most columns. + + Primary Feature Layer Columns Referenced: + opa_id, geometry """ rco_geoms = FeatureLayer(name="RCOs", esri_rest_urls=RCOS_LAYERS_TO_LOAD) diff --git a/data/src/new_etl/data_utils/tactical_urbanism.py b/data/src/new_etl/data_utils/tactical_urbanism.py index 68ca85e2..e862a2c3 100644 --- a/data/src/new_etl/data_utils/tactical_urbanism.py +++ b/data/src/new_etl/data_utils/tactical_urbanism.py @@ -1,6 +1,8 @@ from ..classes.featurelayer import FeatureLayer +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def tactical_urbanism(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Assigns a 'tactical_urbanism' value to each row in the primary feature layer based on specific conditions. @@ -11,6 +13,15 @@ def tactical_urbanism(primary_featurelayer: FeatureLayer) -> FeatureLayer: Args: primary_featurelayer: A FeatureLayer object containing a GeoDataFrame (`gdf`) as an attribute. + Columns Added: + tactical_urbanism (str): Indicates whether each property qualifies for tactical urbanism ("Yes" or "No"). + + Primary Feature Layer Columns Referenced: + parcel_type, unsafe_building, imm_dang_building + + Tagline: + Identify tactical urbanism-eligible properties + Returns: The input FeatureLayer with a new column 'tactical_urbanism' added to its GeoDataFrame. """ diff --git a/data/src/new_etl/data_utils/tree_canopy.py b/data/src/new_etl/data_utils/tree_canopy.py index 9e67b4e2..8b5632ec 100644 --- a/data/src/new_etl/data_utils/tree_canopy.py +++ b/data/src/new_etl/data_utils/tree_canopy.py @@ -1,11 +1,16 @@ -import requests import io import zipfile + import geopandas as gpd -from ..classes.featurelayer import FeatureLayer +import requests + from config.config import USE_CRS +from ..classes.featurelayer import FeatureLayer +from ..metadata.metadata_utils import provide_metadata + +@provide_metadata() def tree_canopy(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Adds tree canopy gap information to the primary feature layer by downloading, @@ -17,6 +22,18 @@ def tree_canopy(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with an added "tree_canopy_gap" column indicating the tree canopy gap for each property. + + Tagline: + Measures tree canopy gaps. + + Columns added: + tree_canopy_gap (float): The amount of tree canopy lacking. + + Primary Feature Layer Columns Referenced: + opa_id, geometry + + Source: + https://national-tes-data-share.s3.amazonaws.com/national_tes_share/pa.zip.zip """ tree_url = ( "https://national-tes-data-share.s3.amazonaws.com/national_tes_share/pa.zip.zip" diff --git a/data/src/new_etl/data_utils/unsafe_buildings.py b/data/src/new_etl/data_utils/unsafe_buildings.py index 655621a3..1e096529 100644 --- a/data/src/new_etl/data_utils/unsafe_buildings.py +++ b/data/src/new_etl/data_utils/unsafe_buildings.py @@ -1,7 +1,9 @@ from ..classes.featurelayer import FeatureLayer from ..constants.services import UNSAFE_BUILDINGS_QUERY +from ..metadata.metadata_utils import provide_metadata +@provide_metadata() def unsafe_buildings(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Adds unsafe building information to the primary feature layer by joining with a dataset @@ -13,6 +15,18 @@ def unsafe_buildings(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with an added "unsafe_building" column, indicating whether each property is categorized as an unsafe building ("Y" or "N"). + + Tagline: + Identify unsafe buildings + + Columns Added: + unsafe_building (str): Indicates whether each property is categorized as an unsafe building ("Y" or "N"). + + Primary Feature Layer Columns Referenced: + opa_id + + Source: + https://phl.carto.com/api/v2/sql """ unsafe_buildings = FeatureLayer( name="Unsafe Buildings", diff --git a/data/src/new_etl/data_utils/vacant_properties.py b/data/src/new_etl/data_utils/vacant_properties.py index 84845ee4..9b4b56f0 100644 --- a/data/src/new_etl/data_utils/vacant_properties.py +++ b/data/src/new_etl/data_utils/vacant_properties.py @@ -1,9 +1,12 @@ -from ..classes.featurelayer import FeatureLayer, google_cloud_bucket -from ..constants.services import VACANT_PROPS_LAYERS_TO_LOAD -import geopandas as gpd from io import BytesIO + +import geopandas as gpd import pandas as pd +from ..classes.featurelayer import FeatureLayer, google_cloud_bucket +from ..constants.services import VACANT_PROPS_LAYERS_TO_LOAD +from ..metadata.metadata_utils import provide_metadata + def load_backup_data_from_gcs(file_name: str) -> pd.DataFrame: """ @@ -54,6 +57,7 @@ def check_null_percentage(df: pd.DataFrame, threshold: float = 0.05) -> None: ) +@provide_metadata() def vacant_properties(primary_featurelayer: FeatureLayer) -> FeatureLayer: """ Adds a "vacant" column to the primary feature layer based on vacant property data from @@ -64,6 +68,18 @@ def vacant_properties(primary_featurelayer: FeatureLayer) -> FeatureLayer: Returns: FeatureLayer: The input feature layer with an added "vacant" column. + + Tagline: + Identify vacant properties. + + Columns Added: + vacant (bool): Indicates whether the property is vacant. + + Primary Feature Layer Columns Referenced: + opa_id + + Known Issues: + - The vacant land data is below the threshold, so backup data is loaded from GCS. """ vacant_properties = FeatureLayer( name="Vacant Properties", diff --git a/data/src/new_etl/metadata/metadata_utils.py b/data/src/new_etl/metadata/metadata_utils.py new file mode 100644 index 00000000..fbdec1d8 --- /dev/null +++ b/data/src/new_etl/metadata/metadata_utils.py @@ -0,0 +1,278 @@ +import functools +import logging as log +import re +import sys +import time +from datetime import datetime, timezone + +import geopandas as gpd + +from config.config import log_level + +log.basicConfig(level=log_level) + +DESCRIPTION_REGEX = r"^(?P.*?)(?=\n\s*\w+:\s|$)" +SECTION_REGEX = r"^\s*(?P[\w\s]+):\s*(?P.*?)(?=^\s*[\w\s]+:\s|\Z)" +METADATA_FIELDS = [ + "description", + "returns", + "tagline", + "columns added", + "columns updated", + "source", + "known issues", + "primary feature layer columns referenced", +] +METADATA_FIELD_TYPES = { + "columns added": "columns", # with types + "columns updated": "columns", # without types + "primary feature layer columns referenced": "column_names", +} + + +def normalize_whitespace(text): + """Convert newlines to spaces and collapse multiple spaces into one.""" + text = text.replace("\n", " ") + text = re.sub(r"\s+", " ", text) + return text.strip() + + +def get_description_from_docstring(docstring): + """ + Extract the description from the docstring. + + Extracts all text before the first section header (e.g. Args:, Returns:). + + """ + + # Regex to capture the "description": everything until a section header + description_pattern = re.compile(DESCRIPTION_REGEX, re.DOTALL) + description_match = description_pattern.search(docstring) + description = ( + description_match.group("description").strip() if description_match else "" + ) + return description + + +def get_sections_from_docstring(docstring): + section_pattern = re.compile( + SECTION_REGEX, + re.DOTALL | re.MULTILINE, + ) + sections = { + m.group("key").lower(): m.group("value").strip() + for m in section_pattern.finditer(docstring) + } + return sections + + +def get_column_details(text): + """ + Parse the column details from the text in the format: + "column_name (data_type): description" + """ + pattern = r"(\w+)(?:\s+\((\w+)\))?:\s+(.+)" + + matches = re.findall(pattern, text) + + # Convert to structured data with default type as "unknown" + parsed_columns = [] + for name, dtype, desc in matches: + column = { + "name": name.strip(), + "description": desc.strip(), + } + if dtype: # Only add 'type' if dtype is not empty + column["type"] = dtype.strip() + + parsed_columns.append(column) + + return parsed_columns + + +def clean_docstring(docstring): + """ + trim function from PEP-257 + + Ensures that the docstring is clean, uniformly indented, and free of extraneous whitespace. + """ + if not docstring: + return "" + + # Convert tabs to spaces (following the normal Python rules) + # and split into a list of lines: + lines = docstring.expandtabs().splitlines() + # Determine minimum indentation (first line doesn't count): + indent = sys.maxsize + for line in lines[1:]: + stripped = line.lstrip() + if stripped: + indent = min(indent, len(line) - len(stripped)) + # Remove indentation (first line is special): + trimmed = [lines[0].strip()] + if indent < sys.maxsize: + for line in lines[1:]: + trimmed.append(line[indent:].rstrip()) + # Strip off trailing and leading blank lines: + while trimmed and not trimmed[-1]: + trimmed.pop() + while trimmed and not trimmed[0]: + trimmed.pop(0) + + # Current code/unittests expects a line return at + # end of multiline docstrings + # workaround expected behavior from unittests + if "\n" in docstring: + trimmed.append("") + + # Return a single string: + return "\n".join(trimmed) + + +def parse_docstring(docstring): + """Parse the docstring into its components.""" + # Capture the "description" which is everything before the first header + if not docstring: + return {} + docstring = clean_docstring(docstring.lstrip("\n")) + description = get_description_from_docstring(docstring) + sections = get_sections_from_docstring(docstring) + sections["description"] = description + + # "columns added" and "columns updated" require special handling + # to breakdown the columns listed in the docstring + + result = {} + for field in METADATA_FIELDS: + if METADATA_FIELD_TYPES.get(field, "text") == "columns": + result[field] = get_column_details(sections.get(field, "")) + elif METADATA_FIELD_TYPES.get(field, "text") == "column_names": + result[field] = [ + col.strip() for col in sections.get(field, "").split(",") if col.strip() + ] + else: + result[field] = ( + normalize_whitespace(sections[field]) if sections.get(field) else "" + ) + + return result + + +def detect_added_columns(df_before, df_after): + """ + Detects columns that have been added in df_after compared to df_before. + Handles cases where df_before is None or empty. + """ + if df_before is None or df_before.empty: + return set(df_after.columns) + return set(df_after.columns) - set(df_before.columns) + + +def provide_metadata(): + """ + Decorator to collect metadata from ETL functions. + + The collected metadata is stored in the`collected_metadata` attribute of the FeatureLayer object. + + Apply this decorator by adding `@provide_metadata()` above the function definition. + + The metadata collects info from the docstring in the following format: + + ''' + Description of what the function does. + + Args: + param1 (Type): Description of parameter 1. + param2 (Type): Description of parameter 2. + + Returns: + ReturnType: Description of the return value. + + Tagline: + A very short summary of the function for use in DAG graphs. + + Columns added: + column_name (data_type): Description of what this new column represents. + + Columns updated: + column_name: Description of how this column was changed. + + Primary Feature Layer Columns Referenced: + column_name (data_type): Description of how this column is referenced. + + Source: + URL or reference for additional context. + + Known issues: + Any known issues or limitations with this function. + + ''' + """ + + def decorator(func): + @functools.wraps(func) + def wrapper(primary_featurelayer=None): + # Run the function and collect metadata + # including start time, end time, and duration + + if ( + primary_featurelayer is None + or not hasattr(primary_featurelayer, "gdf") + or primary_featurelayer.gdf is None + ): + gdf_before = gpd.GeoDataFrame() + current_metadata = [] + else: + gdf_before = primary_featurelayer.gdf.copy() + current_metadata = primary_featurelayer.collected_metadata + start_time_str = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S") + start_time = time.time() + if primary_featurelayer is None: + primary_featurelayer = func() + else: + primary_featurelayer = func(primary_featurelayer) + end_time = time.time() + end_time_str = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S") + try: + gdf_after = primary_featurelayer.gdf.copy() + detected_columns_added = detect_added_columns(gdf_before, gdf_after) + + func_name = func.__name__ + doc_meta = parse_docstring(func.__doc__) + + metadata = { + "name": func_name, + "start_time": start_time_str, + "end_time": end_time_str, + "duration_in_seconds": round(end_time - start_time, 2), + } + + for field in METADATA_FIELDS: + metadata[field.replace(" ", "_")] = doc_meta.get(field, "") + + names_of_columns_added = set( + [col["name"] for col in metadata.get("columns_added", [])] + ) + if detected_columns_added != names_of_columns_added: + log.debug( + "Columns added doesn't match columns listed as added in the docstring:" + f"Detected: {detected_columns_added}" + f"Listed in docstring: {names_of_columns_added}" + ) + + primary_featurelayer.collected_metadata = current_metadata + [metadata] + except Exception as e: + print("Failed to collect metadata for", func.__name__) + print(type(e), e) + log.error(e, exc_info=True) + metadata = { + "name": func.__name__, + "description": "Failed to collect metadata", + } + primary_featurelayer.collected_metadata = current_metadata + [metadata] + + return primary_featurelayer + + return wrapper + + return decorator diff --git a/data/src/test/test_metadata_utils.py b/data/src/test/test_metadata_utils.py new file mode 100644 index 00000000..f8f186eb --- /dev/null +++ b/data/src/test/test_metadata_utils.py @@ -0,0 +1,404 @@ +import unittest + +import geopandas as gpd +from new_etl.classes.featurelayer import FeatureLayer + +from ..new_etl.metadata.metadata_utils import ( + get_column_details, + get_description_from_docstring, + get_sections_from_docstring, + normalize_whitespace, + parse_docstring, + provide_metadata, +) + +# Stub functions with actual docstrings used for parsing tests + + +def stub_update_vacant_community(primary_featurelayer): + """ + Updates the 'vacant' column in the primary feature layer to ensure community gardens + are marked as not vacant. This protects known community gardens from being categorized + as vacant, preventing potential predatory development. + + Args: + primary_featurelayer (FeatureLayer): The feature layer containing property data. + + Returns: + FeatureLayer: The input feature layer with the 'vacant' column updated to False + for parcels containing community gardens. + + Tagline: + Mark Community Gardens as Not Vacant + + Columns updated: + vacant: Updated to False for parcels containing community gardens. + + Primary Feature Layer Columns Referenced: + vacant, ipa_id + """ + pass + + +def stub_kde_analysis(primary_featurelayer): + """ + Applies kernel density estimation (KDE) analysis for drug crimes to the primary feature layer. + + Args: + primary_featurelayer (FeatureLayer): The feature layer containing property data. + + Returns: + FeatureLayer: The input feature layer with KDE analysis results for drug crimes. + + Tagline: + Density analysis for drug crimes + + Source: + https://phl.carto.com/api/v2/sql + """ + pass + + +def stub_load_opa(): + """ + Loads and processes OPA property data, standardizing addresses and cleaning geometries. + + Returns: + FeatureLayer: A feature layer containing processed OPA property data. + + Columns added: + opa_id (type): desc + market_value (type): desc + sale_date (type): desc + sale_price (numeric): desc + parcel_type (type): desc + zip_code (type): desc + zoning (type): desc + owner_1 (type): desc + owner_2 (type): desc + building_code_description (str): desc + standardized_address (str): A standardized mailing address + geometry (type): desc + + Source: + https://phl.carto.com/api/v2/sql + + Tagline: + Load OPA data + """ + pass + + +def stub_update_vacant_ppr(primary_featurelayer): + """ + Updates the 'vacant' column in the primary feature layer to ensure PPR properties + are marked as not vacant. This prevents PPR properties from being miscategorized as vacant. + + Args: + primary_featurelayer (FeatureLayer): The primary feature layer to update. + + Returns: + FeatureLayer: The updated primary feature layer. + + Columns updated: + vacant: Updated to False for PPR properties. + + Tagline: + Mark Parks as Not Vacant + + Source: + https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/PPR_Properties/FeatureServer/0 + + Known issues: + If the Ersi REST URL is not available the function + will fall back to loading the data from a GeoJSON URL: + https://opendata.arcgis.com/datasets/d52445160ab14380a673e5849203eb64_0.geojson + """ + pass + + +def stub_columns_added_variation(primary_featurelayer): + """ + Function with a docstring that uses 'Columns Added:' key variation. + + Args: + primary_featurelayer (FeatureLayer): The feature layer. + + Returns: + FeatureLayer: The updated feature layer. + + Columns Added: + column_x (int): Some description for column_x. + column_y (float): Some description for column_y. + + Tagline: + Example tagline + """ + pass + + +def stub_only_args_and_returns(primary_featurelayer): + """ + Function with only args and returns sections. + + Args: + primary_featurelayer (FeatureLayer): The feature layer. + + Returns: + FeatureLayer: The updated feature layer. + """ + pass + + +@provide_metadata() +def sample_add_columns(primary_featurelayer): + """ + Adds columns to the primary feature layer. + + Args: + primary_featurelayer (FeatureLayer): The feature layer to update. + + Returns: + FeatureLayer: The updated primary feature layer. + + Columns added: + column1 (int): Description for column1. + + Tagline: + Example tagline + """ + new_layer = FeatureLayer( + name="stub_add_columns", + ) + + new_layer.gdf = gpd.GeoDataFrame( + data={"opa_number": ["1", "2", "3"], "column1": [1, 2, 3]} + ) + primary_featurelayer.opa_join( + new_layer.gdf, + "opa_number", + ) + + return primary_featurelayer + + +class TestMetadataUtils(unittest.TestCase): + def test_normalize_whitespace(self): + test_cases = [ + ("Hello world", "Hello world"), + ("Line1\nLine2", "Line1 Line2"), + (" Leading and multiple spaces ", "Leading and multiple spaces"), + ] + for input_text, expected in test_cases: + with self.subTest(input_text=input_text): + result = normalize_whitespace(input_text) + self.assertEqual(result, expected) + + def test_get_description_from_docstring(self): + # Ensure description extraction stops before a section header. + docstring = ( + "This is the function description.\n\n" + "Args:\n param (int): parameter description" + ) + expected = "This is the function description." + result = get_description_from_docstring(docstring) + self.assertEqual(result, expected) + + def test_get_sections_from_docstring(self): + # Test that sections are correctly extracted. + docstring = ( + "This is a description.\n\n" + "Args:\n param (int): description\n\n" + "Returns:\n int: result" + ) + sections = get_sections_from_docstring(docstring) + self.assertIn("args", sections) + self.assertIn("returns", sections) + self.assertTrue(sections["args"].strip()) + self.assertTrue(sections["returns"].strip()) + + def test_get_column_details(self): + # Test column details extraction. + text = "col1 (int): description for col1\ncol2 (str): description for col2" + expected = [ + {"name": "col1", "type": "int", "description": "description for col1"}, + {"name": "col2", "type": "str", "description": "description for col2"}, + ] + result = get_column_details(text) + self.assertEqual(result, expected) + + def test_parse_docstring(self): + test_cases = [ + ( + stub_update_vacant_community.__doc__, + { + "description": ( + "Updates the 'vacant' column in the primary feature layer to ensure community gardens " + "are marked as not vacant. This protects known community gardens from being categorized as " + "vacant, preventing potential predatory development." + ), + "returns": ( + "FeatureLayer: The input feature layer with the 'vacant' column updated to False for parcels " + "containing community gardens." + ), + "tagline": "Mark Community Gardens as Not Vacant", + "columns updated": [ + { + "name": "vacant", + "description": "Updated to False for parcels containing community gardens.", + } + ], + "columns added": [], + "source": "", + "known issues": "", + "primary feature layer columns referenced": ["vacant", "ipa_id"], + }, + ), + ( + stub_kde_analysis.__doc__, + { + "description": "Applies kernel density estimation (KDE) analysis for drug crimes to the primary feature layer.", + "returns": "FeatureLayer: The input feature layer with KDE analysis results for drug crimes.", + "tagline": "Density analysis for drug crimes", + "source": "https://phl.carto.com/api/v2/sql", + "columns added": [], + "columns updated": [], + "known issues": "", + "primary feature layer columns referenced": [], + }, + ), + ( + stub_load_opa.__doc__, + { + "description": "Loads and processes OPA property data, standardizing addresses and cleaning geometries.", + "returns": "FeatureLayer: A feature layer containing processed OPA property data.", + "tagline": "Load OPA data", + "source": "https://phl.carto.com/api/v2/sql", + # For columns added, we expect a list of 12 dictionaries. + "columns added": "list_of_12", + "columns updated": [], + "known issues": "", + "primary feature layer columns referenced": [], + }, + ), + ( + stub_update_vacant_ppr.__doc__, + { + "description": ( + "Updates the 'vacant' column in the primary feature layer to ensure PPR properties " + "are marked as not vacant. This prevents PPR properties from being miscategorized as vacant." + ), + "returns": "FeatureLayer: The updated primary feature layer.", + "tagline": "Mark Parks as Not Vacant", + "source": "https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/PPR_Properties/FeatureServer/0", + "columns updated": [ + { + "name": "vacant", + "description": "Updated to False for PPR properties.", + } + ], + "columns added": [], + "known issues": ( + "If the Ersi REST URL is not available the function" # NOTE: because the next line has a colon, only the first line is captured + ), + "primary feature layer columns referenced": [], + }, + ), + ( + stub_columns_added_variation.__doc__, + { + "description": "Function with a docstring that uses 'Columns Added:' key variation.", + "returns": "FeatureLayer: The updated feature layer.", + "tagline": "Example tagline", + "columns added": [ + { + "name": "column_x", + "type": "int", + "description": "Some description for column_x.", + }, + { + "name": "column_y", + "type": "float", + "description": "Some description for column_y.", + }, + ], + "columns updated": [], + "source": "", + "known issues": "", + "primary feature layer columns referenced": [], + }, + ), + ( + stub_only_args_and_returns.__doc__, + { + "description": "Function with only args and returns sections.", + "returns": "FeatureLayer: The updated feature layer.", + "tagline": "", + "columns added": [], + "columns updated": [], + "source": "", + "known issues": "", + "primary feature layer columns referenced": [], + }, + ), + ] + for docstring, expected_metadata in test_cases: + with self.subTest(docstring=docstring): + print(expected_metadata["description"]) + metadata = parse_docstring(docstring) + # For stub_load_opa, we expect a list of 12 columns. + if expected_metadata["columns added"] == "list_of_12": + self.assertIsInstance(metadata.get("columns added"), list) + self.assertEqual(len(metadata.get("columns added")), 12) + else: + self.assertEqual( + metadata.get("columns added"), + expected_metadata["columns added"], + ) + fields = metadata.keys() + for field in fields: + if field == "columns added": + continue + self.assertEqual(metadata.get(field), expected_metadata[field]) + + def test_provide_metadata_with_sample_add_columns(self): + # Test that the metadata is correctly added to the function output. + primary_featurelayer = FeatureLayer(name="stub") + primary_featurelayer.gdf = gpd.GeoDataFrame( + data={ + "opa_id": ["1", "2", "3"], + "existing_field": [1, 2, 3], + "geometry": gpd.points_from_xy([1, 2, 3], [1, 2, 3]), + } + ) + result = sample_add_columns(primary_featurelayer) + metadata = result.collected_metadata + + expected_metadata = { + "name": "sample_add_columns", + "description": "Adds columns to the primary feature layer.", + "returns": "FeatureLayer: The updated primary feature layer.", + "start_time": "2021-10-01 00:00:00", + "end_time": "2021-10-01 00:00:00", + "duration_in_seconds": 0.0, + "tagline": "Example tagline", + "columns_added": [ + { + "name": "column1", + "type": "int", + "description": "Description for column1.", + } + ], + "columns_updated": [], + "source": "", + "known_issues": "", + "primary_feature_layer_columns_referenced": [], + } + most_recent_metadata = metadata[-1] + fields = most_recent_metadata.keys() + assert sorted(fields) == sorted(expected_metadata.keys()) + for field in fields: + if field in ["start_time", "end_time", "duration_in_seconds"]: + continue + self.assertEqual(most_recent_metadata.get(field), expected_metadata[field]) + self.assertEqual(most_recent_metadata.get(field), expected_metadata[field]) From 8d0490e6701ffa0492edd3b34beddb1386d012d4 Mon Sep 17 00:00:00 2001 From: Adam Levin Date: Thu, 20 Mar 2025 10:51:50 -0400 Subject: [PATCH 2/7] chore: store metadata to tmp folder when running main.py --- data/src/main.py | 55 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/data/src/main.py b/data/src/main.py index 66a30287..bc97fa43 100644 --- a/data/src/main.py +++ b/data/src/main.py @@ -1,14 +1,42 @@ import sys -import pandas as pd import traceback +import pandas as pd from config.psql import conn -from config.config import tiles_file_id_prefix - -from new_etl.classes.slack_reporters import send_dataframe_profile_to_slack, send_pg_stats_to_slack, send_error_to_slack from new_etl.classes.data_diff import DiffReport -from new_etl.data_utils import * -from new_etl.database import to_postgis_with_schema +from new_etl.classes.slack_reporters import ( + send_dataframe_profile_to_slack, + send_error_to_slack, + send_pg_stats_to_slack, +) +from new_etl.data_utils import ( + city_owned_properties, + community_gardens, + conservatorship, + contig_neighbors, + council_dists, + delinquencies, + dev_probability, + drug_crimes, + gun_crimes, + imm_dang_buildings, + li_complaints, + li_violations, + nbhoods, + negligent_devs, + owner_type, + park_priority, + phs_properties, + ppr_properties, + pwd_parcels, + rco_geoms, + tactical_urbanism, + tree_canopy, + unsafe_buildings, + vacant_properties, +) + +from config.config import tiles_file_id_prefix # Ensure the directory containing awkde is in the Python path awkde_path = "/usr/src/app" @@ -17,7 +45,6 @@ try: - print("Starting ETL process.") services = [ @@ -58,6 +85,12 @@ dataset = priority_level(dataset) dataset = access_process(dataset) + # Save metadata + try: + metadata_df = pd.DataFrame(dataset.collected_metadata) + metadata_df.to_csv("tmp/metadata.csv", index=False) + except Exception as e: + print(f"Error saving metadata: {str(e)}") # Drop duplicates before_drop = dataset.gdf.shape[0] dataset.gdf = dataset.gdf.drop_duplicates(subset="opa_id") @@ -72,8 +105,12 @@ "num_years_owed", "permit_count", ] - dataset.gdf[numeric_columns] = dataset.gdf[numeric_columns].apply(pd.to_numeric, errors="coerce") - dataset.gdf["most_recent_year_owed"] = dataset.gdf["most_recent_year_owed"].astype(str) + dataset.gdf[numeric_columns] = dataset.gdf[numeric_columns].apply( + pd.to_numeric, errors="coerce" + ) + dataset.gdf["most_recent_year_owed"] = dataset.gdf["most_recent_year_owed"].astype( + str + ) # Dataset profiling send_dataframe_profile_to_slack(dataset.gdf, "all_properties_end") From 8186b65e543cc75bfa377561aa347b84efa097c9 Mon Sep 17 00:00:00 2001 From: Adam Levin Date: Thu, 20 Mar 2025 11:05:37 -0400 Subject: [PATCH 3/7] chore: add DAG and DataDict to docs --- docs/ETL pipeline/DAG.md | 60 +++++++++++++++++++++ docs/ETL pipeline/DataDict.md | 98 +++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 docs/ETL pipeline/DAG.md create mode 100644 docs/ETL pipeline/DataDict.md diff --git a/docs/ETL pipeline/DAG.md b/docs/ETL pipeline/DAG.md new file mode 100644 index 00000000..dbd64978 --- /dev/null +++ b/docs/ETL pipeline/DAG.md @@ -0,0 +1,60 @@ +## DAG for the new ETL Pipline + +In practice, functions are run sequentially but this DAG shows dependencies on prior data modifications/additions. + +```mermaid +%%{init: {'flowchart': {'nodeSpacing': 100, 'rankSpacing': 50}}}%% +graph LR + %% Initial Ingestion + OP[opa_properties
Load OPA data] + VP[vacant_properties
Identify vacant properties] + + %% First updates from ingestion + OP --> PP[pwd_parcels
Improve geometry with PWD parcels data] + OP --> LV[li_violations
Counts L&I violations] + OP --> CO[city_owned_properties
Categorizes City Owned Properties] + OP --> DL[delinquencies
Summarize tax delinquencies] + OP --> UB[unsafe_buildings
Identify unsafe buildings] + OP --> IDB[imm_dang_buildings
Identify imminently dangerous buildings] + + VP --> CG[community_gardens
Mark Community Gardens as Not Vacant] + VP --> PPR[ppr_properties
Mark Parks as Not Vacant] + + %% Branches from pwd_parcels (updated geometry) + PP --> CD[council_dists
Assigns council districts] + PP --> NB[nbhoods
Assigns neighborhoods] + PP --> RC[rco_geoms
Assigns Community Org Info] + PP --> PH[phs_properties
Identifies PHS Care properties] + PP --> LC[li_complaints
Analyzes L&I complaint density] + PP --> TC[tree_canopy
Measures tree canopy gaps] + PP --> GC[gun_crimes
Analyzes gun crime density] + PP --> DC[drug_crimes
Density analysis for drug crimes] + PP --> DP[dev_probability
Calculate development probability] + PP --> PPri[park_priority
Labels high-priority park areas] + + %% Updates from city ownership branch + CO --> OT[owner_type
Assigns ownership types] + CO --> CV[conservatorship
Identify conservatorship-eligible properties] + CO --> AP[access_process
Assigns access processes] + + %% Additional dependencies feeding into conservatorship + LV --> CV + DL --> CV + + %% Combining multiple updates for tactical urbanism + UB --> TU[tactical_urbanism
Identify tactical urbanism-eligible properties] + IDB --> TU + + %% Vacant branch updates feeding subsequent functions + CG --> CN[contig_neighbors
Count vacant neighbors] + PPR --> CN + CG --> ND[negligent_devs
Identify negligent developers] + PPR --> ND + + %% Priority level depends on several geometry-based outputs + GC --> PL[priority_level
Add priority levels] + LV --> PL + LC --> PL + TC --> PL + PH --> PL +``` diff --git a/docs/ETL pipeline/DataDict.md b/docs/ETL pipeline/DataDict.md new file mode 100644 index 00000000..b17cdf0b --- /dev/null +++ b/docs/ETL pipeline/DataDict.md @@ -0,0 +1,98 @@ +# New ETL Pipeline + +## Overview + +This document describes the datasets used in the pipeline, including their sources, attributes, update frequency, and known issues. + +## Data Dictionary + +| Column Name | Added by Function | Data Type | Description | Function Known Issues | Source | Function Description | Updated by Functions | +| :------------------------------------ | :-------------------- | :-------- | :----------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------- | +| access_process | access_process | str | The access process for each property based on city ownership and market value. | | | Process a dataset to determine the access process for each property based on city ownership and market value. The result is added as a new column in the dataset. | | +| all_violations_past_year | li_violations | int | Total violations in the past year. | | https://phl.carto.com/api/v2/sql | Process L&I (Licenses and Inspections) data for violations. This function filters and processes L&I violations data, joining it with the primary feature layer based on spatial relationships and OPA (Office of Property Assessment) identifiers. | | +| building_code_description | opa_properties | str | The building code description | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | | +| city_owner_agency | city_owned_properties | str | The agency that owns the city property. | | https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/LAMAAssets/FeatureServer/0/ | Processes city-owned property data by joining it with the primary feature layer, renaming columns, and updating access information for properties based on ownership. All instances where the "city_owner_agency" is "PLB" are changed to "Land Bank (PHDC)". | | +| conservatorship | conservatorship | str | Indicates whether each property qualifies for conservatorship ("Yes" or "No"). | | | Determines conservatorship eligibility for properties in a feature layer. | | +| dev_rank | dev_probability | str | The development rank of the census block group. | | https://phl.carto.com/api/v2/sql | Calculates development probability based on permit counts and assigns development ranks to census block groups. The results are joined to the primary feature layer. | | +| district | council_dists | str | The council district associated with the property. | | | Associates properties in the primary feature layer with council districts using a spatial join. | | +| drug_crimes_density | drug_crimes | float | KDE density of drug crimes. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for drug crimes to the primary feature layer. | | +| drug_crimes_density_label | drug_crimes | str | Categorized density level. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for drug crimes to the primary feature layer. | | +| drug_crimes_density_percentile | drug_crimes | float | Percentile rank of density. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for drug crimes to the primary feature layer. | | +| drug_crimes_density_zscore | drug_crimes | float | Z-score of drug crime density. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for drug crimes to the primary feature layer. | | +| geometry | opa_properties | geometry | The geometry of the property | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | pwd_parcels | +| gun_crimes_density | gun_crimes | float | KDE density of gun crimes. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for gun crimes to the primary feature layer. | | +| gun_crimes_density_label | gun_crimes | str | Categorized density level. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for gun crimes to the primary feature layer. | | +| gun_crimes_density_percentile | gun_crimes | float | Percentile rank of density. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for gun crimes to the primary feature layer. | | +| gun_crimes_density_zscore | gun_crimes | float | Z-score of gun crime density. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for gun crimes to the primary feature layer. | | +| imm_dang_building | imm_dang_buildings | str | Indicates whether each property is categorized as imminently dangerous ("Y" or "N"). | | https://phl.carto.com/api/v2/sql | Adds information about imminently dangerous buildings to the primary feature layer by joining with a dataset of dangerous buildings. | | +| is_actionable | delinquencies | str | Flag for actionable tax delinquency. | | https://phl.carto.com/api/v2/sql | Adds property tax delinquency information to the primary feature layer by joining with a tax delinquencies dataset. | | +| l_and_i_complaints_density | li_complaints | float | KDE density of complaints. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for L&I complaints to the primary feature layer. | | +| l_and_i_complaints_density_label | li_complaints | str | Categorized density level. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for L&I complaints to the primary feature layer. | | +| l_and_i_complaints_density_percentile | li_complaints | float | Percentile rank of density. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for L&I complaints to the primary feature layer. | | +| l_and_i_complaints_density_zscore | li_complaints | float | Z-score of complaint density. | | https://phl.carto.com/api/v2/sql | Applies kernel density estimation (KDE) analysis for L&I complaints to the primary feature layer. | | +| market_value | opa_properties | float | the market value from the OPA data | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | | +| most_recent_year_owed | delinquencies | str | Most recent year owed. | | https://phl.carto.com/api/v2/sql | Adds property tax delinquency information to the primary feature layer by joining with a tax delinquencies dataset. | | +| n_contiguous | contig_neighbors | int | The number of contiguous vacant neighbors for each property. | | | Calculates the number of contiguous vacant neighbors for each property in a feature layer. | | +| n_total_properties_owned | negligent_devs | int | Total number of properties owned by the developer | | | Identifies negligent developers based on the number of vacant properties owned and flags them in the primary feature layer. | | +| n_vacant_properties_owned | negligent_devs | int | Number of vacant properties owned by the developer | | | Identifies negligent developers based on the number of vacant properties owned and flags them in the primary feature layer. | | +| negligent_dev | negligent_devs | bool | non-city owned entities owning 5+ vacant properties | | | Identifies negligent developers based on the number of vacant properties owned and flags them in the primary feature layer. | | +| neighborhood | nbhoods | str | The name of the neighborhood associated with the property. | | https://raw.githubusercontent.com/opendataphilly/open-geo-data/master/philadelphia-neighborhoods/philadelphia-neighborhoods.geojson | Adds neighborhood information to the primary feature layer by performing a spatial join with a neighborhoods dataset. | | +| num_years_owed | delinquencies | int | Number of years owed. | | https://phl.carto.com/api/v2/sql | Adds property tax delinquency information to the primary feature layer by joining with a tax delinquencies dataset. | | +| opa_id | opa_properties | int | the OPA ID of the property | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | | +| open_violations_past_year | li_violations | int | Open violations in the past year. | | https://phl.carto.com/api/v2/sql | Process L&I (Licenses and Inspections) data for violations. This function filters and processes L&I violations data, joining it with the primary feature layer based on spatial relationships and OPA (Office of Property Assessment) identifiers. | | +| owner_1 | opa_properties | str | The first owner of the property | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | | +| owner_2 | opa_properties | str | The second owner of the property | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | | +| owner_type | owner_type | str | The ownership type of the property: Public, Business (LLC) or Individual. | | | Determines the ownership type for each property in the primary feature layer based on the 'owner_1', 'owner_2', and 'city_owner_agency' columns. The ownership type is set as: - "Public" if 'city_owner_agency' is not NA. - "Business (LLC)" if 'city_owner_agency' is NA and "LLC" is found in 'owner_1' or 'owner_2'. - "Individual" if 'city_owner_agency' is NA and "LLC" is not found in 'owner_1' or 'owner_2'. | | +| parcel_type | opa_properties | str | "Land" or "Building" | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | | +| park_priority | park_priority | int | The park priority score. | | https://www.tpl.org/park-data-downloads | Downloads and processes park priority data, then joins it with the primary feature layer. | | +| payment_agreement | delinquencies | str | Indicates if there is a payment agreement. | | https://phl.carto.com/api/v2/sql | Adds property tax delinquency information to the primary feature layer by joining with a tax delinquencies dataset. | | +| permit_count | dev_probability | int | The number of permits issued in the census block group. | | https://phl.carto.com/api/v2/sql | Calculates development probability based on permit counts and assigns development ranks to census block groups. The results are joined to the primary feature layer. | | +| phs_care_program | phs_properties | str | The PHS care program associated with the property. | | | Perform a spatial join between the primary feature layer and the PHS properties layer, then update the primary feature layer with a new column 'phs_care_program' indicating if the property is part of the PHS care program. | | +| priority_level | priority_level | str | The priority level ( "Low", "Medium", or "High") of the property | | gun_crimes_density_zscore, all_violations_past_year, l_and_i_complaints_density_zscore, tree_canopy_gap, phs_care_program columns in the primary feature layer. | Determines priority levels for properties based on gun crime density, violations, tree canopy gaps, and PHS Landcare status. | | +| rco_info | rco_geoms | str | Additional RCO-related information. | | "https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/Zoning_RCO/FeatureServer/0/" | Adds Registered Community Organization (RCO) information to the primary feature layer by performing a spatial join and aggregating RCO data. | | +| rco_names | rco_geoms | str | Names of RCOs associated with the property. | | "https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/Zoning_RCO/FeatureServer/0/" | Adds Registered Community Organization (RCO) information to the primary feature layer by performing a spatial join and aggregating RCO data. | | +| sale_date | opa_properties | str | the date of the last sale | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | | +| sale_price | opa_properties | float | the price of the last sale | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | | +| sheriff_sale | delinquencies | str | Indicates if the property is at risk of sheriff sale. | | https://phl.carto.com/api/v2/sql | Adds property tax delinquency information to the primary feature layer by joining with a tax delinquencies dataset. | | +| side_yard_eligible | city_owned_properties | str | Indicates if the property is eligible for the side yard program. | | https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/LAMAAssets/FeatureServer/0/ | Processes city-owned property data by joining it with the primary feature layer, renaming columns, and updating access information for properties based on ownership. All instances where the "city_owner_agency" is "PLB" are changed to "Land Bank (PHDC)". | | +| standardized_address | opa_properties | str | A standardized mailing address | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | | +| tactical_urbanism | tactical_urbanism | str | Indicates whether each property qualifies for tactical urbanism ("Yes" or "No"). | | | Assigns a 'tactical_urbanism' value to each row in the primary feature layer based on specific conditions. Tactical urbanism is marked as "Yes" if the property is a parcel of type 'Land', and does not have any unsafe or immediately dangerous buildings. Otherwise, it is "No". | | +| total_assessment | delinquencies | float | Total property assessment. | | https://phl.carto.com/api/v2/sql | Adds property tax delinquency information to the primary feature layer by joining with a tax delinquencies dataset. | | +| total_due | delinquencies | float | Total amount owed. | | https://phl.carto.com/api/v2/sql | Adds property tax delinquency information to the primary feature layer by joining with a tax delinquencies dataset. | | +| tree_canopy_gap | tree_canopy | float | The amount of tree canopy lacking. | | https://national-tes-data-share.s3.amazonaws.com/national_tes_share/pa.zip.zip | Adds tree canopy gap information to the primary feature layer by downloading, processing, and spatially joining tree canopy data for Philadelphia County. | | +| unsafe_building | unsafe_buildings | str | Indicates whether each property is categorized as an unsafe building ("Y" or "N"). | | https://phl.carto.com/api/v2/sql | Adds unsafe building information to the primary feature layer by joining with a dataset of unsafe buildings. | | +| vacant | vacant_properties | bool | Indicates whether the property is vacant. | - The vacant land data is below the threshold, so backup data is loaded from GCS. | | Adds a "vacant" column to the primary feature layer based on vacant property data from ESRI layers and backup data from Google Cloud Storage if necessary. | community_gardens -> ppr_properties | +| zip_code | opa_properties | str | The zip code of the property | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | | +| zoning | opa_properties | str | The zoning of the property | | https://phl.carto.com/api/v2/sql | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | | + +## By Function + +| name | start_time | end_time | duration | description | returns | tagline | columns_added | columns_updated | source | known_issues | primary_feature_layer_columns_referenced | +| :-------------------- | :------------------ | :------------------ | :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------- | +| opa_properties | 2025-03-20 01:45:03 | 2025-03-20 01:45:38 | 34.72 seconds | Loads and processes OPA property data, standardizing addresses and cleaning geometries. | FeatureLayer: A feature layer containing processed OPA property data. | Load OPA data | [{'name': 'opa_id', 'description': 'the OPA ID of the property', 'type': 'int'}, {'name': 'market_value', 'description': 'the market value from the OPA data', 'type': 'float'}, {'name': 'sale_date', 'description': 'the date of the last sale', 'type': 'str'}, {'name': 'sale_price', 'description': 'the price of the last sale', 'type': 'float'}, {'name': 'parcel_type', 'description': '"Land" or "Building"', 'type': 'str'}, {'name': 'zip_code', 'description': 'The zip code of the property', 'type': 'str'}, {'name': 'zoning', 'description': 'The zoning of the property', 'type': 'str'}, {'name': 'owner_1', 'description': 'The first owner of the property', 'type': 'str'}, {'name': 'owner_2', 'description': 'The second owner of the property', 'type': 'str'}, {'name': 'building_code_description', 'description': 'The building code description', 'type': 'str'}, {'name': 'standardized_address', 'description': 'A standardized mailing address', 'type': 'str'}, {'name': 'geometry', 'description': 'The geometry of the property', 'type': 'geometry'}] | [] | https://phl.carto.com/api/v2/sql | | [] | +| vacant_properties | 2025-03-20 01:45:38 | 2025-03-20 01:46:06 | 27.54 seconds | Adds a "vacant" column to the primary feature layer based on vacant property data from ESRI layers and backup data from Google Cloud Storage if necessary. | FeatureLayer: The input feature layer with an added "vacant" column. | Identify vacant properties. | [{'name': 'vacant', 'description': 'Indicates whether the property is vacant.', 'type': 'bool'}] | [] | | - The vacant land data is below the threshold, so backup data is loaded from GCS. | ['opa_id'] | +| pwd_parcels | 2025-03-20 01:46:06 | 2025-03-20 01:46:35 | 28.37 seconds | Updates the primary feature layer by replacing its geometry column with validated geometries from PWD parcels data. Retains point geometry for rows with no polygon geometry available. | FeatureLayer: The updated primary feature layer with geometries replaced by those from PWD parcels or retained from the original layer if no match. | Improve geometry with PWD parcels data. | [] | [{'name': 'geometry', 'description': 'The geometry column is updated with validated geometries from PWD parcels.'}] | https://phl.carto.com/api/v2/sql | | ['opa_id', 'geometry'] | +| council_dists | 2025-03-20 01:46:35 | 2025-03-20 01:46:57 | 21.87 seconds | Associates properties in the primary feature layer with council districts using a spatial join. | FeatureLayer: The input feature layer with properties spatially joined to council districts, ensuring no duplicate entries. | Assigns council districts | [{'name': 'district', 'description': 'The council district associated with the property.', 'type': 'str'}] | [] | | | ['opa_id', 'geometry'] | +| nbhoods | 2025-03-20 01:46:58 | 2025-03-20 01:47:06 | 8.58 seconds | Adds neighborhood information to the primary feature layer by performing a spatial join with a neighborhoods dataset. | FeatureLayer: The input feature layer with an added "neighborhood" column, containing the name of the neighborhood for each property. | Assigns neighborhoods | [{'name': 'neighborhood', 'description': 'The name of the neighborhood associated with the property.', 'type': 'str'}] | [] | https://raw.githubusercontent.com/opendataphilly/open-geo-data/master/philadelphia-neighborhoods/philadelphia-neighborhoods.geojson | | ['opa_id', 'geometry'] | +| rco_geoms | 2025-03-20 01:47:07 | 2025-03-20 01:48:06 | 59.03 seconds | Adds Registered Community Organization (RCO) information to the primary feature layer by performing a spatial join and aggregating RCO data. | FeatureLayer: The input feature layer with added RCO-related columns, including aggregated RCO information and names. | Assigns Community Org Info | [{'name': 'rco_names', 'description': 'Names of RCOs associated with the property.', 'type': 'str'}, {'name': 'rco_info', 'description': 'Additional RCO-related information.', 'type': 'str'}] | [] | "https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/Zoning_RCO/FeatureServer/0/" | | ['opa_id', 'geometry'] | +| city_owned_properties | 2025-03-20 01:48:06 | 2025-03-20 01:48:25 | 18.64 seconds | Processes city-owned property data by joining it with the primary feature layer, renaming columns, and updating access information for properties based on ownership. All instances where the "city_owner_agency" is "PLB" are changed to "Land Bank (PHDC)". | FeatureLayer: The updated primary feature layer with processed city ownership information. | Categorizes City Owned Properties | [{'name': 'city_owner_agency', 'description': 'The agency that owns the city property.', 'type': 'str'}, {'name': 'side_yard_eligible', 'description': 'Indicates if the property is eligible for the side yard program.', 'type': 'str'}] | [] | https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/LAMAAssets/FeatureServer/0/ | | ['opa_id', 'owner_1', 'owner2'] | +| phs_properties | 2025-03-20 01:48:25 | 2025-03-20 01:48:56 | 30.57 seconds | Perform a spatial join between the primary feature layer and the PHS properties layer, then update the primary feature layer with a new column 'phs_care_program' indicating if the property is part of the PHS care program. | FeatureLayer: The updated primary feature layer with the 'phs_care_program' column. | Identifies PHS Care properties | [{'name': 'phs_care_program', 'description': 'The PHS care program associated with the property.', 'type': 'str'}] | [] | | | ['opa_id', 'geometry'] | +| community_gardens | 2025-03-20 01:48:57 | 2025-03-20 01:48:59 | 2.13 seconds | Updates the 'vacant' column in the primary feature layer to ensure community gardens are marked as not vacant. This protects known community gardens from being categorized as vacant, preventing potential predatory development. | FeatureLayer: The input feature layer with the 'vacant' column updated to False for parcels containing community gardens. | Mark Community Gardens as Not Vacant | [] | [{'name': 'vacant', 'description': 'Updated to False for parcels containing community gardens.'}] | https://services2.arcgis.com/qjOOiLCYeUtwT7x7/arcgis/rest/services/PHS_NGT_Supported_Current_view/FeatureServer/0/ | | ['opa_id', 'vacant'] | +| ppr_properties | 2025-03-20 01:49:00 | 2025-03-20 01:49:11 | 11.08 seconds | Updates the 'vacant' column in the primary feature layer to ensure PPR properties are marked as not vacant. This prevents PPR properties from being miscategorized as vacant. | FeatureLayer: The updated primary feature layer. | Mark Parks as Not Vacant | [] | [{'name': 'vacant', 'description': 'Updated to False for PPR properties.'}] | https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/PPR_Properties/FeatureServer/0 | If the Ersi REST URL is not available the function will fall back to loading the data from a GeoJSON URL https://opendata.arcgis.com/datasets/d52445160ab14380a673e5849203eb64_0.geojson | ['opa_id', 'geometry', 'vacant', 'public_name'] | +| owner_type | 2025-03-20 01:49:12 | 2025-03-20 01:49:29 | 17.75 seconds | Determines the ownership type for each property in the primary feature layer based on the 'owner_1', 'owner_2', and 'city_owner_agency' columns. The ownership type is set as: - "Public" if 'city_owner_agency' is not NA. - "Business (LLC)" if 'city_owner_agency' is NA and "LLC" is found in 'owner_1' or 'owner_2'. - "Individual" if 'city_owner_agency' is NA and "LLC" is not found in 'owner_1' or 'owner_2'. | FeatureLayer: The updated feature layer with the 'owner_type' column added. | Assigns ownership types | [{'name': 'owner_type', 'description': 'The ownership type of the property: Public, Business (LLC) or Individual.', 'type': 'str'}] | [] | | | ['opa_id', 'owner_1', 'owner_2', 'city_owner_agency'] | +| li_violations | 2025-03-20 01:49:31 | 2025-03-20 01:49:38 | 7.11 seconds | Process L&I (Licenses and Inspections) data for violations. This function filters and processes L&I violations data, joining it with the primary feature layer based on spatial relationships and OPA (Office of Property Assessment) identifiers. | FeatureLayer: The primary feature layer updated with L&I data. | Counts L&I violations | [{'name': 'all_violations_past_year', 'description': 'Total violations in the past year.', 'type': 'int'}, {'name': 'open_violations_past_year', 'description': 'Open violations in the past year.', 'type': 'int'}] | [] | https://phl.carto.com/api/v2/sql | | ['opa_id'] | +| li_complaints | 2025-03-20 01:49:38 | 2025-03-20 02:00:23 | 645.06 seconds | Applies kernel density estimation (KDE) analysis for L&I complaints to the primary feature layer. | FeatureLayer: The input feature layer with KDE analysis results for L&I complaints, including density and derived metrics. | Analyzes L&I complaint density | [{'name': 'l_and_i_complaints_density', 'description': 'KDE density of complaints.', 'type': 'float'}, {'name': 'l_and_i_complaints_density_zscore', 'description': 'Z-score of complaint density.', 'type': 'float'}, {'name': 'l_and_i_complaints_density_label', 'description': 'Categorized density level.', 'type': 'str'}, {'name': 'l_and_i_complaints_density_percentile', 'description': 'Percentile rank of density.', 'type': 'float'}] | [] | https://phl.carto.com/api/v2/sql | | ['geometry'] | +| tree_canopy | 2025-03-20 02:00:25 | 2025-03-20 02:00:37 | 12.59 seconds | Adds tree canopy gap information to the primary feature layer by downloading, processing, and spatially joining tree canopy data for Philadelphia County. | FeatureLayer: The input feature layer with an added "tree_canopy_gap" column indicating the tree canopy gap for each property. | Measures tree canopy gaps. | [{'name': 'tree_canopy_gap', 'description': 'The amount of tree canopy lacking.', 'type': 'float'}] | [] | https://national-tes-data-share.s3.amazonaws.com/national_tes_share/pa.zip.zip | | ['opa_id', 'geometry'] | +| gun_crimes | 2025-03-20 02:00:38 | 2025-03-20 02:01:12 | 34.15 seconds | Applies kernel density estimation (KDE) analysis for gun crimes to the primary feature layer. | FeatureLayer: The input feature layer with KDE analysis results for gun crimes. | Analyzes gun crime density | [{'name': 'gun_crimes_density', 'description': 'KDE density of gun crimes.', 'type': 'float'}, {'name': 'gun_crimes_density_zscore', 'description': 'Z-score of gun crime density.', 'type': 'float'}, {'name': 'gun_crimes_density_label', 'description': 'Categorized density level.', 'type': 'str'}, {'name': 'gun_crimes_density_percentile', 'description': 'Percentile rank of density.', 'type': 'float'}] | [] | https://phl.carto.com/api/v2/sql | | ['geometry'] | +| drug_crimes | 2025-03-20 02:01:13 | 2025-03-20 02:01:47 | 33.43 seconds | Applies kernel density estimation (KDE) analysis for drug crimes to the primary feature layer. | FeatureLayer: The input feature layer with KDE analysis results for drug crimes. | Density analysis for drug crimes | [{'name': 'drug_crimes_density', 'description': 'KDE density of drug crimes.', 'type': 'float'}, {'name': 'drug_crimes_density_zscore', 'description': 'Z-score of drug crime density.', 'type': 'float'}, {'name': 'drug_crimes_density_label', 'description': 'Categorized density level.', 'type': 'str'}, {'name': 'drug_crimes_density_percentile', 'description': 'Percentile rank of density.', 'type': 'float'}] | [] | https://phl.carto.com/api/v2/sql | | ['geometry'] | +| delinquencies | 2025-03-20 02:01:49 | 2025-03-20 02:01:58 | 9.18 seconds | Adds property tax delinquency information to the primary feature layer by joining with a tax delinquencies dataset. | FeatureLayer: The input feature layer with added columns for tax delinquency information, including total due, actionable status, payment agreements, and more. | Summarize tax delinquencies | [{'name': 'total_due', 'description': 'Total amount owed.', 'type': 'float'}, {'name': 'most_recent_year_owed', 'description': 'Most recent year owed.', 'type': 'str'}, {'name': 'num_years_owed', 'description': 'Number of years owed.', 'type': 'int'}, {'name': 'payment_agreement', 'description': 'Indicates if there is a payment agreement.', 'type': 'str'}, {'name': 'is_actionable', 'description': 'Flag for actionable tax delinquency.', 'type': 'str'}, {'name': 'sheriff_sale', 'description': 'Indicates if the property is at risk of sheriff sale.', 'type': 'str'}, {'name': 'total_assessment', 'description': 'Total property assessment.', 'type': 'float'}] | [] | https://phl.carto.com/api/v2/sql | | ['opa_id'] | +| unsafe_buildings | 2025-03-20 02:02:00 | 2025-03-20 02:02:06 | 5.77 seconds | Adds unsafe building information to the primary feature layer by joining with a dataset of unsafe buildings. | FeatureLayer: The input feature layer with an added "unsafe_building" column, indicating whether each property is categorized as an unsafe building ("Y" or "N"). | Identify unsafe buildings | [{'name': 'unsafe_building', 'description': 'Indicates whether each property is categorized as an unsafe building ("Y" or "N").', 'type': 'str'}] | [] | https://phl.carto.com/api/v2/sql | | ['oda_id'] | +| imm_dang_buildings | 2025-03-20 02:02:06 | 2025-03-20 02:02:11 | 4.83 seconds | Adds information about imminently dangerous buildings to the primary feature layer by joining with a dataset of dangerous buildings. | FeatureLayer: The input feature layer with an added "imm_dang_building" column, indicating whether each property is categorized as imminently dangerous ("Y" or "N"). | Identify imminently dangerous buildings | [{'name': 'imm_dang_building', 'description': 'Indicates whether each property is categorized as imminently dangerous ("Y" or "N").', 'type': 'str'}] | [] | https://phl.carto.com/api/v2/sql | | ['opa_id'] | +| contig_neighbors | 2025-03-20 02:02:12 | 2025-03-20 02:02:14 | 1.66 seconds | Calculates the number of contiguous vacant neighbors for each property in a feature layer. | FeatureLayer: The input feature layer with an added "n_contiguous" column indicating the number of contiguous vacant neighbors for each property. | Count vacant neighbors | [{'name': 'n_contiguous', 'description': 'The number of contiguous vacant neighbors for each property.', 'type': 'int'}] | [] | | | ['opa_id', 'vacant'] | +| dev_probability | 2025-03-20 02:02:15 | 2025-03-20 02:02:31 | 15.98 seconds | Calculates development probability based on permit counts and assigns development ranks to census block groups. The results are joined to the primary feature layer. | FeatureLayer: The input feature layer with added spatial join data for development probability and ranks. | Calculate development probability | [{'name': 'permit_count', 'description': 'The number of permits issued in the census block group.', 'type': 'int'}, {'name': 'dev_rank', 'description': 'The development rank of the census block group.', 'type': 'str'}] | [] | https://phl.carto.com/api/v2/sql | | ['opa_id', 'geometry'] | +| negligent_devs | 2025-03-20 02:02:32 | 2025-03-20 02:02:34 | 2.05 seconds | Identifies negligent developers based on the number of vacant properties owned and flags them in the primary feature layer. | FeatureLayer: The input feature layer with additional columns for total properties owned, vacant properties owned, and a "negligent_dev" flag. | Identify negligent developers | [{'name': 'negligent_dev', 'description': 'non-city owned entities owning 5+ vacant properties', 'type': 'bool'}, {'name': 'n_total_properties_owned', 'description': 'Total number of properties owned by the developer', 'type': 'int'}, {'name': 'n_vacant_properties_owned', 'description': 'Number of vacant properties owned by the developer', 'type': 'int'}] | [] | | | ['opa_id', 'vacant', 'city_owner_agency', 'standardized_address'] | +| tactical_urbanism | 2025-03-20 02:02:34 | 2025-03-20 02:02:50 | 15.94 seconds | Assigns a 'tactical_urbanism' value to each row in the primary feature layer based on specific conditions. Tactical urbanism is marked as "Yes" if the property is a parcel of type 'Land', and does not have any unsafe or immediately dangerous buildings. Otherwise, it is "No". | The input FeatureLayer with a new column 'tactical_urbanism' added to its GeoDataFrame. | Identify tactical urbanism-eligible properties | [{'name': 'tactical_urbanism', 'description': 'Indicates whether each property qualifies for tactical urbanism ("Yes" or "No").', 'type': 'str'}] | [] | | | ['parcel_type', 'unsafe_building', 'imm_dang_building'] | +| conservatorship | 2025-03-20 02:02:53 | 2025-03-20 02:03:47 | 53.97 seconds | Determines conservatorship eligibility for properties in a feature layer. | FeatureLayer: The input feature layer with an added "conservatorship" column indicating whether each property qualifies for conservatorship ("Yes" or "No"). | Identify conservatorship-eligible properties | [{'name': 'conservatorship', 'description': 'Indicates whether each property qualifies for conservatorship ("Yes" or "No").', 'type': 'str'}] | [] | | | ['city_owner_agency', 'sheriff_sale', 'market_value', 'all_violations_past_year', 'sale_date'] | +| park_priority | 2025-03-20 02:03:49 | 2025-03-20 02:04:04 | 14.62 seconds | Downloads and processes park priority data, then joins it with the primary feature layer. | FeatureLayer: The primary feature layer with park priority data joined. | Labels high-priority park areas. | [{'name': 'park_priority', 'description': 'The park priority score.', 'type': 'int'}] | [] | https://www.tpl.org/park-data-downloads | | ['opa_id', 'geometry'] | +| priority_level | 2025-03-20 02:04:04 | 2025-03-20 02:04:25 | 20.22 seconds | Determines priority levels for properties based on gun crime density, violations, tree canopy gaps, and PHS Landcare status. | FeatureLayer: The input feature layer with an added "priority_level" column, indicating the priority for each property as "Low", "Medium", or "High". | Add priority levels | [{'name': 'priority_level', 'description': 'The priority level ( "Low", "Medium", or "High") of the property', 'type': 'str'}] | [] | gun_crimes_density_zscore, all_violations_past_year, l_and_i_complaints_density_zscore, tree_canopy_gap, phs_care_program columns in the primary feature layer. | | [] | +| access_process | 2025-03-20 02:04:27 | 2025-03-20 02:04:45 | 17.99 seconds | Process a dataset to determine the access process for each property based on city ownership and market value. The result is added as a new column in the dataset. | Any: The updated dataset with an additional "access_process" column. | Assigns access processes | [{'name': 'access_process', 'description': 'The access process for each property based on city ownership and market value.', 'type': 'str'}] | [] | | | ['city_owner_agency', 'market_value'] | From 8b08427f4cda70d7269b37ab22d81f7780506d8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Mar 2025 12:32:20 -0400 Subject: [PATCH 4/7] deps: bump the all-npm group with 32 updates (#1124) Removed breaking changes from upgrading Tailwind to v4 and React to v19 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Collum --- package-lock.json | 4914 ++++++++++------- package.json | 50 +- .../find-properties/[[...opa_id]]/page.tsx | 2 +- src/components/Filters/MultiSelect.tsx | 4 +- src/components/InfoGraphicSection.tsx | 1 + src/components/MapLegendControl/MapLegend.tsx | 7 +- .../MapLegendControl/MapLegendControl.tsx | 2 +- .../PropertyAccessOptionContainer.tsx | 32 +- src/components/PropertyMap.tsx | 3 +- src/components/SinglePropertyDetail.tsx | 8 +- src/config/config.ts | 3 +- 11 files changed, 2914 insertions(+), 2112 deletions(-) diff --git a/package-lock.json b/package-lock.json index fa4dc228..776a9a41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,52 +8,52 @@ "name": "phl-vacancy-dashboard-app", "version": "1.0.0", "dependencies": { - "@heroicons/react": "^2.1.5", - "@maptiler/geocoding-control": "^1.4.1", - "@maptiler/sdk": "^2.5.1", + "@heroicons/react": "^2.2.0", + "@maptiler/geocoding-control": "^2.1.6", + "@maptiler/sdk": "^3.0.1", "@nextui-org/react": "^2.4.6", "@phosphor-icons/react": "^2.1.7", - "@turf/centroid": "^7.0.0", - "autoprefixer": "10.4.19", + "@turf/centroid": "^7.2.0", + "autoprefixer": "10.4.21", "clsx": "^2.1.1", - "framer-motion": "^11.3.8", + "framer-motion": "^12.5.0", "lodash": "^4.17.21", - "maplibre-gl": "^4.5.0", + "maplibre-gl": "^5.2.0", "multi-range-slider-react": "^2.0.7", "next": "^14.2.5", - "pmtiles": "^3.0.6", - "postcss": "8.4.39", + "pmtiles": "^4.3.0", + "postcss": "8.5.3", "protobufjs": "^7.3.2", "react": "18.3.1", "react-dom": "18.3.1", - "react-icons": "^5.2.1", - "react-map-gl": "^7.1.7", + "react-icons": "^5.5.0", + "react-map-gl": "^8.0.1", "sharp": "^0.33.4", "tailwindcss": "^3.4.6", - "typescript": "5.5.3" + "typescript": "5.8.2" }, "devDependencies": { "@semantic-release/changelog": "^6.0.3", - "@semantic-release/commit-analyzer": "^13.0.0", + "@semantic-release/commit-analyzer": "^13.0.1", "@semantic-release/git": "^10.0.1", - "@semantic-release/github": "^10.1.1", + "@semantic-release/github": "^11.0.1", "@semantic-release/npm": "^12.0.1", - "@semantic-release/release-notes-generator": "^14.0.1", - "@types/node": "^20.14.11", + "@semantic-release/release-notes-generator": "^14.0.3", + "@types/node": "^22.13.11", "@types/pbf": "^3.0.5", - "@types/pg": "^8.11.6", + "@types/pg": "^8.11.11", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.16.1", - "@typescript-eslint/parser": "^7.16.1", - "eslint": "^8.56.0", - "eslint-config-next": "^14.2.5", - "eslint-config-prettier": "^9.1.0", + "@typescript-eslint/eslint-plugin": "^8.27.0", + "@typescript-eslint/parser": "^8.27.0", + "eslint": "^9.22.0", + "eslint-config-next": "^15.2.3", + "eslint-config-prettier": "^10.1.1", "eslint-plugin-custom-rules": "file:./eslint-plugin-custom-rules", - "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-prettier": "^5.2.3", "eslint-plugin-react": "^7.34.4", - "postcss-nesting": "^12.1.5", - "postcss-preset-env": "^9.6.0", + "postcss-nesting": "^13.0.1", + "postcss-preset-env": "^10.1.5", "semantic-release": "^24.0.0" } }, @@ -66,6 +66,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -182,9 +183,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz", - "integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", + "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -204,9 +205,9 @@ } }, "node_modules/@csstools/cascade-layer-name-parser": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-1.0.13.tgz", - "integrity": "sha512-MX0yLTwtZzr82sQ0zOjqimpZbzjMaK/h2pmlrLK7DCzlmiZLYFpoO94WmN1akRVo6ll/TdpHb53vihHLUMyvng==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-2.0.4.tgz", + "integrity": "sha512-7DFHlPuIxviKYZrOiwVU/PiHLm3lLUR23OMuEEtfEOQTOp9hzQ2JjdY6X5H18RVuUPJqSCI+qNnD5iOLMVE0bA==", "dev": true, "funding": [ { @@ -218,18 +219,19 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1" + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" } }, "node_modules/@csstools/color-helpers": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-4.2.1.tgz", - "integrity": "sha512-CEypeeykO9AN7JWkr1OEOQb0HRzZlPWGwV0Ya6DuVgFdDi6g3ma/cPZ5ZPZM4AWQikDpq/0llnGGlIL+j8afzw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", + "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", "dev": true, "funding": [ { @@ -241,14 +243,15 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" } }, "node_modules/@csstools/css-calc": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-1.2.4.tgz", - "integrity": "sha512-tfOuvUQeo7Hz+FcuOd3LfXVp+342pnWUJ7D2y8NUpu1Ww6xnTbHLpz018/y6rtbHifJ3iIEf9ttxXd8KG7nL0Q==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.2.tgz", + "integrity": "sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==", "dev": true, "funding": [ { @@ -260,18 +263,19 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1" + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" } }, "node_modules/@csstools/css-color-parser": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-2.0.5.tgz", - "integrity": "sha512-lRZSmtl+DSjok3u9hTWpmkxFZnz7stkbZxzKc08aDUsdrWwhSgWo8yq9rq9DaFUtbAyAq2xnH92fj01S+pwIww==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.8.tgz", + "integrity": "sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==", "dev": true, "funding": [ { @@ -283,22 +287,23 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^4.2.1", - "@csstools/css-calc": "^1.2.4" + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.2" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1" + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" } }, "node_modules/@csstools/css-parser-algorithms": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.7.1.tgz", - "integrity": "sha512-2SJS42gxmACHgikc1WGesXLIT8d/q2l0UFM7TaEeIzdFCE/FPMtTiizcPGGJtlPo2xuQzY09OhrLTzRxqJqwGw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", + "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", "dev": true, "funding": [ { @@ -310,17 +315,18 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { - "@csstools/css-tokenizer": "^2.4.1" + "@csstools/css-tokenizer": "^3.0.3" } }, "node_modules/@csstools/css-tokenizer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.4.1.tgz", - "integrity": "sha512-eQ9DIktFJBhGjioABJRtUucoWR2mwllurfnM8LuNGAqX3ViZXaUchqk+1s7jjtkFiT9ySdACsFEA3etErkALUg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", "dev": true, "funding": [ { @@ -332,14 +338,15 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" } }, "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.13.tgz", - "integrity": "sha512-XaHr+16KRU9Gf8XLi3q8kDlI18d5vzKSKCY510Vrtc9iNR0NJzbY9hhTmwhzYZj/ZwGL4VmB3TA9hJW0Um2qFA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz", + "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==", "dev": true, "funding": [ { @@ -351,18 +358,19 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1" + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" } }, "node_modules/@csstools/postcss-cascade-layers": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-4.0.6.tgz", - "integrity": "sha512-Xt00qGAQyqAODFiFEJNkTpSUz5VfYqnDLECdlA/Vv17nl/OIV5QfTRHGAXrBGG5YcJyHpJ+GF9gF/RZvOQz4oA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-5.0.1.tgz", + "integrity": "sha512-XOfhI7GShVcKiKwmPAnWSqd2tBR0uxt+runAxttbSp/LY2U16yAVPmAf7e9q4JJ0d+xMNmpwNDLBXnmRCl3HMQ==", "dev": true, "funding": [ { @@ -374,21 +382,22 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/selector-specificity": "^3.1.1", - "postcss-selector-parser": "^6.0.13" + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-color-function": { - "version": "3.0.19", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-3.0.19.tgz", - "integrity": "sha512-d1OHEXyYGe21G3q88LezWWx31ImEDdmINNDy0LyLNN9ChgN2bPxoubUPiHf9KmwypBMaHmNcMuA/WZOKdZk/Lg==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-4.0.8.tgz", + "integrity": "sha512-9dUvP2qpZI6PlGQ/sob+95B3u5u7nkYt9yhZFCC7G9HBRHBxj+QxS/wUlwaMGYW0waf+NIierI8aoDTssEdRYw==", "dev": true, "funding": [ { @@ -400,24 +409,25 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0" + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-color-mix-function": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-2.0.19.tgz", - "integrity": "sha512-mLvQlMX+keRYr16AuvuV8WYKUwF+D0DiCqlBdvhQ0KYEtcQl9/is9Ssg7RcIys8x0jIn2h1zstS4izckdZj9wg==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.8.tgz", + "integrity": "sha512-yuZpgWUzqZWQhEqfvtJufhl28DgO9sBwSbXbf/59gejNuvZcoUTRGQZhzhwF4ccqb53YAGB+u92z9+eSKoB4YA==", "dev": true, "funding": [ { @@ -429,24 +439,25 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0" + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-content-alt-text": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-1.0.0.tgz", - "integrity": "sha512-SkHdj7EMM/57GVvSxSELpUg7zb5eAndBeuvGwFzYtU06/QXJ/h9fuK7wO5suteJzGhm3GDF/EWPCdWV2h1IGHQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.4.tgz", + "integrity": "sha512-YItlZUOuZJCBlRaCf8Aucc1lgN41qYGALMly0qQllrxYJhiyzlI6RxOTMUvtWk+KhS8GphMDsDhKQ7KTPfEMSw==", "dev": true, "funding": [ { @@ -458,23 +469,24 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0" + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-exponential-functions": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-1.0.9.tgz", - "integrity": "sha512-x1Avr15mMeuX7Z5RJUl7DmjhUtg+Amn5DZRD0fQ2TlTFTcJS8U1oxXQ9e5mA62S2RJgUU6db20CRoJyDvae2EQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-2.0.7.tgz", + "integrity": "sha512-XTb6Mw0v2qXtQYRW9d9duAjDnoTbBpsngD7sRNLmYDjvwU2ebpIHplyxgOeo6jp/Kr52gkLi5VaK5RDCqzMzZQ==", "dev": true, "funding": [ { @@ -486,22 +498,23 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-calc": "^1.2.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1" + "@csstools/css-calc": "^2.1.2", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-font-format-keywords": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-3.0.2.tgz", - "integrity": "sha512-E0xz2sjm4AMCkXLCFvI/lyl4XO6aN1NCSMMVEOngFDJ+k2rDwfr6NDjWljk1li42jiLNChVX+YFnmfGCigZKXw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-4.0.0.tgz", + "integrity": "sha512-usBzw9aCRDvchpok6C+4TXC57btc4bJtmKQWOHQxOVKen1ZfVqBUuCZ/wuqdX5GHsD0NRSr9XTP+5ID1ZZQBXw==", "dev": true, "funding": [ { @@ -513,21 +526,22 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/utilities": "^1.0.0", + "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-gamut-mapping": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-1.0.11.tgz", - "integrity": "sha512-KrHGsUPXRYxboXmJ9wiU/RzDM7y/5uIefLWKFSc36Pok7fxiPyvkSHO51kh+RLZS1W5hbqw9qaa6+tKpTSxa5g==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.8.tgz", + "integrity": "sha512-/K8u9ZyGMGPjmwCSIjgaOLKfic2RIGdFHHes84XW5LnmrvdhOTVxo255NppHi3ROEvoHPW7MplMJgjZK5Q+TxA==", "dev": true, "funding": [ { @@ -539,22 +553,23 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1" + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-gradients-interpolation-method": { - "version": "4.0.20", - "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-4.0.20.tgz", - "integrity": "sha512-ZFl2JBHano6R20KB5ZrB8KdPM2pVK0u+/3cGQ2T8VubJq982I2LSOvQ4/VtxkAXjkPkk1rXt4AD1ni7UjTZ1Og==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.8.tgz", + "integrity": "sha512-CoHQ/0UXrvxLovu0ZeW6c3/20hjJ/QRg6lyXm3dZLY/JgvRU6bdbQZF/Du30A4TvowfcgvIHQmP1bNXUxgDrAw==", "dev": true, "funding": [ { @@ -566,24 +581,25 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0" + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-hwb-function": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-3.0.18.tgz", - "integrity": "sha512-3ifnLltR5C7zrJ+g18caxkvSRnu9jBBXCYgnBznRjxm6gQJGnnCO9H6toHfywNdNr/qkiVf2dymERPQLDnjLRQ==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.8.tgz", + "integrity": "sha512-LpFKjX6hblpeqyych1cKmk+3FJZ19QmaJtqincySoMkbkG/w2tfbnO5oE6mlnCTXcGUJ0rCEuRHvTqKK0nHYUQ==", "dev": true, "funding": [ { @@ -595,24 +611,25 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0" + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-ic-unit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-3.0.7.tgz", - "integrity": "sha512-YoaNHH2wNZD+c+rHV02l4xQuDpfR8MaL7hD45iJyr+USwvr0LOheeytJ6rq8FN6hXBmEeoJBeXXgGmM8fkhH4g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.0.tgz", + "integrity": "sha512-9QT5TDGgx7wD3EEMN3BSUG6ckb6Eh5gSPT5kZoVtUuAonfPmLDJyPhqR4ntPpMYhUKAMVKAg3I/AgzqHMSeLhA==", "dev": true, "funding": [ { @@ -624,22 +641,23 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-initial": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-initial/-/postcss-initial-1.0.1.tgz", - "integrity": "sha512-wtb+IbUIrIf8CrN6MLQuFR7nlU5C7PwuebfeEXfjthUha1+XZj2RVi+5k/lukToA24sZkYAiSJfHM8uG/UZIdg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-initial/-/postcss-initial-2.0.1.tgz", + "integrity": "sha512-L1wLVMSAZ4wovznquK0xmC7QSctzO4D0Is590bxpGqhqjboLXYA16dWZpfwImkdOgACdQ9PqXsuRroW6qPlEsg==", "dev": true, "funding": [ { @@ -651,17 +669,18 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-is-pseudo-class": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-4.0.8.tgz", - "integrity": "sha512-0aj591yGlq5Qac+plaWCbn5cpjs5Sh0daovYUKJUOMjIp70prGH/XPLp7QjxtbFXz3CTvb0H9a35dpEuIuUi3Q==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.1.tgz", + "integrity": "sha512-JLp3POui4S1auhDR0n8wHd/zTOWmMsmK3nQd3hhL6FhWPaox5W7j1se6zXOG/aP07wV2ww0lxbKYGwbBszOtfQ==", "dev": true, "funding": [ { @@ -673,21 +692,22 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/selector-specificity": "^3.1.1", - "postcss-selector-parser": "^6.0.13" + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-light-dark-function": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-1.0.8.tgz", - "integrity": "sha512-x0UtpCyVnERsplUeoaY6nEtp1HxTf4lJjoK/ULEm40DraqFfUdUSt76yoOyX5rGY6eeOUOkurHyYlFHVKv/pew==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.7.tgz", + "integrity": "sha512-ZZ0rwlanYKOHekyIPaU+sVm3BEHCe+Ha0/px+bmHe62n0Uc1lL34vbwrLYn6ote8PHlsqzKeTQdIejQCJ05tfw==", "dev": true, "funding": [ { @@ -699,23 +719,24 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0" + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-logical-float-and-clear": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-2.0.1.tgz", - "integrity": "sha512-SsrWUNaXKr+e/Uo4R/uIsqJYt3DaggIh/jyZdhy/q8fECoJSKsSMr7nObSLdvoULB69Zb6Bs+sefEIoMG/YfOA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-3.0.0.tgz", + "integrity": "sha512-SEmaHMszwakI2rqKRJgE+8rpotFfne1ZS6bZqBoQIicFyV+xT1UF42eORPxJkVJVrH9C0ctUgwMSn3BLOIZldQ==", "dev": true, "funding": [ { @@ -727,17 +748,18 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-logical-overflow": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overflow/-/postcss-logical-overflow-1.0.1.tgz", - "integrity": "sha512-Kl4lAbMg0iyztEzDhZuQw8Sj9r2uqFDcU1IPl+AAt2nue8K/f1i7ElvKtXkjhIAmKiy5h2EY8Gt/Cqg0pYFDCw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overflow/-/postcss-logical-overflow-2.0.0.tgz", + "integrity": "sha512-spzR1MInxPuXKEX2csMamshR4LRaSZ3UXVaRGjeQxl70ySxOhMpP2252RAFsg8QyyBXBzuVOOdx1+bVO5bPIzA==", "dev": true, "funding": [ { @@ -749,17 +771,18 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-logical-overscroll-behavior": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overscroll-behavior/-/postcss-logical-overscroll-behavior-1.0.1.tgz", - "integrity": "sha512-+kHamNxAnX8ojPCtV8WPcUP3XcqMFBSDuBuvT6MHgq7oX4IQxLIXKx64t7g9LiuJzE7vd06Q9qUYR6bh4YnGpQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overscroll-behavior/-/postcss-logical-overscroll-behavior-2.0.0.tgz", + "integrity": "sha512-e/webMjoGOSYfqLunyzByZj5KKe5oyVg/YSbie99VEaSDE2kimFm0q1f6t/6Jo+VVCQ/jbe2Xy+uX+C4xzWs4w==", "dev": true, "funding": [ { @@ -771,17 +794,18 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-logical-resize": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-2.0.1.tgz", - "integrity": "sha512-W5Gtwz7oIuFcKa5SmBjQ2uxr8ZoL7M2bkoIf0T1WeNqljMkBrfw1DDA8/J83k57NQ1kcweJEjkJ04pUkmyee3A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-3.0.0.tgz", + "integrity": "sha512-DFbHQOFW/+I+MY4Ycd/QN6Dg4Hcbb50elIJCfnwkRTCX05G11SwViI5BbBlg9iHRl4ytB7pmY5ieAFk3ws7yyg==", "dev": true, "funding": [ { @@ -793,20 +817,21 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-logical-viewport-units": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-2.0.11.tgz", - "integrity": "sha512-ElITMOGcjQtvouxjd90WmJRIw1J7KMP+M+O87HaVtlgOOlDt1uEPeTeii8qKGe2AiedEp0XOGIo9lidbiU2Ogg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-3.0.3.tgz", + "integrity": "sha512-OC1IlG/yoGJdi0Y+7duz/kU/beCwO+Gua01sD6GtOtLi7ByQUpcIqs7UE/xuRPay4cHgOMatWdnDdsIDjnWpPw==", "dev": true, "funding": [ { @@ -818,21 +843,22 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/utilities": "^1.0.0" + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-media-minmax": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-1.1.8.tgz", - "integrity": "sha512-KYQCal2i7XPNtHAUxCECdrC7tuxIWQCW+s8eMYs5r5PaAiVTeKwlrkRS096PFgojdNCmHeG0Cb7njtuNswNf+w==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-2.0.7.tgz", + "integrity": "sha512-LB6tIP7iBZb5CYv8iRenfBZmbaG3DWNEziOnPjGoQX5P94FBPvvTBy68b/d9NnS5PELKwFmmOYsAEIgEhDPCHA==", "dev": true, "funding": [ { @@ -844,23 +870,24 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "dependencies": { - "@csstools/css-calc": "^1.2.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/media-query-list-parser": "^2.1.13" + "@csstools/css-calc": "^2.1.2", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/media-query-list-parser": "^4.0.2" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-2.0.11.tgz", - "integrity": "sha512-YD6jrib20GRGQcnOu49VJjoAnQ/4249liuz7vTpy/JfgqQ1Dlc5eD4HPUMNLOw9CWey9E6Etxwf/xc/ZF8fECA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-3.0.4.tgz", + "integrity": "sha512-AnGjVslHMm5xw9keusQYvjVWvuS7KWK+OJagaG0+m9QnIjZsrysD2kJP/tr/UJIyYtMCtu8OkUd+Rajb4DqtIQ==", "dev": true, "funding": [ { @@ -872,22 +899,23 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/media-query-list-parser": "^2.1.13" + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/media-query-list-parser": "^4.0.2" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-nested-calc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-3.0.2.tgz", - "integrity": "sha512-ySUmPyawiHSmBW/VI44+IObcKH0v88LqFe0d09Sb3w4B1qjkaROc6d5IA3ll9kjD46IIX/dbO5bwFN/swyoyZA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-4.0.0.tgz", + "integrity": "sha512-jMYDdqrQQxE7k9+KjstC3NbsmC063n1FTPLCgCRS2/qHUbHM0mNy9pIn4QIiQGs9I/Bg98vMqw7mJXBxa0N88A==", "dev": true, "funding": [ { @@ -899,21 +927,22 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/utilities": "^1.0.0", + "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-normalize-display-values": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-3.0.2.tgz", - "integrity": "sha512-fCapyyT/dUdyPtrelQSIV+d5HqtTgnNP/BEG9IuhgXHt93Wc4CfC1bQ55GzKAjWrZbgakMQ7MLfCXEf3rlZJOw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.0.tgz", + "integrity": "sha512-HlEoG0IDRoHXzXnkV4in47dzsxdsjdz6+j7MLjaACABX2NfvjFS6XVAnpaDyGesz9gK2SC7MbNwdCHusObKJ9Q==", "dev": true, "funding": [ { @@ -925,20 +954,21 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-oklab-function": { - "version": "3.0.19", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-3.0.19.tgz", - "integrity": "sha512-e3JxXmxjU3jpU7TzZrsNqSX4OHByRC3XjItV3Ieo/JEQmLg5rdOL4lkv/1vp27gXemzfNt44F42k/pn0FpE21Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.8.tgz", + "integrity": "sha512-+5aPsNWgxohXoYNS1f+Ys0x3Qnfehgygv3qrPyv+Y25G0yX54/WlVB+IXprqBLOXHM1gsVF+QQSjlArhygna0Q==", "dev": true, "funding": [ { @@ -950,24 +980,25 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0" + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-progressive-custom-properties": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-3.3.0.tgz", - "integrity": "sha512-W2oV01phnILaRGYPmGFlL2MT/OgYjQDrL9sFlbdikMFi6oQkFki9B86XqEWR7HCsTZFVq7dbzr/o71B75TKkGg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.0.0.tgz", + "integrity": "sha512-XQPtROaQjomnvLUSy/bALTR5VCtTVUFwYs1SblvYgLSeTo2a/bMNwUwo2piXw5rTv/FEYiy5yPSXBqg9OKUx7Q==", "dev": true, "funding": [ { @@ -979,20 +1010,49 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-random-function": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-random-function/-/postcss-random-function-1.0.3.tgz", + "integrity": "sha512-dbNeEEPHxAwfQJ3duRL5IPpuD77QAHtRl4bAHRs0vOVhVbHrsL7mHnwe0irYjbs9kYwhAHZBQTLBgmvufPuRkA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.2", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + }, + "engines": { + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-relative-color-syntax": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-2.0.19.tgz", - "integrity": "sha512-MxUMSNvio1WwuS6WRLlQuv6nNPXwIWUFzBBAvL/tBdWfiKjiJnAa6eSSN5gtaacSqUkQ/Ce5Z1OzLRfeaWhADA==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.8.tgz", + "integrity": "sha512-eGE31oLnJDoUysDdjS9MLxNZdtqqSxjDXMdISpLh80QMaYrKs7VINpid34tWQ+iU23Wg5x76qAzf1Q/SLLbZVg==", "dev": true, "funding": [ { @@ -1004,24 +1064,25 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0" + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/@csstools/postcss-scope-pseudo-class": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-3.0.1.tgz", - "integrity": "sha512-3ZFonK2gfgqg29gUJ2w7xVw2wFJ1eNWVDONjbzGkm73gJHVCYK5fnCqlLr+N+KbEfv2XbWAO0AaOJCFB6Fer6A==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-4.0.1.tgz", + "integrity": "sha512-IMi9FwtH6LMNuLea1bjVMQAsUhFxJnyLSgOp/cpv5hrzWmrUYU5fm0EguNDIIOHUqzXode8F/1qkC/tEo/qN8Q==", "dev": true, "funding": [ { @@ -1033,20 +1094,21 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "postcss-selector-parser": "^6.0.13" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-stepped-value-functions": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-3.0.10.tgz", - "integrity": "sha512-MZwo0D0TYrQhT5FQzMqfy/nGZ28D1iFtpN7Su1ck5BPHS95+/Y5O9S4kEvo76f2YOsqwYcT8ZGehSI1TnzuX2g==", + "node_modules/@csstools/postcss-sign-functions": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.1.2.tgz", + "integrity": "sha512-4EcAvXTUPh7n6UoZZkCzgtCf/wPzMlTNuddcKg7HG8ozfQkUcHsJ2faQKeLmjyKdYPyOUn4YA7yDPf8K/jfIxw==", "dev": true, "funding": [ { @@ -1058,22 +1120,23 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-calc": "^1.2.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1" + "@csstools/css-calc": "^2.1.2", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-text-decoration-shorthand": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-3.0.7.tgz", - "integrity": "sha512-+cptcsM5r45jntU6VjotnkC9GteFR7BQBfZ5oW7inLCxj7AfLGAzMbZ60hKTP13AULVZBdxky0P8um0IBfLHVA==", + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-4.0.7.tgz", + "integrity": "sha512-rdrRCKRnWtj5FyRin0u/gLla7CIvZRw/zMGI1fVJP0Sg/m1WGicjPVHRANL++3HQtsiXKAbPrcPr+VkyGck0IA==", "dev": true, "funding": [ { @@ -1085,21 +1148,23 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/color-helpers": "^4.2.1", - "postcss-value-parser": "^4.2.0" + "@csstools/css-calc": "^2.1.2", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-trigonometric-functions": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-3.0.10.tgz", - "integrity": "sha512-G9G8moTc2wiad61nY5HfvxLiM/myX0aYK4s1x8MQlPH29WDPxHQM7ghGgvv2qf2xH+rrXhztOmjGHJj4jsEqXw==", + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.2.tgz", + "integrity": "sha512-8XvCRrFNseBSAGxeaVTaNijAu+FzUvjwFXtcrynmazGb/9WUdsPCpBX+mHEHShVRq47Gy4peYAoxYs8ltUnmzA==", "dev": true, "funding": [ { @@ -1111,22 +1176,22 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-calc": "^1.2.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1" + "@csstools/color-helpers": "^5.0.2", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, - "node_modules/@csstools/postcss-unset-value": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-3.0.1.tgz", - "integrity": "sha512-dbDnZ2ja2U8mbPP0Hvmt2RMEGBiF1H7oY6HYSpjteXJGihYwgxgTr6KRbbJ/V6c+4wd51M+9980qG4gKVn5ttg==", + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-4.0.7.tgz", + "integrity": "sha512-qTrZgLju3AV7Djhzuh2Bq/wjFqbcypnk0FhHjxW8DWJQcZLS1HecIus4X2/RLch1ukX7b+YYCdqbEnpIQO5ccg==", "dev": true, "funding": [ { @@ -1138,17 +1203,23 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.2", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, - "node_modules/@csstools/selector-resolve-nested": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-1.1.0.tgz", - "integrity": "sha512-uWvSaeRcHyeNenKg8tp17EVDRkpflmdyvbE0DHo6D/GdBb6PDnCYYU6gRpXhtICMGMcahQmj2zGxwFM/WC8hCg==", + "node_modules/@csstools/postcss-unset-value": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-4.0.0.tgz", + "integrity": "sha512-cBz3tOCI5Fw6NIFEwU3RiwK6mn3nKegjpJuzCndoGq3BZPkUjnsq7uQmIeMNeMbMk7YD2MfKcgCpZwX5jyXqCA==", "dev": true, "funding": [ { @@ -1160,17 +1231,18 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { - "postcss-selector-parser": "^6.0.13" + "postcss": "^8.4" } }, "node_modules/@csstools/selector-specificity": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.1.1.tgz", - "integrity": "sha512-a7cxGcJ2wIlMFLlh8z2ONm+715QkPHiyJcxwQlKOz/03GPw1COpfhcmC9wm4xlZfp//jWHNNMwzjtqHXVWU9KA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", "dev": true, "funding": [ { @@ -1182,17 +1254,18 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { - "postcss-selector-parser": "^6.0.13" + "postcss-selector-parser": "^7.0.0" } }, "node_modules/@csstools/utilities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-1.0.0.tgz", - "integrity": "sha512-tAgvZQe/t2mlvpNosA4+CkMiZ2azISW5WPAcdSalZlEjQvUfghHxfQcrCiK/7/CrfAWVxyM88kGFYO82heIGDg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-2.0.0.tgz", + "integrity": "sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==", "dev": true, "funding": [ { @@ -1204,17 +1277,42 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, + "node_modules/@emnapi/core": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.3.1.tgz", + "integrity": "sha512-pVGjBIt1Y6gg3EJN8jTcfpP/+uuRksIo055oE/OBkDNcjZqVbfkWCksG1Jp4yZnj3iKWyWX8fdG/j6UDYPbFog==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.1", + "tslib": "^2.4.0" + } + }, "node_modules/@emnapi/runtime": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", - "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", + "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", + "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "dev": true, + "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" @@ -1236,24 +1334,88 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", + "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", + "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -1261,7 +1423,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -1272,6 +1434,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1282,6 +1445,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1290,12 +1454,37 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", + "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", + "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.12.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@formatjs/ecma402-abstract": { @@ -1350,52 +1539,54 @@ } }, "node_modules/@heroicons/react": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.1.5.tgz", - "integrity": "sha512-FuzFN+BsHa+7OxbvAERtgBTNeZpUjgM/MIizfVkSCL2/edriN0Hx/DWRCR//aPYwO5QX/YlgLGXk+E3PcfZwjA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz", + "integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==", + "license": "MIT", "peerDependencies": { - "react": ">= 16" + "react": ">= 16 || ^19.0.0-rc" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, + "license": "Apache-2.0", "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "brace-expansion": "^1.1.7" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": "*" + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, @@ -1407,12 +1598,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.33.5", @@ -1797,6 +1995,7 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -1813,6 +2012,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -1824,6 +2024,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -1835,9 +2036,10 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -1851,6 +2053,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -1859,6 +2062,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -1866,12 +2070,14 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -1947,17 +2153,17 @@ } }, "node_modules/@maplibre/maplibre-gl-style-spec": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-20.3.1.tgz", - "integrity": "sha512-5ueL4UDitzVtceQ8J4kY+Px3WK+eZTsmGwha3MBKHKqiHvKrjWWwBCIl1K8BuJSc5OFh83uI8IFNoFvQxX2uUw==", + "version": "23.1.0", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-23.1.0.tgz", + "integrity": "sha512-R6/ihEuC5KRexmKIYkWqUv84Gm+/QwsOUgHyt1yy2XqCdGdLvlBWVWIIeTZWN4NGdwmY6xDzdSGU2R9oBLNg2w==", + "license": "ISC", "dependencies": { "@mapbox/jsonlint-lines-primitives": "~2.0.2", "@mapbox/unitbezier": "^0.0.1", "json-stringify-pretty-compact": "^4.0.0", "minimist": "^1.2.8", - "quickselect": "^2.0.0", + "quickselect": "^3.0.0", "rw": "^1.3.3", - "sort-object": "^3.0.3", "tinyqueue": "^3.0.0" }, "bin": { @@ -1966,11 +2172,6 @@ "gl-style-validate": "dist/gl-style-validate.mjs" } }, - "node_modules/@maplibre/maplibre-gl-style-spec/node_modules/tinyqueue": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", - "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==" - }, "node_modules/@maptiler/client": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@maptiler/client/-/client-2.2.0.tgz", @@ -1981,23 +2182,24 @@ } }, "node_modules/@maptiler/geocoding-control": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@maptiler/geocoding-control/-/geocoding-control-1.4.1.tgz", - "integrity": "sha512-/NMM8oaKKAdF36KbJuucJc18RaY+VpwkJ2V098yoG7H+9K7Rkyen+XKuLDA8gmvrgTeX1m48Pb9RP+e5zCrRvA==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@maptiler/geocoding-control/-/geocoding-control-2.1.6.tgz", + "integrity": "sha512-2XR70DneLibrpb5wPC8Ht+HwHok7yhC9MGji9ZdEY9r+64qnGCdHodPZcxf+l0p3FqRyTeFZeo+028wmTOKpoQ==", + "license": "BSD-3-Clause", "dependencies": { - "@turf/bbox": "^7.1.0", - "@turf/clone": "^7.1.0", - "@turf/difference": "^7.1.0", - "@turf/flatten": "^7.1.0", - "@turf/union": "^7.1.0", - "geo-coordinates-parser": "^1.7.3" + "@turf/bbox": "^7.2.0", + "@turf/clone": "^7.2.0", + "@turf/difference": "^7.2.0", + "@turf/flatten": "^7.2.0", + "@turf/union": "^7.2.0", + "geo-coordinates-parser": "^1.7.4" }, "peerDependencies": { - "@maptiler/sdk": "^1 || ^2", + "@maptiler/sdk": "^1 || ^2 || ^3", "leaflet": "^1.7 || ^1.8 || ^1.9", - "maplibre-gl": "^2 || ^3 || ^4", + "maplibre-gl": "^2 || ^3 || ^4 || ^5", "ol": "^6 || ^7 || ^8 || ^9 || ^10", - "react": "^17 || ^18", + "react": "^17 || ^18 || ^19", "svelte": "^4.2" }, "peerDependenciesMeta": { @@ -2022,37 +2224,82 @@ } }, "node_modules/@maptiler/sdk": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@maptiler/sdk/-/sdk-2.5.1.tgz", - "integrity": "sha512-JKFzSjsDTkbJhqshtPwkl6P3Yf5XZzdbfUQZdSutQb6BatR9kuxhdX5in9A3vHTUjgjTwoQQ4pCvhvK7cnAuGA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@maptiler/sdk/-/sdk-3.0.1.tgz", + "integrity": "sha512-81CeL/brKTY0Qp1SPd6aexaXUpFAmsoLaPFi62zugdG/hUYuavBupLirF+qnOJOW6j+MWFWLdsUFRaORtRrKzQ==", "license": "BSD-3-Clause", "dependencies": { - "@maplibre/maplibre-gl-style-spec": "^20.3.1", + "@maplibre/maplibre-gl-style-spec": "^23.0.0", "@maptiler/client": "^2.2.0", "events": "^3.3.0", - "js-base64": "^3.7.4", - "maplibre-gl": "4.7.1", - "uuid": "^9.0.0" + "js-base64": "^3.7.7", + "maplibre-gl": "^5.0.1", + "uuid": "^11.0.5" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.7.tgz", + "integrity": "sha512-5yximcFK5FNompXfJFoWanu5l8v1hNGqNHh9du1xETp9HWk/B/PzvchX55WYOPaIeNglG8++68AAiauBAtbnzw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.3.1", + "@emnapi/runtime": "^1.3.1", + "@tybys/wasm-util": "^0.9.0" } }, "node_modules/@next/env": { - "version": "14.2.24", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.24.tgz", - "integrity": "sha512-LAm0Is2KHTNT6IT16lxT+suD0u+VVfYNQqM+EJTKuFRRuY2z+zj01kueWXPCxbMBDt0B5vONYzabHGUNbZYAhA==" + "version": "14.2.25", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.25.tgz", + "integrity": "sha512-JnzQ2cExDeG7FxJwqAksZ3aqVJrHjFwZQAEJ9gQZSoEhIow7SNoKZzju/AwQ+PLIR4NY8V0rhcVozx/2izDO0w==", + "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.13.tgz", - "integrity": "sha512-z8Mk0VljxhIzsSiZUSdt3wp+t2lKd+jk5a9Jsvh3zDGkItgDMfjv/ZbET6HsxEl/fSihVoHGsXV6VLyDH0lfTQ==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.2.3.tgz", + "integrity": "sha512-eNSOIMJtjs+dp4Ms1tB1PPPJUQHP3uZK+OQ7iFY9qXpGO6ojT6imCL+KcUOqE/GXGidWbBZJzYdgAdPHqeCEPA==", "dev": true, + "license": "MIT", "dependencies": { - "glob": "10.3.10" + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.24", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.24.tgz", - "integrity": "sha512-7Tdi13aojnAZGpapVU6meVSpNzgrFwZ8joDcNS8cJVNuP3zqqrLqeory9Xec5TJZR/stsGJdfwo8KeyloT3+rQ==", + "version": "14.2.25", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.25.tgz", + "integrity": "sha512-09clWInF1YRd6le00vt750s3m7SEYNehz9C4PUcSu3bAdCTpjIV4aTYQZ25Ehrr83VR1rZeqtKUPWSI7GfuKZQ==", "cpu": [ "arm64" ], @@ -2066,9 +2313,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.24", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.24.tgz", - "integrity": "sha512-lXR2WQqUtu69l5JMdTwSvQUkdqAhEWOqJEYUQ21QczQsAlNOW2kWZCucA6b3EXmPbcvmHB1kSZDua/713d52xg==", + "version": "14.2.25", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.25.tgz", + "integrity": "sha512-V+iYM/QR+aYeJl3/FWWU/7Ix4b07ovsQ5IbkwgUK29pTHmq+5UxeDr7/dphvtXEq5pLB/PucfcBNh9KZ8vWbug==", "cpu": [ "x64" ], @@ -2082,9 +2329,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.24", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.24.tgz", - "integrity": "sha512-nxvJgWOpSNmzidYvvGDfXwxkijb6hL9+cjZx1PVG6urr2h2jUqBALkKjT7kpfurRWicK6hFOvarmaWsINT1hnA==", + "version": "14.2.25", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.25.tgz", + "integrity": "sha512-LFnV2899PJZAIEHQ4IMmZIgL0FBieh5keMnriMY1cK7ompR+JUd24xeTtKkcaw8QmxmEdhoE5Mu9dPSuDBgtTg==", "cpu": [ "arm64" ], @@ -2098,9 +2345,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.24", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.24.tgz", - "integrity": "sha512-PaBgOPhqa4Abxa3y/P92F3kklNPsiFjcjldQGT7kFmiY5nuFn8ClBEoX8GIpqU1ODP2y8P6hio6vTomx2Vy0UQ==", + "version": "14.2.25", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.25.tgz", + "integrity": "sha512-QC5y5PPTmtqFExcKWKYgUNkHeHE/z3lUsu83di488nyP0ZzQ3Yse2G6TCxz6nNsQwgAx1BehAJTZez+UQxzLfw==", "cpu": [ "arm64" ], @@ -2114,9 +2361,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.24", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.24.tgz", - "integrity": "sha512-vEbyadiRI7GOr94hd2AB15LFVgcJZQWu7Cdi9cWjCMeCiUsHWA0U5BkGPuoYRnTxTn0HacuMb9NeAmStfBCLoQ==", + "version": "14.2.25", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.25.tgz", + "integrity": "sha512-y6/ML4b9eQ2D/56wqatTJN5/JR8/xdObU2Fb1RBidnrr450HLCKr6IJZbPqbv7NXmje61UyxjF5kvSajvjye5w==", "cpu": [ "x64" ], @@ -2130,9 +2377,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.24", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.24.tgz", - "integrity": "sha512-df0FC9ptaYsd8nQCINCzFtDWtko8PNRTAU0/+d7hy47E0oC17tI54U/0NdGk7l/76jz1J377dvRjmt6IUdkpzQ==", + "version": "14.2.25", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.25.tgz", + "integrity": "sha512-sPX0TSXHGUOZFvv96GoBXpB3w4emMqKeMgemrSxI7A6l55VBJp/RKYLwZIB9JxSqYPApqiREaIIap+wWq0RU8w==", "cpu": [ "x64" ], @@ -2146,9 +2393,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.24", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.24.tgz", - "integrity": "sha512-ZEntbLjeYAJ286eAqbxpZHhDFYpYjArotQ+/TW9j7UROh0DUmX7wYDGtsTPpfCV8V+UoqHBPU7q9D4nDNH014Q==", + "version": "14.2.25", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.25.tgz", + "integrity": "sha512-ReO9S5hkA1DU2cFCsGoOEp7WJkhFzNbU/3VUF6XxNGUCQChyug6hZdYL/istQgfT/GWE6PNIg9cm784OI4ddxQ==", "cpu": [ "arm64" ], @@ -2162,9 +2409,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.24", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.24.tgz", - "integrity": "sha512-9KuS+XUXM3T6v7leeWU0erpJ6NsFIwiTFD5nzNg8J5uo/DMIPvCp3L1Ao5HjbHX0gkWPB1VrKoo/Il4F0cGK2Q==", + "version": "14.2.25", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.25.tgz", + "integrity": "sha512-DZ/gc0o9neuCDyD5IumyTGHVun2dCox5TfPQI/BJTYwpSNYM3CZDI4i6TOdjeq1JMo+Ug4kPSMuZdwsycwFbAw==", "cpu": [ "ia32" ], @@ -2178,9 +2425,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.24", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.24.tgz", - "integrity": "sha512-cXcJ2+x0fXQ2CntaE00d7uUH+u1Bfp/E0HsNQH79YiLaZE5Rbm7dZzyAYccn3uICM7mw+DxoMqEfGXZtF4Fgaw==", + "version": "14.2.25", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.25.tgz", + "integrity": "sha512-KSznmS6eFjQ9RJ1nEc66kJvtGIL1iZMYmGEXsZPh2YtnLtqrgdVvKXJY2ScjjoFnG6nGLyPFR0UiEvDwVah4Tw==", "cpu": [ "x64" ], @@ -3788,6 +4035,7 @@ "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.4.0" } @@ -3958,6 +4206,7 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", "optional": true, "engines": { "node": ">=14" @@ -4151,17 +4400,16 @@ } }, "node_modules/@react-aria/checkbox/node_modules/@react-aria/toggle": { - "version": "3.10.11", - "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.10.11.tgz", - "integrity": "sha512-J3jO3KJiUbaYVDEpeXSBwqcyKxpi9OreiHRGiaxb6VwB+FWCj7Gb2WKajByXNyfs8jc6kX9VUFaXa7jze60oEQ==", + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.11.1.tgz", + "integrity": "sha512-9SBvSFpGcLODN1u64tQ8aL6uLFnuuJRA2N0Kjmxp5PE1gk8IKG+BXsjZmq7auDAN5WPISBXw1RzEOmbghruBTQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/toggle": "^3.8.1", - "@react-types/checkbox": "^3.9.1", - "@react-types/shared": "^3.27.0", + "@react-aria/interactions": "^3.24.1", + "@react-aria/utils": "^3.28.1", + "@react-stately/toggle": "^3.8.2", + "@react-types/checkbox": "^3.9.2", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4169,32 +4417,16 @@ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, - "node_modules/@react-aria/checkbox/node_modules/@react-aria/toggle/node_modules/@react-aria/focus": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.19.1.tgz", - "integrity": "sha512-bix9Bu1Ue7RPcYmjwcjhB14BMu2qzfJ3tMQLqDc9pweJA66nOw8DThy3IfVr8Z7j2PHktOLf9kcbiZpydKHqzg==", - "license": "Apache-2.0", - "dependencies": { - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", - "@swc/helpers": "^0.5.0", - "clsx": "^2.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, "node_modules/@react-aria/checkbox/node_modules/@react-aria/toggle/node_modules/@react-aria/interactions": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.23.0.tgz", - "integrity": "sha512-0qR1atBIWrb7FzQ+Tmr3s8uH5mQdyRH78n0krYaG8tng9+u1JlSi8DGRSaC9ezKyNB84m7vHT207xnHXGeJ3Fg==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.24.1.tgz", + "integrity": "sha512-OWEcIC6UQfWq4Td5Ptuh4PZQ4LHLJr/JL2jGYvuNL6EgL3bWvzPrRYIF/R64YbfVxIC7FeZpPSkS07sZ93/NoA==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.7", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.1", + "@react-stately/flags": "^3.1.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4203,14 +4435,15 @@ } }, "node_modules/@react-aria/checkbox/node_modules/@react-aria/toggle/node_modules/@react-aria/utils": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.27.0.tgz", - "integrity": "sha512-p681OtApnKOdbeN8ITfnnYqfdHS0z7GE+4l8EXlfLnr70Rp/9xicBO6d2rU+V/B3JujDw2gPWxYKEnEeh0CGCw==", + "version": "3.28.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.28.1.tgz", + "integrity": "sha512-mnHFF4YOVu9BRFQ1SZSKfPhg3z+lBRYoW5mLcYTQihbKhz48+I1sqRkP7ahMITr8ANH3nb34YaMME4XWmK2Mgg==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.7", + "@react-stately/flags": "^3.1.0", "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -4220,14 +4453,14 @@ } }, "node_modules/@react-aria/checkbox/node_modules/@react-stately/toggle": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.8.1.tgz", - "integrity": "sha512-MVpe79ghVQiwLmVzIPhF/O/UJAUc9B+ZSylVTyJiEPi0cwhbkKGQv9thOF0ebkkRkace5lojASqUAYtSTZHQJA==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.8.2.tgz", + "integrity": "sha512-5KPpT6zvt8H+WC9UbubhCTZltREeYb/3hKdl4YkS7BbSOQlHTFC0pOk8SsQU70Pwk26jeVHbl5le/N8cw00x8w==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.5", - "@react-types/checkbox": "^3.9.1", - "@react-types/shared": "^3.27.0", + "@react-types/checkbox": "^3.9.2", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4235,21 +4468,21 @@ } }, "node_modules/@react-aria/checkbox/node_modules/@react-types/checkbox": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.9.1.tgz", - "integrity": "sha512-0x/KQcipfNM9Nvy6UMwYG25roRLvsiqf0J3woTYylNNWzF+72XT0iI5FdJkE3w2wfa0obmSoeq4WcbFREQrH/A==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.9.2.tgz", + "integrity": "sha512-BruOLjr9s0BS2+G1Q2ZZ0ubnSTG54hZWr59lCHXaLxMdA/+KVsR6JVMQuYKsW0P8RDDlQXE/QGz3n9yB/Ara4A==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-aria/checkbox/node_modules/@react-types/shared": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", + "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -4363,23 +4596,23 @@ } }, "node_modules/@react-aria/grid": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.11.1.tgz", - "integrity": "sha512-Wg8m68RtNWfkhP3Qjrrsl1q1et8QCjXPMRsYgKBahYRS0kq2MDcQ+UBdG1fiCQn/MfNImhTUGVeQX276dy1lww==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.12.1.tgz", + "integrity": "sha512-f0Sx/O6VVjNcg5xq0cLhA7QSCkZodV+/Y0UXJTg/NObqgPX/tqh/KNEy7zeVd22FS6SUpXV+fJU99yLPo37rjQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", + "@react-aria/focus": "^3.20.1", + "@react-aria/i18n": "^3.12.7", + "@react-aria/interactions": "^3.24.1", "@react-aria/live-announcer": "^3.4.1", - "@react-aria/selection": "^3.22.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/collections": "^3.12.1", - "@react-stately/grid": "^3.10.1", - "@react-stately/selection": "^3.19.0", - "@react-types/checkbox": "^3.9.1", - "@react-types/grid": "^3.2.11", - "@react-types/shared": "^3.27.0", + "@react-aria/selection": "^3.23.1", + "@react-aria/utils": "^3.28.1", + "@react-stately/collections": "^3.12.2", + "@react-stately/grid": "^3.11.0", + "@react-stately/selection": "^3.20.0", + "@react-types/checkbox": "^3.9.2", + "@react-types/grid": "^3.3.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4397,14 +4630,14 @@ } }, "node_modules/@react-aria/grid/node_modules/@react-aria/focus": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.19.1.tgz", - "integrity": "sha512-bix9Bu1Ue7RPcYmjwcjhB14BMu2qzfJ3tMQLqDc9pweJA66nOw8DThy3IfVr8Z7j2PHktOLf9kcbiZpydKHqzg==", + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.1.tgz", + "integrity": "sha512-lgYs+sQ1TtBrAXnAdRBQrBo0/7o5H6IrfDxec1j+VRpcXL0xyk0xPq+m3lZp8typzIghqDgpnKkJ5Jf4OrzPIw==", "license": "Apache-2.0", "dependencies": { - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/interactions": "^3.24.1", + "@react-aria/utils": "^3.28.1", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -4414,9 +4647,9 @@ } }, "node_modules/@react-aria/grid/node_modules/@react-aria/i18n": { - "version": "3.12.5", - "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.5.tgz", - "integrity": "sha512-ooeop2pTG94PuaHoN2OTk2hpkqVuoqgEYxRvnc1t7DVAtsskfhS/gVOTqyWGsxvwAvRi7m/CnDu6FYdeQ/bK5w==", + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.7.tgz", + "integrity": "sha512-eLbYO2xrpeOKIEmLv2KD5LFcB0wltFqS+pUjsOzkKZg6H3b6AFDmJPxr/a0x2KGHtpGJvuHwCSbpPi9PzSSQLg==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.7.0", @@ -4424,8 +4657,8 @@ "@internationalized/number": "^3.6.0", "@internationalized/string": "^3.2.5", "@react-aria/ssr": "^3.9.7", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.1", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4434,14 +4667,15 @@ } }, "node_modules/@react-aria/grid/node_modules/@react-aria/interactions": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.23.0.tgz", - "integrity": "sha512-0qR1atBIWrb7FzQ+Tmr3s8uH5mQdyRH78n0krYaG8tng9+u1JlSi8DGRSaC9ezKyNB84m7vHT207xnHXGeJ3Fg==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.24.1.tgz", + "integrity": "sha512-OWEcIC6UQfWq4Td5Ptuh4PZQ4LHLJr/JL2jGYvuNL6EgL3bWvzPrRYIF/R64YbfVxIC7FeZpPSkS07sZ93/NoA==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.7", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.1", + "@react-stately/flags": "^3.1.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4450,17 +4684,17 @@ } }, "node_modules/@react-aria/grid/node_modules/@react-aria/selection": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.22.0.tgz", - "integrity": "sha512-XFOrK525HX2eeWeLZcZscUAs5qsuC1ZxsInDXMjvLeAaUPtQNEhUKHj3psDAl6XDU4VV1IJo0qCmFTVqTTMZSg==", + "version": "3.23.1", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.23.1.tgz", + "integrity": "sha512-z4vVw7Fw0+nK46PPlCV8TyieCS+EOUp3eguX8833fFJ/QDlFp3Ewgw2T5qCIix5U3siXPYU0ZmAMOdrjibdGpQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/selection": "^3.19.0", - "@react-types/shared": "^3.27.0", + "@react-aria/focus": "^3.20.1", + "@react-aria/i18n": "^3.12.7", + "@react-aria/interactions": "^3.24.1", + "@react-aria/utils": "^3.28.1", + "@react-stately/selection": "^3.20.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4469,14 +4703,15 @@ } }, "node_modules/@react-aria/grid/node_modules/@react-aria/utils": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.27.0.tgz", - "integrity": "sha512-p681OtApnKOdbeN8ITfnnYqfdHS0z7GE+4l8EXlfLnr70Rp/9xicBO6d2rU+V/B3JujDw2gPWxYKEnEeh0CGCw==", + "version": "3.28.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.28.1.tgz", + "integrity": "sha512-mnHFF4YOVu9BRFQ1SZSKfPhg3z+lBRYoW5mLcYTQihbKhz48+I1sqRkP7ahMITr8ANH3nb34YaMME4XWmK2Mgg==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.7", + "@react-stately/flags": "^3.1.0", "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -4486,12 +4721,12 @@ } }, "node_modules/@react-aria/grid/node_modules/@react-stately/collections": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.1.tgz", - "integrity": "sha512-8QmFBL7f+P64dEP4o35pYH61/lP0T/ziSdZAvNMrCqaM+fXcMfUp2yu1E63kADVX7WRDsFJWE3CVMeqirPH6Xg==", + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.2.tgz", + "integrity": "sha512-RoehfGwrsYJ/WGtyGSLZNYysszajnq0Q3iTXg7plfW1vNEzom/A31vrLjOSOHJWAtwW339SDGGRpymDtLo4GWA==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4499,33 +4734,33 @@ } }, "node_modules/@react-aria/grid/node_modules/@react-types/checkbox": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.9.1.tgz", - "integrity": "sha512-0x/KQcipfNM9Nvy6UMwYG25roRLvsiqf0J3woTYylNNWzF+72XT0iI5FdJkE3w2wfa0obmSoeq4WcbFREQrH/A==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.9.2.tgz", + "integrity": "sha512-BruOLjr9s0BS2+G1Q2ZZ0ubnSTG54hZWr59lCHXaLxMdA/+KVsR6JVMQuYKsW0P8RDDlQXE/QGz3n9yB/Ara4A==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-aria/grid/node_modules/@react-types/grid": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.2.11.tgz", - "integrity": "sha512-Mww9nrasppvPbsBi+uUqFnf7ya8fXN0cTVzDNG+SveD8mhW+sbtuy+gPtEpnFD2Oyi8qLuObefzt4gdekJX2Yw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.3.0.tgz", + "integrity": "sha512-9IXgD5qXXxz+S9RK+zT8umuTCEcE4Yfdl0zUGyTCB8LVcPEeZuarLGXZY/12Rkbd8+r6MUIKTxMVD3Nq9X5Ksg==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-aria/grid/node_modules/@react-types/shared": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", + "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -4753,16 +4988,16 @@ } }, "node_modules/@react-aria/spinbutton": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.6.11.tgz", - "integrity": "sha512-RM+gYS9tf9Wb+GegV18n4ArK3NBKgcsak7Nx1CkEgX9BjJ0yayWUHdfEjRRvxGXl+1z1n84cJVkZ6FUlWOWEZA==", + "version": "3.6.13", + "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.6.13.tgz", + "integrity": "sha512-phF7WU4mTryPY+IORqQC6eGvCdLItJ41KJ8ZWmpubnLkhqyyxBn8BirXlxWC5UIIvir9c3oohX2Vip/bE5WJiA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/i18n": "^3.12.5", + "@react-aria/i18n": "^3.12.7", "@react-aria/live-announcer": "^3.4.1", - "@react-aria/utils": "^3.27.0", - "@react-types/button": "^3.10.2", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.1", + "@react-types/button": "^3.11.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4780,9 +5015,9 @@ } }, "node_modules/@react-aria/spinbutton/node_modules/@react-aria/i18n": { - "version": "3.12.5", - "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.5.tgz", - "integrity": "sha512-ooeop2pTG94PuaHoN2OTk2hpkqVuoqgEYxRvnc1t7DVAtsskfhS/gVOTqyWGsxvwAvRi7m/CnDu6FYdeQ/bK5w==", + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.7.tgz", + "integrity": "sha512-eLbYO2xrpeOKIEmLv2KD5LFcB0wltFqS+pUjsOzkKZg6H3b6AFDmJPxr/a0x2KGHtpGJvuHwCSbpPi9PzSSQLg==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.7.0", @@ -4790,8 +5025,8 @@ "@internationalized/number": "^3.6.0", "@internationalized/string": "^3.2.5", "@react-aria/ssr": "^3.9.7", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.1", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4800,14 +5035,15 @@ } }, "node_modules/@react-aria/spinbutton/node_modules/@react-aria/utils": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.27.0.tgz", - "integrity": "sha512-p681OtApnKOdbeN8ITfnnYqfdHS0z7GE+4l8EXlfLnr70Rp/9xicBO6d2rU+V/B3JujDw2gPWxYKEnEeh0CGCw==", + "version": "3.28.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.28.1.tgz", + "integrity": "sha512-mnHFF4YOVu9BRFQ1SZSKfPhg3z+lBRYoW5mLcYTQihbKhz48+I1sqRkP7ahMITr8ANH3nb34YaMME4XWmK2Mgg==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.7", + "@react-stately/flags": "^3.1.0", "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -4817,21 +5053,21 @@ } }, "node_modules/@react-aria/spinbutton/node_modules/@react-types/button": { - "version": "3.10.2", - "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.10.2.tgz", - "integrity": "sha512-h8SB/BLoCgoBulCpyzaoZ+miKXrolK9XC48+n1dKJXT8g4gImrficurDW6+PRTQWaRai0Q0A6bu8UibZOU4syg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.11.0.tgz", + "integrity": "sha512-gJh5i0JiBiZGZGDo+tXMp6xbixPM7IKZ0sDuxTYBG49qNzzWJq0uNYltO3emwSVXFSsBgRV/Wu8kQGhfuN7wIw==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-aria/spinbutton/node_modules/@react-types/shared": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", + "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -4869,17 +5105,16 @@ } }, "node_modules/@react-aria/switch/node_modules/@react-aria/toggle": { - "version": "3.10.11", - "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.10.11.tgz", - "integrity": "sha512-J3jO3KJiUbaYVDEpeXSBwqcyKxpi9OreiHRGiaxb6VwB+FWCj7Gb2WKajByXNyfs8jc6kX9VUFaXa7jze60oEQ==", + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.11.1.tgz", + "integrity": "sha512-9SBvSFpGcLODN1u64tQ8aL6uLFnuuJRA2N0Kjmxp5PE1gk8IKG+BXsjZmq7auDAN5WPISBXw1RzEOmbghruBTQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/toggle": "^3.8.1", - "@react-types/checkbox": "^3.9.1", - "@react-types/shared": "^3.27.0", + "@react-aria/interactions": "^3.24.1", + "@react-aria/utils": "^3.28.1", + "@react-stately/toggle": "^3.8.2", + "@react-types/checkbox": "^3.9.2", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4887,32 +5122,16 @@ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, - "node_modules/@react-aria/switch/node_modules/@react-aria/toggle/node_modules/@react-aria/focus": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.19.1.tgz", - "integrity": "sha512-bix9Bu1Ue7RPcYmjwcjhB14BMu2qzfJ3tMQLqDc9pweJA66nOw8DThy3IfVr8Z7j2PHktOLf9kcbiZpydKHqzg==", - "license": "Apache-2.0", - "dependencies": { - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", - "@swc/helpers": "^0.5.0", - "clsx": "^2.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, "node_modules/@react-aria/switch/node_modules/@react-aria/toggle/node_modules/@react-aria/interactions": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.23.0.tgz", - "integrity": "sha512-0qR1atBIWrb7FzQ+Tmr3s8uH5mQdyRH78n0krYaG8tng9+u1JlSi8DGRSaC9ezKyNB84m7vHT207xnHXGeJ3Fg==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.24.1.tgz", + "integrity": "sha512-OWEcIC6UQfWq4Td5Ptuh4PZQ4LHLJr/JL2jGYvuNL6EgL3bWvzPrRYIF/R64YbfVxIC7FeZpPSkS07sZ93/NoA==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.7", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.1", + "@react-stately/flags": "^3.1.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4921,14 +5140,15 @@ } }, "node_modules/@react-aria/switch/node_modules/@react-aria/toggle/node_modules/@react-aria/utils": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.27.0.tgz", - "integrity": "sha512-p681OtApnKOdbeN8ITfnnYqfdHS0z7GE+4l8EXlfLnr70Rp/9xicBO6d2rU+V/B3JujDw2gPWxYKEnEeh0CGCw==", + "version": "3.28.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.28.1.tgz", + "integrity": "sha512-mnHFF4YOVu9BRFQ1SZSKfPhg3z+lBRYoW5mLcYTQihbKhz48+I1sqRkP7ahMITr8ANH3nb34YaMME4XWmK2Mgg==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.7", + "@react-stately/flags": "^3.1.0", "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -4938,14 +5158,14 @@ } }, "node_modules/@react-aria/switch/node_modules/@react-stately/toggle": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.8.1.tgz", - "integrity": "sha512-MVpe79ghVQiwLmVzIPhF/O/UJAUc9B+ZSylVTyJiEPi0cwhbkKGQv9thOF0ebkkRkace5lojASqUAYtSTZHQJA==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.8.2.tgz", + "integrity": "sha512-5KPpT6zvt8H+WC9UbubhCTZltREeYb/3hKdl4YkS7BbSOQlHTFC0pOk8SsQU70Pwk26jeVHbl5le/N8cw00x8w==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.5", - "@react-types/checkbox": "^3.9.1", - "@react-types/shared": "^3.27.0", + "@react-types/checkbox": "^3.9.2", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4953,21 +5173,21 @@ } }, "node_modules/@react-aria/switch/node_modules/@react-types/checkbox": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.9.1.tgz", - "integrity": "sha512-0x/KQcipfNM9Nvy6UMwYG25roRLvsiqf0J3woTYylNNWzF+72XT0iI5FdJkE3w2wfa0obmSoeq4WcbFREQrH/A==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.9.2.tgz", + "integrity": "sha512-BruOLjr9s0BS2+G1Q2ZZ0ubnSTG54hZWr59lCHXaLxMdA/+KVsR6JVMQuYKsW0P8RDDlQXE/QGz3n9yB/Ara4A==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-aria/switch/node_modules/@react-types/shared": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", + "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -5190,9 +5410,9 @@ } }, "node_modules/@react-stately/flags": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.0.5.tgz", - "integrity": "sha512-6wks4csxUwPCp23LgJSnkBRhrWpd9jGd64DjcCTNB2AHIFu7Ab1W59pJpUL6TW7uAxVxdNKjgn6D1hlBy8qWsA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.0.tgz", + "integrity": "sha512-KSHOCxTFpBtxhIRcKwsD1YDTaNxFtCYuAUb0KEihc16QwqZViq4hasgPBs2gYm7fHRbw7WYzWKf6ZSo/+YsFlg==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -5212,15 +5432,15 @@ } }, "node_modules/@react-stately/grid": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.10.1.tgz", - "integrity": "sha512-MOIy//AdxZxIXIzvWSKpvMvaPEMZGQNj+/cOsElHepv/Veh0psNURZMh2TP6Mr0+MnDTZbX+5XIeinGkWYO3JQ==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.11.0.tgz", + "integrity": "sha512-Wp6kza+2MzNybls9pRWvIwAHwMnSV1eUZXZxLwJy+JVS5lghkr731VvT+YD79z70osJKmgxgmiQGm4/yfetXdA==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.1", - "@react-stately/selection": "^3.19.0", - "@react-types/grid": "^3.2.11", - "@react-types/shared": "^3.27.0", + "@react-stately/collections": "^3.12.2", + "@react-stately/selection": "^3.20.0", + "@react-types/grid": "^3.3.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5228,12 +5448,12 @@ } }, "node_modules/@react-stately/grid/node_modules/@react-stately/collections": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.1.tgz", - "integrity": "sha512-8QmFBL7f+P64dEP4o35pYH61/lP0T/ziSdZAvNMrCqaM+fXcMfUp2yu1E63kADVX7WRDsFJWE3CVMeqirPH6Xg==", + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.2.tgz", + "integrity": "sha512-RoehfGwrsYJ/WGtyGSLZNYysszajnq0Q3iTXg7plfW1vNEzom/A31vrLjOSOHJWAtwW339SDGGRpymDtLo4GWA==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5241,21 +5461,21 @@ } }, "node_modules/@react-stately/grid/node_modules/@react-types/grid": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.2.11.tgz", - "integrity": "sha512-Mww9nrasppvPbsBi+uUqFnf7ya8fXN0cTVzDNG+SveD8mhW+sbtuy+gPtEpnFD2Oyi8qLuObefzt4gdekJX2Yw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.3.0.tgz", + "integrity": "sha512-9IXgD5qXXxz+S9RK+zT8umuTCEcE4Yfdl0zUGyTCB8LVcPEeZuarLGXZY/12Rkbd8+r6MUIKTxMVD3Nq9X5Ksg==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-stately/grid/node_modules/@react-types/shared": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", + "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -5323,16 +5543,16 @@ } }, "node_modules/@react-stately/select": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/@react-stately/select/-/select-3.6.10.tgz", - "integrity": "sha512-V7V0FCL9T+GzLjyfnJB6PUaKldFyT/8Rj6M+R9ura1A0O+s/FEOesy0pdMXFoL1l5zeUpGlCnhJrsI5HFWHfDw==", + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/@react-stately/select/-/select-3.6.11.tgz", + "integrity": "sha512-8pD4PNbZQNWg33D4+Fa0mrajUCYV3aA5YIwW3GY8NSRwBspaW4PKSZJtDT5ieN0WAO44YkAmX4idRaMAvqRusA==", "license": "Apache-2.0", "dependencies": { - "@react-stately/form": "^3.1.1", - "@react-stately/list": "^3.11.2", - "@react-stately/overlays": "^3.6.13", - "@react-types/select": "^3.9.9", - "@react-types/shared": "^3.27.0", + "@react-stately/form": "^3.1.2", + "@react-stately/list": "^3.12.0", + "@react-stately/overlays": "^3.6.14", + "@react-types/select": "^3.9.10", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5340,12 +5560,12 @@ } }, "node_modules/@react-stately/select/node_modules/@react-stately/collections": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.1.tgz", - "integrity": "sha512-8QmFBL7f+P64dEP4o35pYH61/lP0T/ziSdZAvNMrCqaM+fXcMfUp2yu1E63kADVX7WRDsFJWE3CVMeqirPH6Xg==", + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.2.tgz", + "integrity": "sha512-RoehfGwrsYJ/WGtyGSLZNYysszajnq0Q3iTXg7plfW1vNEzom/A31vrLjOSOHJWAtwW339SDGGRpymDtLo4GWA==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5353,12 +5573,12 @@ } }, "node_modules/@react-stately/select/node_modules/@react-stately/form": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.1.1.tgz", - "integrity": "sha512-qavrz5X5Mdf/Q1v/QJRxc0F8UTNEyRCNSM1we/nnF7GV64+aYSDLOtaRGmzq+09RSwo1c8ZYnIkK5CnwsPhTsQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.1.2.tgz", + "integrity": "sha512-sKgkV+rxeqM1lf0dCq2wWzdYa5Z0wz/MB3yxjodffy8D43PjFvUOMWpgw/752QHPGCd1XIxA3hE58Dw9FFValg==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5366,15 +5586,15 @@ } }, "node_modules/@react-stately/select/node_modules/@react-stately/list": { - "version": "3.11.2", - "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.11.2.tgz", - "integrity": "sha512-eU2tY3aWj0SEeC7lH9AQoeAB4LL9mwS54FvTgHHoOgc1ZIwRJUaZoiuETyWQe98AL8KMgR1nrnDJ1I+CcT1Y7g==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.12.0.tgz", + "integrity": "sha512-6niQWJ6TZwOKLAOn2wIsxtOvWenh3rKiKdOh4L4O4f7U+h1Hu000Mu4lyIQm2P9uZAkF2Y5QNh6dHN+hSd6h3A==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.1", - "@react-stately/selection": "^3.19.0", + "@react-stately/collections": "^3.12.2", + "@react-stately/selection": "^3.20.0", "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5382,13 +5602,13 @@ } }, "node_modules/@react-stately/select/node_modules/@react-stately/overlays": { - "version": "3.6.13", - "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.13.tgz", - "integrity": "sha512-WsU85Gf/b+HbWsnnYw7P/Ila3wD+C37Uk/WbU4/fHgJ26IEOWsPE6wlul8j54NZ1PnLNhV9Fn+Kffi+PaJMQXQ==", + "version": "3.6.14", + "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.14.tgz", + "integrity": "sha512-RRalTuHdwrKO1BmXKaqBtE1GGUXU4VUAWwgh4lsP2EFSixDHmOVLxHFDWYvOPChBhpi8KXfLEgm6DEgPBvLBZQ==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.5", - "@react-types/overlays": "^3.8.12", + "@react-types/overlays": "^3.8.13", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5396,47 +5616,47 @@ } }, "node_modules/@react-stately/select/node_modules/@react-types/overlays": { - "version": "3.8.12", - "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.12.tgz", - "integrity": "sha512-ZvR1t0YV7/6j+6OD8VozKYjvsXT92+C/2LOIKozy7YUNS5KI4MkXbRZzJvkuRECVZOmx8JXKTUzhghWJM/3QuQ==", + "version": "3.8.13", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.13.tgz", + "integrity": "sha512-xgT843KIh1otvYPQ6kCGTVUICiMF5UQ7SZUQZd4Zk3VtiFIunFVUvTvL03cpt0026UmY7tbv7vFrPKcT6xjsjw==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-stately/select/node_modules/@react-types/select": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/@react-types/select/-/select-3.9.9.tgz", - "integrity": "sha512-/hCd0o+ztn29FKCmVec+v7t4JpOzz56o+KrG7NDq2pcRWqUR9kNwCjrPhSbJIIEDm4ubtrfPu41ysIuDvRd2Bg==", + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/@react-types/select/-/select-3.9.10.tgz", + "integrity": "sha512-vvC5+cBSOu6J6lm74jhhP3Zvo1JO8m0FNX+Q95wapxrhs2aYYeMIgVuvNKeOuhVqzpBZxWmblBjCVNzCArZOaQ==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-stately/select/node_modules/@react-types/shared": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", + "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-stately/selection": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.19.0.tgz", - "integrity": "sha512-AvbUqnWjqVQC48RD39S9BpMKMLl55Zo5l/yx5JQFPl55cFwe9Tpku1KY0wzt3fXXiXWaqjDn/7Gkg1VJYy8esQ==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.20.0.tgz", + "integrity": "sha512-woUSHMTyQiNmCf63Dyot1WXFfWnm6PFYkI9kymcq1qrrly4g/j27U+5PaRWOHawMiJwn1e1GTogk8B+K5ahshQ==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.1", + "@react-stately/collections": "^3.12.2", "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5444,12 +5664,12 @@ } }, "node_modules/@react-stately/selection/node_modules/@react-stately/collections": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.1.tgz", - "integrity": "sha512-8QmFBL7f+P64dEP4o35pYH61/lP0T/ziSdZAvNMrCqaM+fXcMfUp2yu1E63kADVX7WRDsFJWE3CVMeqirPH6Xg==", + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.2.tgz", + "integrity": "sha512-RoehfGwrsYJ/WGtyGSLZNYysszajnq0Q3iTXg7plfW1vNEzom/A31vrLjOSOHJWAtwW339SDGGRpymDtLo4GWA==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5457,9 +5677,9 @@ } }, "node_modules/@react-stately/selection/node_modules/@react-types/shared": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", + "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -5746,21 +5966,21 @@ } }, "node_modules/@react-types/listbox": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.5.4.tgz", - "integrity": "sha512-5otTes0zOwRZwNtqysPD/aW4qFJSxd5znjwoWTLnzDXXOBHXPyR83IJf8ITgvIE5C0y+EFadsWR/BBO3k9Pj7g==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.5.5.tgz", + "integrity": "sha512-6cUjbYZVa0X2UMsenQ50ZaAssTUfzX3D0Q0Wd5nNf4W7ntBroDg6aBfNQoPDZikPUy8u+Y3uc/xZQfv30si7NA==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/listbox/node_modules/@react-types/shared": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", + "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -5837,42 +6057,42 @@ } }, "node_modules/@react-types/slider": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.7.8.tgz", - "integrity": "sha512-utW1o9KT70hqFwu1zqMtyEWmP0kSATk4yx+Fm/peSR4iZa+BasRqH83yzir5GKc8OfqfE1kmEsSlO98/k986+w==", + "version": "3.7.9", + "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.7.9.tgz", + "integrity": "sha512-MxCIVkrBSbN3AxIYW4hOpTcwPmIuY4841HF36sDLFWR3wx06z70IY3GFwV7Cbp814vhc84d4ABnPMwtE+AZRGQ==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/slider/node_modules/@react-types/shared": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", + "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/switch": { - "version": "3.5.8", - "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.8.tgz", - "integrity": "sha512-sL7jmh8llF8BxzY4HXkSU4bwU8YU6gx45P85D0AdYXgRHxU9Cp7BQPOMF4pJoQ8TTej05MymY5q7xvJVmxUTAQ==", + "version": "3.5.9", + "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.9.tgz", + "integrity": "sha512-7XIS5qycIKhdfcWfzl8n458/7tkZKCNfMfZmIREgozKOtTBirjmtRRsefom2hlFT8VIlG7COmY4btK3oEuEhnQ==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/switch/node_modules/@react-types/shared": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", + "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -5932,7 +6152,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@rushstack/eslint-patch": { "version": "1.10.4", @@ -5965,17 +6186,18 @@ } }, "node_modules/@semantic-release/commit-analyzer": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-13.0.0.tgz", - "integrity": "sha512-KtXWczvTAB1ZFZ6B4O+w8HkfYm/OgQb1dUGNFZtDgQ0csggrmkq8sTxhd+lwGF8kMb59/RnG9o4Tn7M/I8dQ9Q==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-13.0.1.tgz", + "integrity": "sha512-wdnBPHKkr9HhNhXOhZD5a2LNl91+hs8CC2vsAVYxtZH3y0dV3wKn+uZSN61rdJQZ8EGxzWB3inWocBHV9+u/CQ==", "dev": true, + "license": "MIT", "dependencies": { "conventional-changelog-angular": "^8.0.0", "conventional-changelog-writer": "^8.0.0", "conventional-commits-filter": "^5.0.0", "conventional-commits-parser": "^6.0.0", "debug": "^4.0.0", - "import-from-esm": "^1.0.3", + "import-from-esm": "^2.0.0", "lodash-es": "^4.17.21", "micromatch": "^4.0.2" }, @@ -6018,10 +6240,11 @@ } }, "node_modules/@semantic-release/github": { - "version": "10.3.5", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-10.3.5.tgz", - "integrity": "sha512-svvRglGmvqvxjmDgkXhrjf0lC88oZowFhOfifTldbgX9Dzj0inEtMLaC+3/MkDEmxmaQjWmF5Q/0CMIvPNSVdQ==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.1.tgz", + "integrity": "sha512-Z9cr0LgU/zgucbT9cksH0/pX9zmVda9hkDPcgIE0uvjMQ8w/mElDivGjx1w1pEQ+MuQJ5CBq3VCF16S6G4VH3A==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/core": "^6.0.0", "@octokit/plugin-paginate-rest": "^11.0.0", @@ -6044,7 +6267,7 @@ "node": ">=20.8.1" }, "peerDependencies": { - "semantic-release": ">=20.1.0" + "semantic-release": ">=24.1.0" } }, "node_modules/@semantic-release/github/node_modules/@semantic-release/error": { @@ -6354,10 +6577,11 @@ } }, "node_modules/@semantic-release/release-notes-generator": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-14.0.1.tgz", - "integrity": "sha512-K0w+5220TM4HZTthE5dDpIuFrnkN1NfTGPidJFm04ULT1DEZ9WG89VNXN7F0c+6nMEpWgqmPvb7vY7JkB2jyyA==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-14.0.3.tgz", + "integrity": "sha512-XxAZRPWGwO5JwJtS83bRdoIhCiYIx8Vhr+u231pQAsdFIAbm19rSVJLdnBN+Avvk7CKvNQE/nJ4y7uqKH6WTiw==", "dev": true, + "license": "MIT", "dependencies": { "conventional-changelog-angular": "^8.0.0", "conventional-changelog-writer": "^8.0.0", @@ -6365,7 +6589,7 @@ "conventional-commits-parser": "^6.0.0", "debug": "^4.0.0", "get-stream": "^7.0.0", - "import-from-esm": "^1.0.3", + "import-from-esm": "^2.0.0", "into-stream": "^7.0.0", "lodash-es": "^4.17.21", "read-package-up": "^11.0.0" @@ -6404,7 +6628,8 @@ "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" }, "node_modules/@swc/helpers": { "version": "0.5.15", @@ -6457,14 +6682,15 @@ } }, "node_modules/@turf/centroid": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-7.1.0.tgz", - "integrity": "sha512-1Y1b2l+ZB1CZ+ITjUCsGqC4/tSjwm/R4OUfDztVqyyCq/VvezkLmTNqvXTGXgfP0GXkpv68iCfxF5M7QdM5pJQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-7.2.0.tgz", + "integrity": "sha512-yJqDSw25T7P48au5KjvYqbDVZ7qVnipziVfZ9aSo7P2/jTE7d4BP21w0/XLi3T/9bry/t9PR1GDDDQljN4KfDw==", + "license": "MIT", "dependencies": { - "@turf/helpers": "^7.1.0", - "@turf/meta": "^7.1.0", + "@turf/helpers": "^7.2.0", + "@turf/meta": "^7.2.0", "@types/geojson": "^7946.0.10", - "tslib": "^2.6.2" + "tslib": "^2.8.1" }, "funding": { "url": "https://opencollective.com/turf" @@ -6551,10 +6777,29 @@ "url": "https://opencollective.com/turf" } }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/geojson": { - "version": "7946.0.14", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", - "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT" }, "node_modules/@types/geojson-vt": { "version": "3.2.5", @@ -6564,24 +6809,24 @@ "@types/geojson": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/leaflet": { - "version": "1.9.12", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.12.tgz", - "integrity": "sha512-BK7XS+NyRI291HIo0HCfE18Lp8oA30H1gpi1tf0mF3TgiCEzanQjOqNZ4x126SXzzi2oNSZhZ5axJp1k0iM6jg==", - "dependencies": { - "@types/geojson": "*" - } + "dev": true, + "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==", + "version": "4.17.16", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", + "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", "license": "MIT" }, "node_modules/@types/lodash.debounce": { @@ -6608,20 +6853,13 @@ "@types/pbf": "*" } }, - "node_modules/@types/mapbox-gl": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@types/mapbox-gl/-/mapbox-gl-3.4.0.tgz", - "integrity": "sha512-tbn++Mm94H1kE7W6FF0oVC9rMXHVzDDNUbS7KfBMRF8NV/8csFi+67ytKcZJ4LsrpsJ+8MC6Os6ZinEDCsrunw==", - "dependencies": { - "@types/geojson": "*" - } - }, "node_modules/@types/node": { - "version": "20.16.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.6.tgz", - "integrity": "sha512-T7PpxM/6yeDE+AdlVysT62BX6/bECZOmQAgiFg5NoBd5MQheZ3tzal7f1wvzfiEcmrcJNRi2zRr2nY2zF+0uqw==", + "version": "22.13.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.11.tgz", + "integrity": "sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g==", + "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.20.0" } }, "node_modules/@types/normalize-package-data": { @@ -6636,10 +6874,11 @@ "integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==" }, "node_modules/@types/pg": { - "version": "8.11.10", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.10.tgz", - "integrity": "sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==", + "version": "8.11.11", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.11.tgz", + "integrity": "sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "pg-protocol": "*", @@ -6647,28 +6886,31 @@ } }, "node_modules/@types/prop-types": { - "version": "15.7.13", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", - "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", - "dev": true + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.8.tgz", - "integrity": "sha512-syBUrW3/XpnW4WJ41Pft+I+aPoDVbrBVQGEnbD7NijDGlVC+8gV/XKRY+7vMDlfPpbwYt0l1vd/Sj8bJGMbs9Q==", + "version": "18.3.19", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.19.tgz", + "integrity": "sha512-fcdJqaHOMDbiAwJnXv6XCzX0jDW77yI3tJqYh1Byn8EL5/S628WRx9b/y3DnNe55zTukUQKrfYxiZls2dHcUMw==", "dev": true, + "license": "MIT", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", + "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", "dev": true, - "dependencies": { - "@types/react": "*" + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" } }, "node_modules/@types/semver": { @@ -6686,230 +6928,421 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", - "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz", + "integrity": "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", + "@typescript-eslint/scope-manager": "8.27.0", + "@typescript-eslint/type-utils": "8.27.0", + "@typescript-eslint/utils": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.27.0.tgz", + "integrity": "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", + "@typescript-eslint/scope-manager": "8.27.0", + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/typescript-estree": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0", "debug": "^4.3.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz", + "integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz", + "integrity": "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.27.0", + "@typescript-eslint/utils": "8.27.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz", + "integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz", + "integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz", + "integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.27.0", + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/typescript-estree": "8.27.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz", + "integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.27.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@unrs/rspack-resolver-binding-darwin-arm64": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-darwin-arm64/-/rspack-resolver-binding-darwin-arm64-1.2.2.tgz", + "integrity": "sha512-i7z0B+C0P8Q63O/5PXJAzeFtA1ttY3OR2VSJgGv18S+PFNwD98xHgAgPOT1H5HIV6jlQP8Avzbp09qxJUdpPNw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/rspack-resolver-binding-darwin-x64": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-darwin-x64/-/rspack-resolver-binding-darwin-x64-1.2.2.tgz", + "integrity": "sha512-YEdFzPjIbDUCfmehC6eS+AdJYtFWY35YYgWUnqqTM2oe/N58GhNy5yRllxYhxwJ9GcfHoNc6Ubze1yjkNv+9Qg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/rspack-resolver-binding-freebsd-x64": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-freebsd-x64/-/rspack-resolver-binding-freebsd-x64-1.2.2.tgz", + "integrity": "sha512-TU4ntNXDgPN2giQyyzSnGWf/dVCem5lvwxg0XYvsvz35h5H19WrhTmHgbrULMuypCB3aHe1enYUC9rPLDw45mA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/rspack-resolver-binding-linux-arm-gnueabihf": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-linux-arm-gnueabihf/-/rspack-resolver-binding-linux-arm-gnueabihf-1.2.2.tgz", + "integrity": "sha512-ik3w4/rU6RujBvNWiDnKdXi1smBhqxEDhccNi/j2rHaMjm0Fk49KkJ6XKsoUnD2kZ5xaMJf9JjailW/okfUPIw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/rspack-resolver-binding-linux-arm64-gnu": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-linux-arm64-gnu/-/rspack-resolver-binding-linux-arm64-gnu-1.2.2.tgz", + "integrity": "sha512-fp4Azi8kHz6TX8SFmKfyScZrMLfp++uRm2srpqRjsRZIIBzH74NtSkdEUHImR4G7f7XJ+sVZjCc6KDDK04YEpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/rspack-resolver-binding-linux-arm64-musl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-linux-arm64-musl/-/rspack-resolver-binding-linux-arm64-musl-1.2.2.tgz", + "integrity": "sha512-gMiG3DCFioJxdGBzhlL86KcFgt9HGz0iDhw0YVYPsShItpN5pqIkNrI+L/Q/0gfDiGrfcE0X3VANSYIPmqEAlQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/rspack-resolver-binding-linux-x64-gnu": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-linux-x64-gnu/-/rspack-resolver-binding-linux-x64-gnu-1.2.2.tgz", + "integrity": "sha512-n/4n2CxaUF9tcaJxEaZm+lqvaw2gflfWQ1R9I7WQgYkKEKbRKbpG/R3hopYdUmLSRI4xaW1Cy0Bz40eS2Yi4Sw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/rspack-resolver-binding-linux-x64-musl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-linux-x64-musl/-/rspack-resolver-binding-linux-x64-musl-1.2.2.tgz", + "integrity": "sha512-cHyhAr6rlYYbon1L2Ag449YCj3p6XMfcYTP0AQX+KkQo025d1y/VFtPWvjMhuEsE2lLvtHm7GdJozj6BOMtzVg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/rspack-resolver-binding-wasm32-wasi": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-wasm32-wasi/-/rspack-resolver-binding-wasm32-wasi-1.2.2.tgz", + "integrity": "sha512-eogDKuICghDLGc32FtP+WniG38IB1RcGOGz0G3z8406dUdjJvxfHGuGs/dSlM9YEp/v0lEqhJ4mBu6X2nL9pog==", + "cpu": [ + "wasm32" + ], "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" + "@napi-rs/wasm-runtime": "^0.2.7" }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=14.0.0" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "node_modules/@unrs/rspack-resolver-binding-win32-arm64-msvc": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-win32-arm64-msvc/-/rspack-resolver-binding-win32-arm64-msvc-1.2.2.tgz", + "integrity": "sha512-7sWRJumhpXSi2lccX8aQpfFXHsSVASdWndLv8AmD8nDRA/5PBi8IplQVZNx2mYRx6+Bp91Z00kuVqpXO9NfCTg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/rspack-resolver-binding-win32-x64-msvc": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@unrs/rspack-resolver-binding-win32-x64-msvc/-/rspack-resolver-binding-win32-x64-msvc-1.2.2.tgz", + "integrity": "sha512-hewo/UMGP1a7O6FG/ThcPzSJdm/WwrYDNkdGgWl6M18H6K6MSitklomWpT9MUtT5KGj++QJb06va/14QBC4pvw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vis.gl/react-mapbox": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@vis.gl/react-mapbox/-/react-mapbox-8.0.1.tgz", + "integrity": "sha512-s/OokvgK1T43Ev2/4hj21C0DKrf79nIigBCdYPtAkEX88qGLRQ5t5zCRqg5Zl+44xXfVxcVpX2/vWUKd9oYGKQ==", + "license": "MIT", "peerDependencies": { - "eslint": "^8.56.0" + "mapbox-gl": ">=3.5.0", + "react": ">=16.3.0", + "react-dom": ">=16.3.0" }, "peerDependenciesMeta": { - "typescript": { + "mapbox-gl": { "optional": true } } }, - "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", - "dev": true, + "node_modules/@vis.gl/react-maplibre": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@vis.gl/react-maplibre/-/react-maplibre-8.0.1.tgz", + "integrity": "sha512-IFguo7DKIDZ9U9uRI4thZRfc5aTHEH4lWlIjedBeCpLeMm7wdrqtU2JshyEQt8dDO85kkEE7CbrtjMx5MplaoA==", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" + "@maplibre/maplibre-gl-style-spec": "^19.2.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "maplibre-gl": ">=4.0.0", + "react": ">=16.3.0", + "react-dom": ">=16.3.0" }, "peerDependenciesMeta": { - "typescript": { + "maplibre-gl": { "optional": true } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, + "node_modules/@vis.gl/react-maplibre/node_modules/@maplibre/maplibre-gl-style-spec": { + "version": "19.3.3", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-19.3.3.tgz", + "integrity": "sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw==", + "license": "ISC", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" + "@mapbox/jsonlint-lines-primitives": "~2.0.2", + "@mapbox/unitbezier": "^0.0.1", + "json-stringify-pretty-compact": "^3.0.0", + "minimist": "^1.2.8", + "rw": "^1.3.3", + "sort-object": "^3.0.3" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "gl-style-format": "dist/gl-style-format.mjs", + "gl-style-migrate": "dist/gl-style-migrate.mjs", + "gl-style-validate": "dist/gl-style-validate.mjs" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/slash": { + "node_modules/@vis.gl/react-maplibre/node_modules/json-stringify-pretty-compact": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", + "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==", + "license": "MIT" }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -6922,6 +7355,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -6956,6 +7390,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -7013,6 +7448,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -7024,7 +7460,8 @@ "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", @@ -7051,18 +7488,20 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { "node": ">= 0.4" @@ -7097,15 +7536,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", @@ -7127,17 +7557,19 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7165,15 +7597,16 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7199,19 +7632,19 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -7224,6 +7657,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7234,10 +7668,20 @@ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/autoprefixer": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", - "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", "funding": [ { "type": "opencollective", @@ -7252,12 +7696,13 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "browserslist": "^4.23.0", - "caniuse-lite": "^1.0.30001599", + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", + "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -7326,6 +7771,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -7359,9 +7805,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "funding": [ { "type": "opencollective", @@ -7376,11 +7822,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -7404,6 +7851,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", "integrity": "sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==", + "license": "MIT", "dependencies": { "bytewise-core": "^1.2.2", "typewise": "^1.0.3" @@ -7413,21 +7861,53 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz", "integrity": "sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==", + "license": "MIT", "dependencies": { "typewise-core": "^1.2" } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -7449,14 +7929,15 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001663", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz", - "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==", + "version": "1.0.30001706", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz", + "integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==", "funding": [ { "type": "opencollective", @@ -7470,7 +7951,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "4.1.2", @@ -7498,9 +7980,10 @@ } }, "node_modules/cheap-ruler": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/cheap-ruler/-/cheap-ruler-3.0.2.tgz", - "integrity": "sha512-02T332h1/HTN6cDSufLP8x4JzDs2+VC+8qZ/N0kWIVPyc2xUkWwWh3B2fJxR7raXkL4Mq7k554mfuM9ofv/vGg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cheap-ruler/-/cheap-ruler-4.0.0.tgz", + "integrity": "sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw==", + "license": "ISC", "optional": true, "peer": true }, @@ -7508,6 +7991,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -7531,6 +8015,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -7672,7 +8157,8 @@ "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" }, "node_modules/cliui": { "version": "8.0.1", @@ -7780,6 +8266,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", "engines": { "node": ">= 6" } @@ -8005,9 +8492,9 @@ } }, "node_modules/css-blank-pseudo": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-6.0.2.tgz", - "integrity": "sha512-J/6m+lsqpKPqWHOifAFtKFeGLOzw3jR92rxQcwRUfA/eTuZzKfKlxOmYDx2+tqOPQAueNvBiY8WhAeHu5qNmTg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-7.0.1.tgz", + "integrity": "sha512-jf+twWGDf6LDoXDUode+nc7ZlrqfaNphrBIBrcmeP3D8yw1uPaix1gCC8LUQUGQ6CycuK2opkbFFWFuq/a94ag==", "dev": true, "funding": [ { @@ -8019,20 +8506,21 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "postcss-selector-parser": "^6.0.13" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/css-has-pseudo": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-6.0.5.tgz", - "integrity": "sha512-ZTv6RlvJJZKp32jPYnAJVhowDCrRrHUTAxsYSuUPBEDJjzws6neMnzkRblxtgmv1RgcV5dhH2gn7E3wA9Wt6lw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-7.0.2.tgz", + "integrity": "sha512-nzol/h+E0bId46Kn2dQH5VElaknX2Sr0hFuB/1EomdC7j+OISt2ZzK7EHX9DZDY53WbIVAR7FYKSO2XnSf07MQ==", "dev": true, "funding": [ { @@ -8044,22 +8532,23 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/selector-specificity": "^3.1.1", - "postcss-selector-parser": "^6.0.13", + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/css-prefers-color-scheme": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-9.0.1.tgz", - "integrity": "sha512-iFit06ochwCKPRiWagbTa1OAWCvWWVdEnIFd8BaRrgO8YrrNh4RAWUQTFcYX5tdFZgFl1DJ3iiULchZyEbnF4g==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-10.0.0.tgz", + "integrity": "sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==", "dev": true, "funding": [ { @@ -8071,8 +8560,9 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" @@ -8086,9 +8576,9 @@ "peer": true }, "node_modules/cssdb": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.1.1.tgz", - "integrity": "sha512-kRbSRgZoxtZNl5snb3nOzBkFOt5AwnephcUTIEFc2DebKG9PN50/cHarlwOooTxYQ/gxsnKs3BxykhNLmfvyLg==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.2.4.tgz", + "integrity": "sha512-3KSCVkjZJe/QxicVXnbyYSY26WsFc1YoMY7jep1ZKWMEVc7jEm6V2Xq2r+MX8WKQIuB7ofGbnr5iVI+aZpoSzg==", "dev": true, "funding": [ { @@ -8099,7 +8589,8 @@ "type": "github", "url": "https://github.com/sponsors/csstools" } - ] + ], + "license": "MIT-0" }, "node_modules/cssesc": { "version": "3.0.0", @@ -8125,14 +8616,15 @@ "dev": true }, "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -8142,29 +8634,31 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -8299,7 +8793,8 @@ "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "license": "Apache-2.0" }, "node_modules/dir-glob": { "version": "3.0.1", @@ -8316,18 +8811,20 @@ "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" }, "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, "node_modules/dot-prop": { @@ -8336,10 +8833,25 @@ "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "dependencies": { - "is-obj": "^2.0.0" + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, "node_modules/duplexer2": { @@ -8352,21 +8864,22 @@ } }, "node_modules/earcut": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", - "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", - "optional": true, - "peer": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.1.tgz", + "integrity": "sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==", + "license": "ISC" }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.28", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.28.tgz", - "integrity": "sha512-VufdJl+rzaKZoYVUijN13QcXVF5dWPZANeFTLNy+OSpHdDL5ynXTF35+60RSBbaQYB1ae723lQXHCrf4pyLsMw==" + "version": "1.5.123", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.123.tgz", + "integrity": "sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==", + "license": "ISC" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -8379,19 +8892,6 @@ "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", "dev": true }, - "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/env-ci": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.1.0.tgz", @@ -8576,57 +9076,63 @@ "dev": true }, "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" }, "engines": { "node": ">= 0.4" @@ -8636,13 +9142,11 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -8677,35 +9181,39 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.2" + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -8714,37 +9222,44 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -8774,79 +9289,86 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", + "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.2", + "@eslint/config-helpers": "^0.1.0", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.0", + "@eslint/js": "9.22.0", + "@eslint/plugin-kit": "^0.2.7", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.3.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-next": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.13.tgz", - "integrity": "sha512-aro1EKAoyYchnO/3Tlo91hnNBO7QO7qnv/79MAFC+4Jq8TdUVKQlht5d2F+YjrePjdpOvfL+mV9JPfyYNwkk1g==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.2.3.tgz", + "integrity": "sha512-VDQwbajhNMFmrhLWVyUXCqsGPN+zz5G8Ys/QwFubfsxTIrkqdx3N3x3QPW+pERz8bzGPP0IgEm8cNbZcd8PFRQ==", "dev": true, + "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "14.2.13", - "@rushstack/eslint-patch": "^1.3.3", + "@next/eslint-plugin-next": "15.2.3", + "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^5.0.0" }, "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", + "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", "typescript": ">=3.3.1" }, "peerDependenciesMeta": { @@ -8856,10 +9378,11 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz", + "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -8888,19 +9411,19 @@ } }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", - "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.9.1.tgz", + "integrity": "sha512-euxa5rTGqHeqVxmOHT25hpk58PxkQ4mNoX6Yun4ooGaCHAxOCojJYNvjmyeOQxj/LyW+3fulH0+xtk+p2kPPTw==", "dev": true, + "license": "ISC", "dependencies": { "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.3.5", - "enhanced-resolve": "^5.15.0", - "eslint-module-utils": "^2.8.1", - "fast-glob": "^3.3.2", - "get-tsconfig": "^4.7.5", - "is-bun-module": "^1.0.2", - "is-glob": "^4.0.3" + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^1.3.0", + "rspack-resolver": "^1.1.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.12" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -8922,11 +9445,30 @@ } } }, + "node_modules/eslint-import-resolver-typescript/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/eslint-module-utils": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.1.tgz", - "integrity": "sha512-EwcbfLOhwVMAfatfqLecR2yv3dE5+kQ8kx+Rrt0DvDXEVwW86KQ/xbMDQhtp5l42VXukD5SOF8mQQHbaNtO0CQ==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -8953,10 +9495,11 @@ "link": true }, "node_modules/eslint-plugin-import": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", - "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, + "license": "MIT", "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.8", @@ -8966,7 +9509,7 @@ "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.9.0", + "eslint-module-utils": "^2.12.0", "hasown": "^2.0.2", "is-core-module": "^2.15.1", "is-glob": "^4.0.3", @@ -8975,13 +9518,14 @@ "object.groupby": "^1.0.3", "object.values": "^1.2.0", "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { @@ -8989,6 +9533,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -8999,27 +9544,17 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/eslint-plugin-import/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -9032,6 +9567,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -9089,10 +9625,11 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", + "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.9.1" @@ -9119,28 +9656,29 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.36.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.36.1.tgz", - "integrity": "sha512-/qwbqNXZoq+VP30s1d4Nc1C5GTxjJQjk4Jzs4Wq2qzxFM7dSmuG2UkIjg2USMLh3A/aVcUNrK7v0J5U1XEGGwA==", + "version": "7.37.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", + "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", + "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.19", + "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.8", "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", + "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "engines": { @@ -9151,15 +9689,16 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { @@ -9172,18 +9711,6 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/eslint-plugin-react/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -9223,16 +9750,17 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -9260,6 +9788,19 @@ "concat-map": "0.0.1" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -9273,17 +9814,31 @@ } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -9306,6 +9861,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -9379,6 +9935,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "license": "MIT", "dependencies": { "is-extendable": "^0.1.0" }, @@ -9406,7 +9963,8 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -9444,7 +10002,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -9481,15 +10040,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -9557,40 +10117,49 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -9604,6 +10173,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", "engines": { "node": ">=14" }, @@ -9624,16 +10194,19 @@ } }, "node_modules/framer-motion": { - "version": "11.5.6", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.5.6.tgz", - "integrity": "sha512-JMwUpAxv/DWgul9vPgX0ElKn0G66sUc6O9tOXsYwn3zxwvhxFljSXC0XT2QCzuTYBshwC8nyDAa1SYcV0Ldbhw==", + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.5.0.tgz", + "integrity": "sha512-buPlioFbH9/W7rDzYh1C09AuZHAk2D1xTA1BlounJ2Rb9aRg84OXexP0GLd+R83v0khURdMX7b5MKnGTaSg5iA==", + "license": "MIT", "dependencies": { + "motion-dom": "^12.5.0", + "motion-utils": "^12.5.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/is-prop-valid": { @@ -9671,17 +10244,12 @@ "node": ">=14.14" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -9711,15 +10279,18 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -9743,11 +10314,10 @@ "integrity": "sha512-gVGxBW+s1csexXVMf5bIwz3TH9n4sCEglOOOqmrPk8YazUI5f79jCowKjTw05m/0h1//3+Z2m/nv8IIozgZyUw==" }, "node_modules/geojson-vt": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz", - "integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==", - "optional": true, - "peer": true + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-4.0.2.tgz", + "integrity": "sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==", + "license": "ISC" }, "node_modules/get-caller-file": { "version": "2.0.5", @@ -9759,16 +10329,22 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -9777,6 +10353,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-7.0.1.tgz", @@ -9790,14 +10380,15 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -9807,10 +10398,11 @@ } }, "node_modules/get-tsconfig": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", - "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", "dev": true, + "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" }, @@ -9822,6 +10414,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9846,21 +10439,20 @@ "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==" }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=16 || 14 >=14.17" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -9913,15 +10505,13 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -9976,12 +10566,13 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10057,10 +10648,14 @@ } }, "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -10069,10 +10664,11 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10207,16 +10803,17 @@ } }, "node_modules/import-from-esm": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/import-from-esm/-/import-from-esm-1.3.4.tgz", - "integrity": "sha512-7EyUlPFC0HOlBDpUFGfYstsU7XHxZJKAAMzCT8wZ0hMW7b+hG51LIKTDcsgtz8Pu6YC0HqRVbX+rVUtsGMUKvg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-from-esm/-/import-from-esm-2.0.0.tgz", + "integrity": "sha512-YVt14UZCgsX1vZQ3gKjkWVdBdHQ6eu3MPU1TBgL1H5orXe2+jWD006WCPPtOuwlQm10NuzOW5WawiF1Q9veW8g==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4", "import-meta-resolve": "^4.0.0" }, "engines": { - "node": ">=16.20" + "node": ">=18.20" } }, "node_modules/import-meta-resolve": { @@ -10259,17 +10856,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -10295,14 +10881,15 @@ } }, "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -10353,13 +10940,15 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -10374,12 +10963,17 @@ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -10389,12 +10983,16 @@ } }, "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10404,6 +11002,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -10412,13 +11011,14 @@ } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10428,10 +11028,11 @@ } }, "node_modules/is-bun-module": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", - "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz", + "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.6.3" } @@ -10463,11 +11064,14 @@ } }, "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, + "license": "MIT", "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" }, "engines": { @@ -10478,12 +11082,14 @@ } }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10496,6 +11102,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10509,12 +11116,16 @@ } }, "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10529,12 +11140,16 @@ } }, "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -10566,18 +11181,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -10587,12 +11190,14 @@ } }, "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10610,19 +11215,11 @@ "node": ">=8" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, @@ -10631,13 +11228,16 @@ } }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -10659,12 +11259,13 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -10686,12 +11287,14 @@ } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10701,12 +11304,15 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -10716,12 +11322,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, + "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -10755,12 +11362,16 @@ } }, "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10797,6 +11408,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10818,28 +11430,31 @@ } }, "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -10857,9 +11472,10 @@ } }, "node_modules/jiti": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "license": "MIT", "bin": { "jiti": "bin/jiti.js" } @@ -10891,7 +11507,8 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-better-errors": { "version": "1.0.2", @@ -10909,7 +11526,8 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -10927,6 +11545,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -10971,6 +11590,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -11015,11 +11635,15 @@ } }, "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lines-and-columns": { @@ -11087,13 +11711,6 @@ "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", "dev": true }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "optional": true, - "peer": true - }, "node_modules/lodash.escaperegexp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", @@ -11140,14 +11757,24 @@ "loose-envify": "cli.js" } }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, "node_modules/mapbox-gl": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.2.0.tgz", - "integrity": "sha512-v8S7x+wTr35kJ9nqzgn/VPiSFZxBkyQhwCk9bdyiFHVwCukNGG3LXt03FoaHHTsOuB9JWenWE96k0Uw+HGMZ8w==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.10.0.tgz", + "integrity": "sha512-YnQxjlthuv/tidcxGYU2C8nRDVXMlAHa3qFhuOJeX4AfRP72OMRBf9ApL+M+k5VWcAXi2fcNOUVgphknjLumjA==", + "license": "SEE LICENSE IN LICENSE.txt", "optional": true, "peer": true, + "workspaces": [ + "src/style-spec", + "test/build/typings" + ], "dependencies": { - "@mapbox/geojson-rewind": "^0.5.2", "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/mapbox-gl-supported": "^3.0.0", "@mapbox/point-geometry": "^0.1.0", @@ -11155,30 +11782,34 @@ "@mapbox/unitbezier": "^0.0.1", "@mapbox/vector-tile": "^1.3.1", "@mapbox/whoots-js": "^3.1.0", - "cheap-ruler": "^3.0.1", + "@types/geojson": "^7946.0.16", + "@types/geojson-vt": "^3.2.5", + "@types/mapbox__point-geometry": "^0.1.4", + "@types/mapbox__vector-tile": "^1.3.4", + "@types/pbf": "^3.0.5", + "@types/supercluster": "^7.1.3", + "cheap-ruler": "^4.0.0", "csscolorparser": "~1.0.3", - "earcut": "^2.2.4", - "geojson-vt": "^3.2.1", + "earcut": "^3.0.0", + "geojson-vt": "^4.0.2", "gl-matrix": "^3.4.3", "grid-index": "^1.1.0", - "kdbush": "^4.0.1", - "lodash.clonedeep": "^4.5.0", + "kdbush": "^4.0.2", "murmurhash-js": "^1.0.0", "pbf": "^3.2.1", "potpack": "^2.0.0", - "quickselect": "^2.0.0", - "rw": "^1.3.3", + "quickselect": "^3.0.0", "serialize-to-js": "^3.1.2", - "supercluster": "^8.0.0", - "tinyqueue": "^2.0.3", - "tweakpane": "^4.0.3", + "supercluster": "^8.0.1", + "tinyqueue": "^3.0.0", "vt-pbf": "^3.1.3" } }, "node_modules/maplibre-gl": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-4.7.1.tgz", - "integrity": "sha512-lgL7XpIwsgICiL82ITplfS7IGwrB1OJIw/pCvprDp2dhmSSEBgmPzYRvwYYYvJGJD7fxUv1Tvpih4nZ6VrLuaA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.2.0.tgz", + "integrity": "sha512-9zZKD0M80qtDsqBet+EDuAhoCeA/cnAuZAA0p3hcGKGbyjM/SH+R6wQvnBEgvJz9UhDynnkoKdUwhI+fUkHoXQ==", + "license": "BSD-3-Clause", "dependencies": { "@mapbox/geojson-rewind": "^0.5.2", "@mapbox/jsonlint-lines-primitives": "^2.0.2", @@ -11187,14 +11818,14 @@ "@mapbox/unitbezier": "^0.0.1", "@mapbox/vector-tile": "^1.3.1", "@mapbox/whoots-js": "^3.1.0", - "@maplibre/maplibre-gl-style-spec": "^20.3.1", - "@types/geojson": "^7946.0.14", + "@maplibre/maplibre-gl-style-spec": "^23.1.0", + "@types/geojson": "^7946.0.16", "@types/geojson-vt": "3.2.5", "@types/mapbox__point-geometry": "^0.1.4", "@types/mapbox__vector-tile": "^1.3.4", "@types/pbf": "^3.0.5", "@types/supercluster": "^7.1.3", - "earcut": "^3.0.0", + "earcut": "^3.0.1", "geojson-vt": "^4.0.2", "gl-matrix": "^3.4.3", "global-prefix": "^4.0.0", @@ -11215,26 +11846,6 @@ "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1" } }, - "node_modules/maplibre-gl/node_modules/earcut": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.0.tgz", - "integrity": "sha512-41Fs7Q/PLq1SDbqjsgcY7GA42T0jvaCNGXgGtsNdvg+Yv8eIu06bxv4/PoREkZ9nMDNwnUSG9OFB9+yv8eKhDg==" - }, - "node_modules/maplibre-gl/node_modules/geojson-vt": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-4.0.2.tgz", - "integrity": "sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==" - }, - "node_modules/maplibre-gl/node_modules/quickselect": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", - "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==" - }, - "node_modules/maplibre-gl/node_modules/tinyqueue": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", - "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==" - }, "node_modules/marked": { "version": "12.0.2", "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", @@ -11279,6 +11890,16 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -11355,10 +11976,26 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, + "node_modules/motion-dom": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.5.0.tgz", + "integrity": "sha512-uH2PETDh7m+Hjd1UQQ56yHqwn83SAwNjimNPE/kC+Kds0t4Yh7+29rfo5wezVFpPOv57U4IuWved5d1x0kNhbQ==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.5.0" + } + }, + "node_modules/motion-utils": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.5.0.tgz", + "integrity": "sha512-+hFFzvimn0sBMP9iPxBa9OtRX35ZQ3py0UHnb8U29VD+d8lQ8zH3dTygJWqK7av2v6yhg7scj9iZuvTS0f4+SA==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -11421,11 +12058,12 @@ "dev": true }, "node_modules/next": { - "version": "14.2.24", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.24.tgz", - "integrity": "sha512-En8VEexSJ0Py2FfVnRRh8gtERwDRaJGNvsvad47ShkC2Yi8AXQPXEA2vKoDJlGFSj5WE5SyF21zNi4M5gyi+SQ==", + "version": "14.2.25", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.25.tgz", + "integrity": "sha512-N5M7xMc4wSb4IkPvEV5X2BRRXUmhVHNyaXwEM86+voXthSZz8ZiRyQW4p9mwAoAPIm6OzuVZtn7idgEJeAJN3Q==", + "license": "MIT", "dependencies": { - "@next/env": "14.2.24", + "@next/env": "14.2.25", "@swc/helpers": "0.5.5", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", @@ -11440,15 +12078,15 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.24", - "@next/swc-darwin-x64": "14.2.24", - "@next/swc-linux-arm64-gnu": "14.2.24", - "@next/swc-linux-arm64-musl": "14.2.24", - "@next/swc-linux-x64-gnu": "14.2.24", - "@next/swc-linux-x64-musl": "14.2.24", - "@next/swc-win32-arm64-msvc": "14.2.24", - "@next/swc-win32-ia32-msvc": "14.2.24", - "@next/swc-win32-x64-msvc": "14.2.24" + "@next/swc-darwin-arm64": "14.2.25", + "@next/swc-darwin-x64": "14.2.25", + "@next/swc-linux-arm64-gnu": "14.2.25", + "@next/swc-linux-arm64-musl": "14.2.25", + "@next/swc-linux-x64-gnu": "14.2.25", + "@next/swc-linux-x64-musl": "14.2.25", + "@next/swc-win32-arm64-msvc": "14.2.25", + "@next/swc-win32-ia32-msvc": "14.2.25", + "@next/swc-win32-x64-msvc": "14.2.25" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -11473,6 +12111,7 @@ "version": "0.5.5", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3", "tslib": "^2.4.0" @@ -11521,14 +12160,16 @@ } }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -14338,15 +14979,17 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -14380,14 +15023,17 @@ } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -14434,6 +15080,7 @@ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -14444,12 +15091,14 @@ } }, "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -14466,15 +15115,6 @@ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -14507,6 +15147,24 @@ "node": ">= 0.8.0" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-each-series": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-3.0.0.tgz", @@ -14603,6 +15261,12 @@ "node": ">=4" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -14686,15 +15350,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -14712,6 +15367,7 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -14723,11 +15379,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -14820,6 +15471,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "license": "MIT", "engines": { "node": ">= 6" } @@ -14896,12 +15548,12 @@ } }, "node_modules/pmtiles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pmtiles/-/pmtiles-3.2.0.tgz", - "integrity": "sha512-4v3Nw5xeMxaUReLZQTz3PyM4VM/Lx/Xp/rc2GGEWMl0nqAmcb+gjyi+eOTwfPu8LnB0ash36hz0dV76uYvih5A==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/pmtiles/-/pmtiles-4.3.0.tgz", + "integrity": "sha512-wnzQeSiYT/MyO63o7AVxwt7+uKqU0QUy2lHrivM7GvecNy0m1A4voVyGey7bujnEW5Hn+ZzLdvHPoFaqrOzbPA==", + "license": "BSD-3-Clause", "dependencies": { - "@types/leaflet": "^1.9.8", - "fflate": "^0.8.0" + "fflate": "^0.8.2" } }, "node_modules/polyclip-ts": { @@ -14923,9 +15575,9 @@ } }, "node_modules/postcss": { - "version": "8.4.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", - "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -14940,19 +15592,20 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, "node_modules/postcss-attribute-case-insensitive": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-6.0.3.tgz", - "integrity": "sha512-KHkmCILThWBRtg+Jn1owTnHPnFit4OkqS+eKiGEOPIGke54DCeYGJ6r0Fx/HjfE9M9kznApCLcU0DvnPchazMQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-7.0.1.tgz", + "integrity": "sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==", "dev": true, "funding": [ { @@ -14964,11 +15617,12 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.0.13" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" @@ -14990,9 +15644,9 @@ } }, "node_modules/postcss-color-functional-notation": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-6.0.14.tgz", - "integrity": "sha512-dNUX+UH4dAozZ8uMHZ3CtCNYw8fyFAmqqdcyxMr7PEdM9jLXV19YscoYO0F25KqZYhmtWKQ+4tKrIZQrwzwg7A==", + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.8.tgz", + "integrity": "sha512-S/TpMKVKofNvsxfau/+bw+IA6cSfB6/kmzFj5szUofHOVnFFMB2WwK+Zu07BeMD8T0n+ZnTO5uXiMvAKe2dPkA==", "dev": true, "funding": [ { @@ -15004,24 +15658,25 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0" + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-color-hex-alpha": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-9.0.4.tgz", - "integrity": "sha512-XQZm4q4fNFqVCYMGPiBjcqDhuG7Ey2xrl99AnDJMyr5eDASsAGalndVgHZF8i97VFNy1GQeZc4q2ydagGmhelQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-10.0.0.tgz", + "integrity": "sha512-1kervM2cnlgPs2a8Vt/Qbe5cQ++N7rkYo/2rz2BkqJZIHQwaVuJgQH38REHrAi4uM0b1fqxMkWYmese94iMp3w==", "dev": true, "funding": [ { @@ -15033,21 +15688,22 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "dependencies": { - "@csstools/utilities": "^1.0.0", + "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-color-rebeccapurple": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-9.0.3.tgz", - "integrity": "sha512-ruBqzEFDYHrcVq3FnW3XHgwRqVMrtEPLBtD7K2YmsLKVc2jbkxzzNEctJKsPCpDZ+LeMHLKRDoSShVefGc+CkQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-10.0.0.tgz", + "integrity": "sha512-JFta737jSP+hdAIEhk1Vs0q0YF5P8fFcj+09pweS8ktuGuZ8pPlykHsk6mPxZ8awDl4TrcxUqJo9l1IhVr/OjQ==", "dev": true, "funding": [ { @@ -15059,21 +15715,22 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/utilities": "^1.0.0", + "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-custom-media": { - "version": "10.0.8", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-10.0.8.tgz", - "integrity": "sha512-V1KgPcmvlGdxTel4/CyQtBJEFhMVpEmRGFrnVtgfGIHj5PJX9vO36eFBxKBeJn+aCDTed70cc+98Mz3J/uVdGQ==", + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-11.0.5.tgz", + "integrity": "sha512-SQHhayVNgDvSAdX9NQ/ygcDQGEY+aSF4b/96z7QUX6mqL5yl/JgG/DywcF6fW9XbnCRE+aVYk+9/nqGuzOPWeQ==", "dev": true, "funding": [ { @@ -15085,23 +15742,24 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "dependencies": { - "@csstools/cascade-layer-name-parser": "^1.0.13", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/media-query-list-parser": "^2.1.13" + "@csstools/cascade-layer-name-parser": "^2.0.4", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/media-query-list-parser": "^4.0.2" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-custom-properties": { - "version": "13.3.12", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-13.3.12.tgz", - "integrity": "sha512-oPn/OVqONB2ZLNqN185LDyaVByELAA/u3l2CS2TS16x2j2XsmV4kd8U49+TMxmUsEU9d8fB/I10E6U7kB0L1BA==", + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.4.tgz", + "integrity": "sha512-QnW8FCCK6q+4ierwjnmXF9Y9KF8q0JkbgVfvQEMa93x1GT8FvOiUevWCN2YLaOWyByeDX8S6VFbZEeWoAoXs2A==", "dev": true, "funding": [ { @@ -15113,24 +15771,25 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "dependencies": { - "@csstools/cascade-layer-name-parser": "^1.0.13", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/utilities": "^1.0.0", + "@csstools/cascade-layer-name-parser": "^2.0.4", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-custom-selectors": { - "version": "7.1.12", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-7.1.12.tgz", - "integrity": "sha512-ctIoprBMJwByYMGjXG0F7IT2iMF2hnamQ+aWZETyBM0aAlyaYdVZTeUkk8RB+9h9wP+NdN3f01lfvKl2ZSqC0g==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-8.0.4.tgz", + "integrity": "sha512-ASOXqNvDCE0dAJ/5qixxPeL1aOVGHGW2JwSy7HyjWNbnWTQCl+fDc968HY1jCmZI0+BaYT5CxsOiUhavpG/7eg==", "dev": true, "funding": [ { @@ -15142,23 +15801,24 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "dependencies": { - "@csstools/cascade-layer-name-parser": "^1.0.13", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "postcss-selector-parser": "^6.1.0" + "@csstools/cascade-layer-name-parser": "^2.0.4", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-dir-pseudo-class": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-8.0.1.tgz", - "integrity": "sha512-uULohfWBBVoFiZXgsQA24JV6FdKIidQ+ZqxOouhWwdE+qJlALbkS5ScB43ZTjPK+xUZZhlaO/NjfCt5h4IKUfw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-9.0.1.tgz", + "integrity": "sha512-tRBEK0MHYvcMUrAuYMEOa0zg9APqirBcgzi6P21OhxtJyJADo/SWBwY1CAwEohQ/6HDaa9jCjLRG7K3PVQYHEA==", "dev": true, "funding": [ { @@ -15170,20 +15830,21 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "postcss-selector-parser": "^6.0.13" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-double-position-gradients": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-5.0.7.tgz", - "integrity": "sha512-1xEhjV9u1s4l3iP5lRt1zvMjI/ya8492o9l/ivcxHhkO3nOz16moC4JpMxDUGrOs4R3hX+KWT7gKoV842cwRgg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.0.tgz", + "integrity": "sha512-JkIGah3RVbdSEIrcobqj4Gzq0h53GG4uqDPsho88SgY84WnpkTpI0k50MFK/sX7XqVisZ6OqUfFnoUO6m1WWdg==", "dev": true, "funding": [ { @@ -15195,22 +15856,23 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-focus-visible": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-9.0.1.tgz", - "integrity": "sha512-N2VQ5uPz3Z9ZcqI5tmeholn4d+1H14fKXszpjogZIrFbhaq0zNAtq8sAnw6VLiqGbL8YBzsnu7K9bBkTqaRimQ==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-10.0.1.tgz", + "integrity": "sha512-U58wyjS/I1GZgjRok33aE8juW9qQgQUNwTSdxQGuShHzwuYdcklnvK/+qOWX1Q9kr7ysbraQ6ht6r+udansalA==", "dev": true, "funding": [ { @@ -15222,20 +15884,21 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "postcss-selector-parser": "^6.0.13" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-focus-within": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-8.0.1.tgz", - "integrity": "sha512-NFU3xcY/xwNaapVb+1uJ4n23XImoC86JNwkY/uduytSl2s9Ekc2EpzmRR63+ExitnW3Mab3Fba/wRPCT5oDILA==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-9.0.1.tgz", + "integrity": "sha512-fzNUyS1yOYa7mOjpci/bR+u+ESvdar6hk8XNK/TRR0fiGTp2QT5N+ducP0n3rfH/m9I7H/EQU6lsa2BrgxkEjw==", "dev": true, "funding": [ { @@ -15247,11 +15910,12 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "postcss-selector-parser": "^6.0.13" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" @@ -15267,9 +15931,9 @@ } }, "node_modules/postcss-gap-properties": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-5.0.1.tgz", - "integrity": "sha512-k2z9Cnngc24c0KF4MtMuDdToROYqGMMUQGcE6V0odwjHyOHtaDBlLeRBV70y9/vF7KIbShrTRZ70JjsI1BZyWw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-6.0.0.tgz", + "integrity": "sha512-Om0WPjEwiM9Ru+VhfEDPZJAKWUd0mV1HmNXqp2C29z80aQ2uP9UVhLc7e3aYMIor/S5cVhoPgYQ7RtfeZpYTRw==", "dev": true, "funding": [ { @@ -15281,17 +15945,18 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-image-set-function": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-6.0.3.tgz", - "integrity": "sha512-i2bXrBYzfbRzFnm+pVuxVePSTCRiNmlfssGI4H0tJQvDue+yywXwUxe68VyzXs7cGtMaH6MCLY6IbCShrSroCw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-7.0.0.tgz", + "integrity": "sha512-QL7W7QNlZuzOwBTeXEmbVckNt1FSmhQtbMRvGGqqU4Nf4xk6KUEQhAoWuMzwbSv5jxiRiSZ5Tv7eiDB9U87znA==", "dev": true, "funding": [ { @@ -15303,12 +15968,13 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/utilities": "^1.0.0", + "@csstools/utilities": "^2.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" @@ -15318,6 +15984,7 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -15334,6 +16001,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" }, @@ -15349,9 +16017,9 @@ } }, "node_modules/postcss-lab-function": { - "version": "6.0.19", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-6.0.19.tgz", - "integrity": "sha512-vwln/mgvFrotJuGV8GFhpAOu9iGf3pvTBr6dLPDmUcqVD5OsQpEFyQMAFTxSxWXGEzBj6ld4pZ/9GDfEpXvo0g==", + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.8.tgz", + "integrity": "sha512-plV21I86Hg9q8omNz13G9fhPtLopIWH06bt/Cb5cs1XnaGU2kUtEitvVd4vtQb/VqCdNUHK5swKn3QFmMRbpDg==", "dev": true, "funding": [ { @@ -15363,15 +16031,16 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/css-color-parser": "^2.0.4", - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/utilities": "^1.0.0" + "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" @@ -15391,6 +16060,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" @@ -15411,21 +16081,10 @@ } } }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, "node_modules/postcss-logical": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-7.0.1.tgz", - "integrity": "sha512-8GwUQZE0ri0K0HJHkDv87XOLC8DE0msc+HoWLeKdtjDZEwpZ5xuK3QdV6FhmHSQW40LPkg43QzvATRAI3LsRkg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-8.1.0.tgz", + "integrity": "sha512-pL1hXFQ2fEXNKiNiAgtfA005T9FBxky5zkX6s4GZM2D8RkVgRqz3f4g1JUoq925zXv495qk8UNldDwh8uGEDoA==", "dev": true, "funding": [ { @@ -15437,11 +16096,12 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" @@ -15461,6 +16121,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.1.1" }, @@ -15471,10 +16132,23 @@ "postcss": "^8.2.14" } }, + "node_modules/postcss-nested/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss-nesting": { - "version": "12.1.5", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.1.5.tgz", - "integrity": "sha512-N1NgI1PDCiAGWPTYrwqm8wpjv0bgDmkYHH72pNsqTCv9CObxjxftdYu6AKtGN+pnJa7FQjMm3v4sp8QJbFsYdQ==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz", + "integrity": "sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==", "dev": true, "funding": [ { @@ -15486,22 +16160,46 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "@csstools/selector-resolve-nested": "^1.1.0", - "@csstools/selector-specificity": "^3.1.1", - "postcss-selector-parser": "^6.1.0" + "@csstools/selector-resolve-nested": "^3.0.0", + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, + "node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.0.0.tgz", + "integrity": "sha512-ZoK24Yku6VJU1gS79a5PFmC8yn3wIapiKmPgun0hZgEI5AOqgH2kiPRsPz1qkGv4HL+wuDLH83yQyk6inMYrJQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, "node_modules/postcss-opacity-percentage": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-2.0.0.tgz", - "integrity": "sha512-lyDrCOtntq5Y1JZpBFzIWm2wG9kbEdujpNt4NLannF+J9c8CgFIzPa80YQfdza+Y+yFfzbYj/rfoOsYsooUWTQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-3.0.0.tgz", + "integrity": "sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==", "dev": true, "funding": [ { @@ -15513,17 +16211,18 @@ "url": "https://liberapay.com/mrcgrtz" } ], + "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { - "postcss": "^8.2" + "postcss": "^8.4" } }, "node_modules/postcss-overflow-shorthand": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-5.0.1.tgz", - "integrity": "sha512-XzjBYKLd1t6vHsaokMV9URBt2EwC9a7nDhpQpjoPk2HRTSQfokPfyAS/Q7AOrzUu6q+vp/GnrDBGuj/FCaRqrQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-6.0.0.tgz", + "integrity": "sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==", "dev": true, "funding": [ { @@ -15535,11 +16234,12 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" @@ -15555,9 +16255,9 @@ } }, "node_modules/postcss-place": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-9.0.1.tgz", - "integrity": "sha512-JfL+paQOgRQRMoYFc2f73pGuG/Aw3tt4vYMR6UA3cWVMxivviPTnMFnFTczUJOA4K2Zga6xgQVE+PcLs64WC8Q==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-10.0.0.tgz", + "integrity": "sha512-5EBrMzat2pPAxQNWYavwAfoKfYcTADJ8AXGVPcUZ2UkNloUTWzJQExgrzrDkh3EKzmAx1evfTAzF9I8NGcc+qw==", "dev": true, "funding": [ { @@ -15569,20 +16269,21 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-preset-env": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-9.6.0.tgz", - "integrity": "sha512-Lxfk4RYjUdwPCYkc321QMdgtdCP34AeI94z+/8kVmqnTIlD4bMRQeGcMZgwz8BxHrzQiFXYIR5d7k/9JMs2MEA==", + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.1.5.tgz", + "integrity": "sha512-LQybafF/K7H+6fAs4SIkgzkSCixJy0/h0gubDIAP3Ihz+IQBRwsjyvBnAZ3JUHD+A/ITaxVRPDxn//a3Qy4pDw==", "dev": true, "funding": [ { @@ -15594,80 +16295,83 @@ "url": "https://opencollective.com/csstools" } ], - "dependencies": { - "@csstools/postcss-cascade-layers": "^4.0.6", - "@csstools/postcss-color-function": "^3.0.19", - "@csstools/postcss-color-mix-function": "^2.0.19", - "@csstools/postcss-content-alt-text": "^1.0.0", - "@csstools/postcss-exponential-functions": "^1.0.9", - "@csstools/postcss-font-format-keywords": "^3.0.2", - "@csstools/postcss-gamut-mapping": "^1.0.11", - "@csstools/postcss-gradients-interpolation-method": "^4.0.20", - "@csstools/postcss-hwb-function": "^3.0.18", - "@csstools/postcss-ic-unit": "^3.0.7", - "@csstools/postcss-initial": "^1.0.1", - "@csstools/postcss-is-pseudo-class": "^4.0.8", - "@csstools/postcss-light-dark-function": "^1.0.8", - "@csstools/postcss-logical-float-and-clear": "^2.0.1", - "@csstools/postcss-logical-overflow": "^1.0.1", - "@csstools/postcss-logical-overscroll-behavior": "^1.0.1", - "@csstools/postcss-logical-resize": "^2.0.1", - "@csstools/postcss-logical-viewport-units": "^2.0.11", - "@csstools/postcss-media-minmax": "^1.1.8", - "@csstools/postcss-media-queries-aspect-ratio-number-values": "^2.0.11", - "@csstools/postcss-nested-calc": "^3.0.2", - "@csstools/postcss-normalize-display-values": "^3.0.2", - "@csstools/postcss-oklab-function": "^3.0.19", - "@csstools/postcss-progressive-custom-properties": "^3.3.0", - "@csstools/postcss-relative-color-syntax": "^2.0.19", - "@csstools/postcss-scope-pseudo-class": "^3.0.1", - "@csstools/postcss-stepped-value-functions": "^3.0.10", - "@csstools/postcss-text-decoration-shorthand": "^3.0.7", - "@csstools/postcss-trigonometric-functions": "^3.0.10", - "@csstools/postcss-unset-value": "^3.0.1", + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-cascade-layers": "^5.0.1", + "@csstools/postcss-color-function": "^4.0.8", + "@csstools/postcss-color-mix-function": "^3.0.8", + "@csstools/postcss-content-alt-text": "^2.0.4", + "@csstools/postcss-exponential-functions": "^2.0.7", + "@csstools/postcss-font-format-keywords": "^4.0.0", + "@csstools/postcss-gamut-mapping": "^2.0.8", + "@csstools/postcss-gradients-interpolation-method": "^5.0.8", + "@csstools/postcss-hwb-function": "^4.0.8", + "@csstools/postcss-ic-unit": "^4.0.0", + "@csstools/postcss-initial": "^2.0.1", + "@csstools/postcss-is-pseudo-class": "^5.0.1", + "@csstools/postcss-light-dark-function": "^2.0.7", + "@csstools/postcss-logical-float-and-clear": "^3.0.0", + "@csstools/postcss-logical-overflow": "^2.0.0", + "@csstools/postcss-logical-overscroll-behavior": "^2.0.0", + "@csstools/postcss-logical-resize": "^3.0.0", + "@csstools/postcss-logical-viewport-units": "^3.0.3", + "@csstools/postcss-media-minmax": "^2.0.7", + "@csstools/postcss-media-queries-aspect-ratio-number-values": "^3.0.4", + "@csstools/postcss-nested-calc": "^4.0.0", + "@csstools/postcss-normalize-display-values": "^4.0.0", + "@csstools/postcss-oklab-function": "^4.0.8", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/postcss-random-function": "^1.0.3", + "@csstools/postcss-relative-color-syntax": "^3.0.8", + "@csstools/postcss-scope-pseudo-class": "^4.0.1", + "@csstools/postcss-sign-functions": "^1.1.2", + "@csstools/postcss-stepped-value-functions": "^4.0.7", + "@csstools/postcss-text-decoration-shorthand": "^4.0.2", + "@csstools/postcss-trigonometric-functions": "^4.0.7", + "@csstools/postcss-unset-value": "^4.0.0", "autoprefixer": "^10.4.19", - "browserslist": "^4.23.1", - "css-blank-pseudo": "^6.0.2", - "css-has-pseudo": "^6.0.5", - "css-prefers-color-scheme": "^9.0.1", - "cssdb": "^8.1.0", - "postcss-attribute-case-insensitive": "^6.0.3", + "browserslist": "^4.24.4", + "css-blank-pseudo": "^7.0.1", + "css-has-pseudo": "^7.0.2", + "css-prefers-color-scheme": "^10.0.0", + "cssdb": "^8.2.3", + "postcss-attribute-case-insensitive": "^7.0.1", "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^6.0.14", - "postcss-color-hex-alpha": "^9.0.4", - "postcss-color-rebeccapurple": "^9.0.3", - "postcss-custom-media": "^10.0.8", - "postcss-custom-properties": "^13.3.12", - "postcss-custom-selectors": "^7.1.12", - "postcss-dir-pseudo-class": "^8.0.1", - "postcss-double-position-gradients": "^5.0.7", - "postcss-focus-visible": "^9.0.1", - "postcss-focus-within": "^8.0.1", + "postcss-color-functional-notation": "^7.0.8", + "postcss-color-hex-alpha": "^10.0.0", + "postcss-color-rebeccapurple": "^10.0.0", + "postcss-custom-media": "^11.0.5", + "postcss-custom-properties": "^14.0.4", + "postcss-custom-selectors": "^8.0.4", + "postcss-dir-pseudo-class": "^9.0.1", + "postcss-double-position-gradients": "^6.0.0", + "postcss-focus-visible": "^10.0.1", + "postcss-focus-within": "^9.0.1", "postcss-font-variant": "^5.0.0", - "postcss-gap-properties": "^5.0.1", - "postcss-image-set-function": "^6.0.3", - "postcss-lab-function": "^6.0.19", - "postcss-logical": "^7.0.1", - "postcss-nesting": "^12.1.5", - "postcss-opacity-percentage": "^2.0.0", - "postcss-overflow-shorthand": "^5.0.1", + "postcss-gap-properties": "^6.0.0", + "postcss-image-set-function": "^7.0.0", + "postcss-lab-function": "^7.0.8", + "postcss-logical": "^8.1.0", + "postcss-nesting": "^13.0.1", + "postcss-opacity-percentage": "^3.0.0", + "postcss-overflow-shorthand": "^6.0.0", "postcss-page-break": "^3.0.4", - "postcss-place": "^9.0.1", - "postcss-pseudo-class-any-link": "^9.0.2", + "postcss-place": "^10.0.0", + "postcss-pseudo-class-any-link": "^10.0.1", "postcss-replace-overflow-wrap": "^4.0.0", - "postcss-selector-not": "^7.0.2" + "postcss-selector-not": "^8.0.1" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-pseudo-class-any-link": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-9.0.2.tgz", - "integrity": "sha512-HFSsxIqQ9nA27ahyfH37cRWGk3SYyQLpk0LiWw/UGMV4VKT5YG2ONee4Pz/oFesnK0dn2AjcyequDbIjKJgB0g==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-10.0.1.tgz", + "integrity": "sha512-3el9rXlBOqTFaMFkWDOkHUTQekFIYnaQY55Rsp8As8QQkpiSgIYEcF/6Ond93oHiDsGb4kad8zjt+NPlOC1H0Q==", "dev": true, "funding": [ { @@ -15679,11 +16383,12 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "dependencies": { - "postcss-selector-parser": "^6.0.13" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" @@ -15699,9 +16404,9 @@ } }, "node_modules/postcss-selector-not": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-7.0.2.tgz", - "integrity": "sha512-/SSxf/90Obye49VZIfc0ls4H0P6i6V1iHv0pzZH8SdgvZOPFkF37ef1r5cyWcMflJSFJ5bfuoluTnFnBBFiuSA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-8.0.1.tgz", + "integrity": "sha512-kmVy/5PYVb2UOhy0+LqUYAhKj7DUGDpSWa5LZqlkWJaaAV+dxxsOG3+St0yNLu6vsKD7Dmqx+nWQt0iil89+WA==", "dev": true, "funding": [ { @@ -15713,20 +16418,23 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.0.13" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "dev": true, + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -15898,6 +16606,7 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -15934,9 +16643,10 @@ } }, "node_modules/quickselect": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", - "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", + "license": "ISC" }, "node_modules/rc": { "version": "1.2.8", @@ -15972,6 +16682,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" }, @@ -15983,6 +16694,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -15992,9 +16704,10 @@ } }, "node_modules/react-icons": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz", - "integrity": "sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "license": "MIT", "peerDependencies": { "react": "*" } @@ -16006,12 +16719,13 @@ "dev": true }, "node_modules/react-map-gl": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/react-map-gl/-/react-map-gl-7.1.7.tgz", - "integrity": "sha512-mwjc0obkBJOXCcoXQr3VoLqmqwo9vS4bXfbGsdxXzEgVCv/PM0v+1QggL7W0d/ccIy+VCjbXNlGij+PENz6VNg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/react-map-gl/-/react-map-gl-8.0.1.tgz", + "integrity": "sha512-VQjLcZdtyJCPXxy5xVL2QIgfA+YG3v+PzSdt07WWbVmXFhV4wUuy6DZSQYDdfqVH2BujKo/ImdL5zfEJApRnpg==", + "license": "MIT", "dependencies": { - "@maplibre/maplibre-gl-style-spec": "^19.2.1", - "@types/mapbox-gl": ">=1.0.0" + "@vis.gl/react-mapbox": "8.0.1", + "@vis.gl/react-maplibre": "8.0.1" }, "peerDependencies": { "mapbox-gl": ">=1.13.0", @@ -16028,33 +16742,10 @@ } } }, - "node_modules/react-map-gl/node_modules/@maplibre/maplibre-gl-style-spec": { - "version": "19.3.3", - "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-19.3.3.tgz", - "integrity": "sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw==", - "dependencies": { - "@mapbox/jsonlint-lines-primitives": "~2.0.2", - "@mapbox/unitbezier": "^0.0.1", - "json-stringify-pretty-compact": "^3.0.0", - "minimist": "^1.2.8", - "rw": "^1.3.3", - "sort-object": "^3.0.3" - }, - "bin": { - "gl-style-format": "dist/gl-style-format.mjs", - "gl-style-migrate": "dist/gl-style-migrate.mjs", - "gl-style-validate": "dist/gl-style-validate.mjs" - } - }, - "node_modules/react-map-gl/node_modules/json-stringify-pretty-compact": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", - "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==" - }, "node_modules/react-textarea-autosize": { - "version": "8.5.7", - "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.7.tgz", - "integrity": "sha512-2MqJ3p0Jh69yt9ktFIaZmORHXw4c4bxSIhCeWiFwmJ9EYKgLmuNII3e9c9b2UO+ijl4StnpZdqpxNIhTdHvqtQ==", + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.8.tgz", + "integrity": "sha512-iUiIj70JefrTuSJ4LbVFiSqWiHHss5L63L717bqaWHMgkm9sz6eEvro4vZ3uQfGJbevzwT6rHOszHKA8RkhRMg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.13", @@ -16072,6 +16763,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "license": "MIT", "dependencies": { "pify": "^2.3.0" } @@ -16080,6 +16772,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -16144,12 +16837,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/read-pkg/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - }, "node_modules/read-pkg/node_modules/normalize-package-data": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", @@ -16201,6 +16888,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -16209,18 +16897,20 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -16236,15 +16926,18 @@ "license": "MIT" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -16304,6 +16997,7 @@ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } @@ -16325,63 +17019,27 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/rspack-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/rspack-resolver/-/rspack-resolver-1.2.2.tgz", + "integrity": "sha512-Fwc19jMBA3g+fxDJH2B4WxwZjE0VaaOL7OX/A4Wn5Zv7bOD/vyPZhzXfaO73Xc2GAlfi96g5fGUa378WbIGfFw==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, + "license": "MIT", "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" + "url": "https://github.com/sponsors/JounQin" }, - "engines": { - "node": "*" + "optionalDependencies": { + "@unrs/rspack-resolver-binding-darwin-arm64": "1.2.2", + "@unrs/rspack-resolver-binding-darwin-x64": "1.2.2", + "@unrs/rspack-resolver-binding-freebsd-x64": "1.2.2", + "@unrs/rspack-resolver-binding-linux-arm-gnueabihf": "1.2.2", + "@unrs/rspack-resolver-binding-linux-arm64-gnu": "1.2.2", + "@unrs/rspack-resolver-binding-linux-arm64-musl": "1.2.2", + "@unrs/rspack-resolver-binding-linux-x64-gnu": "1.2.2", + "@unrs/rspack-resolver-binding-linux-x64-musl": "1.2.2", + "@unrs/rspack-resolver-binding-wasm32-wasi": "1.2.2", + "@unrs/rspack-resolver-binding-win32-arm64-msvc": "1.2.2", + "@unrs/rspack-resolver-binding-win32-x64-msvc": "1.2.2" } }, "node_modules/run-parallel": { @@ -16412,14 +17070,16 @@ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" }, "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -16435,15 +17095,33 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "is-regex": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -16456,6 +17134,7 @@ "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" } @@ -16518,37 +17197,7 @@ "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", "dev": true, "engines": { - "node": ">=18" - } - }, - "node_modules/semantic-release/node_modules/@semantic-release/github": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.1.tgz", - "integrity": "sha512-Z9cr0LgU/zgucbT9cksH0/pX9zmVda9hkDPcgIE0uvjMQ8w/mElDivGjx1w1pEQ+MuQJ5CBq3VCF16S6G4VH3A==", - "dev": true, - "dependencies": { - "@octokit/core": "^6.0.0", - "@octokit/plugin-paginate-rest": "^11.0.0", - "@octokit/plugin-retry": "^7.0.0", - "@octokit/plugin-throttling": "^9.0.0", - "@semantic-release/error": "^4.0.0", - "aggregate-error": "^5.0.0", - "debug": "^4.3.4", - "dir-glob": "^3.0.1", - "globby": "^14.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", - "issue-parser": "^7.0.0", - "lodash-es": "^4.17.21", - "mime": "^4.0.0", - "p-filter": "^4.0.0", - "url-join": "^5.0.0" - }, - "engines": { - "node": ">=20.8.1" - }, - "peerDependencies": { - "semantic-release": ">=24.1.0" + "node": ">=18" } }, "node_modules/semantic-release/node_modules/@sindresorhus/merge-streams": { @@ -16681,19 +17330,6 @@ "node": ">=18.18.0" } }, - "node_modules/semantic-release/node_modules/import-from-esm": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-from-esm/-/import-from-esm-2.0.0.tgz", - "integrity": "sha512-YVt14UZCgsX1vZQ3gKjkWVdBdHQ6eu3MPU1TBgL1H5orXe2+jWD006WCPPtOuwlQm10NuzOW5WawiF1Q9veW8g==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "import-meta-resolve": "^4.0.0" - }, - "engines": { - "node": ">=18.20" - } - }, "node_modules/semantic-release/node_modules/indent-string": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", @@ -16730,12 +17366,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semantic-release/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - }, "node_modules/semantic-release/node_modules/npm-run-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", @@ -16901,10 +17531,26 @@ "node": ">= 0.4" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "license": "MIT", "dependencies": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -16973,15 +17619,73 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -17129,6 +17833,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", "integrity": "sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -17137,6 +17842,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.2.0.tgz", "integrity": "sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -17145,6 +17851,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-3.0.3.tgz", "integrity": "sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==", + "license": "MIT", "dependencies": { "bytewise": "^1.1.0", "get-value": "^2.0.2", @@ -17221,6 +17928,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "license": "MIT", "dependencies": { "extend-shallow": "^3.0.0" }, @@ -17232,6 +17940,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "license": "MIT", "dependencies": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -17244,6 +17953,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4" }, @@ -17260,6 +17970,13 @@ "through2": "~2.0.0" } }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -17303,6 +18020,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -17320,6 +18038,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -17332,12 +18051,14 @@ "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -17349,6 +18070,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -17370,23 +18092,25 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -17406,15 +18130,19 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -17424,15 +18152,20 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -17470,6 +18203,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -17500,6 +18234,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -17511,6 +18246,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "license": "MIT", "dependencies": { "client-only": "0.0.1" }, @@ -17533,6 +18269,7 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", @@ -17666,32 +18403,33 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.13", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz", - "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==", + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", - "chokidar": "^3.5.3", + "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.3.0", + "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.21.0", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", @@ -17701,13 +18439,17 @@ "node": ">=14.0.0" } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, + "node_modules/tailwindcss/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, "engines": { - "node": ">=6" + "node": ">=4" } }, "node_modules/temp-dir": { @@ -17761,12 +18503,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -17811,12 +18547,56 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tinyglobby": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", + "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", + "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tinyqueue": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", - "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==", - "optional": true, - "peer": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", + "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==", + "license": "ISC" }, "node_modules/to-regex-range": { "version": "5.0.1", @@ -17842,27 +18622,30 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0" }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -17875,16 +18658,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, - "node_modules/tweakpane": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/tweakpane/-/tweakpane-4.0.4.tgz", - "integrity": "sha512-RkWD54zDlEbnN01wQPk0ANHGbdCvlJx/E8A1QxhTfCbX+ROWos1Ws2MnhOm39aUGMOh+36TjUwpDmLfmwTr1Fg==", - "optional": true, - "peer": true, - "funding": { - "url": "https://github.com/sponsors/cocopon" - } - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -17897,43 +18670,33 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -17943,17 +18706,19 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -17963,17 +18728,18 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -17983,9 +18749,10 @@ } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -17998,6 +18765,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz", "integrity": "sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==", + "license": "MIT", "dependencies": { "typewise-core": "^1.2.0" } @@ -18005,7 +18773,8 @@ "node_modules/typewise-core": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz", - "integrity": "sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg==" + "integrity": "sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg==", + "license": "MIT" }, "node_modules/uglify-js": { "version": "3.19.3", @@ -18021,24 +18790,29 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" }, "node_modules/unicode-emoji-modifier-base": { "version": "1.0.0", @@ -18065,6 +18839,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "license": "MIT", "dependencies": { "arr-union": "^3.1.0", "get-value": "^2.0.6", @@ -18106,9 +18881,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -18123,9 +18898,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -18139,6 +18915,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -18203,16 +18980,16 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/validate-npm-package-license": { @@ -18250,39 +19027,45 @@ } }, "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, + "license": "MIT", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-builtin-type": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", - "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, + "license": "MIT", "dependencies": { + "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", + "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", + "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", - "which-typed-array": "^1.1.15" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -18310,15 +19093,18 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, "engines": { @@ -18347,6 +19133,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -18364,6 +19151,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -18379,12 +19167,14 @@ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -18398,6 +19188,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -18409,6 +19200,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -18420,6 +19212,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -18430,12 +19223,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -18455,9 +19242,10 @@ } }, "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "license": "ISC", "bin": { "yaml": "bin.mjs" }, diff --git a/package.json b/package.json index 84e1d58c..211b9785 100644 --- a/package.json +++ b/package.json @@ -12,52 +12,52 @@ "release": "semantic-release" }, "dependencies": { - "@heroicons/react": "^2.1.5", - "@maptiler/geocoding-control": "^1.4.1", - "@maptiler/sdk": "^2.5.1", + "@heroicons/react": "^2.2.0", + "@maptiler/geocoding-control": "^2.1.6", + "@maptiler/sdk": "^3.0.1", "@nextui-org/react": "^2.4.6", "@phosphor-icons/react": "^2.1.7", - "@turf/centroid": "^7.0.0", - "autoprefixer": "10.4.19", + "@turf/centroid": "^7.2.0", + "autoprefixer": "10.4.21", "clsx": "^2.1.1", - "framer-motion": "^11.3.8", + "framer-motion": "^12.5.0", "lodash": "^4.17.21", - "maplibre-gl": "^4.5.0", + "maplibre-gl": "^5.2.0", "multi-range-slider-react": "^2.0.7", "next": "^14.2.5", - "pmtiles": "^3.0.6", - "postcss": "8.4.39", + "pmtiles": "^4.3.0", + "postcss": "8.5.3", "protobufjs": "^7.3.2", "react": "18.3.1", "react-dom": "18.3.1", - "react-icons": "^5.2.1", - "react-map-gl": "^7.1.7", + "react-icons": "^5.5.0", + "react-map-gl": "^8.0.1", "sharp": "^0.33.4", "tailwindcss": "^3.4.6", - "typescript": "5.5.3" + "typescript": "5.8.2" }, "devDependencies": { "@semantic-release/changelog": "^6.0.3", - "@semantic-release/commit-analyzer": "^13.0.0", + "@semantic-release/commit-analyzer": "^13.0.1", "@semantic-release/git": "^10.0.1", - "@semantic-release/github": "^10.1.1", + "@semantic-release/github": "^11.0.1", "@semantic-release/npm": "^12.0.1", - "@semantic-release/release-notes-generator": "^14.0.1", - "@types/node": "^20.14.11", + "@semantic-release/release-notes-generator": "^14.0.3", + "@types/node": "^22.13.11", "@types/pbf": "^3.0.5", - "@types/pg": "^8.11.6", + "@types/pg": "^8.11.11", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.16.1", - "@typescript-eslint/parser": "^7.16.1", - "eslint": "^8.56.0", - "eslint-config-next": "^14.2.5", - "eslint-config-prettier": "^9.1.0", + "@typescript-eslint/eslint-plugin": "^8.27.0", + "@typescript-eslint/parser": "^8.27.0", + "eslint": "^9.22.0", + "eslint-config-next": "^15.2.3", + "eslint-config-prettier": "^10.1.1", "eslint-plugin-custom-rules": "file:./eslint-plugin-custom-rules", - "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-prettier": "^5.2.3", "eslint-plugin-react": "^7.34.4", - "postcss-nesting": "^12.1.5", - "postcss-preset-env": "^9.6.0", + "postcss-nesting": "^13.0.1", + "postcss-preset-env": "^10.1.5", "semantic-release": "^24.0.0" }, "overrides": { diff --git a/src/app/find-properties/[[...opa_id]]/page.tsx b/src/app/find-properties/[[...opa_id]]/page.tsx index c7a1f809..3449962a 100644 --- a/src/app/find-properties/[[...opa_id]]/page.tsx +++ b/src/app/find-properties/[[...opa_id]]/page.tsx @@ -16,7 +16,7 @@ import { centroid } from '@turf/centroid'; import { Position } from 'geojson'; import { ThemeButton } from '../../../components/ThemeButton'; import { useRouter } from 'next/navigation'; -import { ViewState } from 'react-map-gl'; +import { ViewState } from 'react-map-gl/maplibre'; import { PiX } from 'react-icons/pi'; import DataDisclaimerModal from '@/components/DataDisclaimerModal'; diff --git a/src/components/Filters/MultiSelect.tsx b/src/components/Filters/MultiSelect.tsx index 34eca2c0..2aa9dde2 100644 --- a/src/components/Filters/MultiSelect.tsx +++ b/src/components/Filters/MultiSelect.tsx @@ -32,7 +32,9 @@ const MultiSelect: FC = ({ // Override Autocomplete design to continue focus on the input after closing the popover menu useEffect(() => { - !isOpen && inputRef.current?.blur(); + if (!isOpen) { + inputRef.current?.blur(); + } }, [isOpen]); return ( diff --git a/src/components/InfoGraphicSection.tsx b/src/components/InfoGraphicSection.tsx index 57d02f76..cf02ca5b 100644 --- a/src/components/InfoGraphicSection.tsx +++ b/src/components/InfoGraphicSection.tsx @@ -2,6 +2,7 @@ import Image, { StaticImageData } from 'next/image'; import type { IconType } from 'react-icons'; import { ThemeButtonLink } from './ThemeButton'; import './components-css/InfoGraphicSection.css'; +import { JSX } from 'react'; interface InfoGraphicBase { id?: string; diff --git a/src/components/MapLegendControl/MapLegend.tsx b/src/components/MapLegendControl/MapLegend.tsx index 816bdcd5..b77c57a7 100644 --- a/src/components/MapLegendControl/MapLegend.tsx +++ b/src/components/MapLegendControl/MapLegend.tsx @@ -1,7 +1,8 @@ import React, { ReactElement, Dispatch, SetStateAction } from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import { FillLayerSpecification } from 'maplibre-gl'; -import { IControl, MapboxMap } from 'react-map-gl'; +import { Map as MaplibreMap } from 'maplibre-gl'; +import { IControl } from 'react-map-gl/maplibre'; import '../../app/mapLegend.css'; @@ -99,7 +100,7 @@ function MapLegend(layerStyle: FillLayerSpecification) { } export class MapLegendControlClass implements IControl { - private _map: MapboxMap | undefined; + private _map: MaplibreMap | undefined; private _container: HTMLElement; private handler: () => void; @@ -117,7 +118,7 @@ export class MapLegendControlClass implements IControl { } // able to add event listeners here for interactivity with layer - onAdd = (map: MapboxMap) => { + onAdd = (map: MaplibreMap) => { this._map = map; this._container.addEventListener('click', this.handler); return this._container; diff --git a/src/components/MapLegendControl/MapLegendControl.tsx b/src/components/MapLegendControl/MapLegendControl.tsx index 253621a0..85b24254 100644 --- a/src/components/MapLegendControl/MapLegendControl.tsx +++ b/src/components/MapLegendControl/MapLegendControl.tsx @@ -1,6 +1,6 @@ import { ControlPosition, FillLayerSpecification } from 'maplibre-gl'; import { Dispatch, SetStateAction } from 'react'; -import { useControl } from 'react-map-gl'; +import { useControl } from 'react-map-gl/maplibre'; import { MapLegendControlClass } from './MapLegend'; interface LegendOptions { diff --git a/src/components/PropertyAccessOptionContainer.tsx b/src/components/PropertyAccessOptionContainer.tsx index 0d5ff3b5..7ebb2b0d 100644 --- a/src/components/PropertyAccessOptionContainer.tsx +++ b/src/components/PropertyAccessOptionContainer.tsx @@ -27,21 +27,29 @@ const determineCardEnums = (property: any) => { unavailable.add(PropertyAccess.PRIVATE_LAND_USE); } - property.access_process === 'Go through Land Bank' - ? (best = PropertyAccess.LAND_BANK) - : unavailable.add(PropertyAccess.LAND_BANK); + if (property.access_process === 'Go through Land Bank') { + best = PropertyAccess.LAND_BANK; + } else { + unavailable.add(PropertyAccess.LAND_BANK); + } - property.side_yard_eligible === 'Yes' - ? (neighbor = PropertyAccess.SIDE_YARD) - : unavailable.add(PropertyAccess.SIDE_YARD); + if (property.side_yard_eligible === 'Yes') { + neighbor = PropertyAccess.SIDE_YARD; + } else { + unavailable.add(PropertyAccess.SIDE_YARD); + } - property.tactical_urbanism === 'Yes' - ? available.add(PropertyAccess.TACTICAL_URBANISM) - : unavailable.add(PropertyAccess.TACTICAL_URBANISM); + if (property.tactical_urbanism === 'Yes') { + available.add(PropertyAccess.TACTICAL_URBANISM); + } else { + unavailable.add(PropertyAccess.TACTICAL_URBANISM); + } - property.conservatorship === 'Yes' - ? available.add(PropertyAccess.CONSERVATORSHIP) - : unavailable.add(PropertyAccess.CONSERVATORSHIP); + if (property.conservatorship === 'Yes') { + available.add(PropertyAccess.CONSERVATORSHIP); + } else { + unavailable.add(PropertyAccess.CONSERVATORSHIP); + } return { best, diff --git a/src/components/PropertyMap.tsx b/src/components/PropertyMap.tsx index 45699807..9e328637 100644 --- a/src/components/PropertyMap.tsx +++ b/src/components/PropertyMap.tsx @@ -24,6 +24,7 @@ import Map, { GeolocateControl, ViewState, } from 'react-map-gl/maplibre'; +import { Feature } from 'maplibre-gl'; import maplibregl, { Map as MaplibreMap, IControl, @@ -498,7 +499,7 @@ const PropertyMap: FC = ({ coordinates: [-75.1652, 39.9526], // Approximate center of Philadelphia }, ]} - onPick={(feature) => { + onPick={({ feature }) => { if (feature) { const address = feature.place_name.split(',')[0]; setSelectedProperty(null); diff --git a/src/components/SinglePropertyDetail.tsx b/src/components/SinglePropertyDetail.tsx index 0f168fc5..f601bc2c 100644 --- a/src/components/SinglePropertyDetail.tsx +++ b/src/components/SinglePropertyDetail.tsx @@ -76,9 +76,11 @@ const SinglePropertyDetail = ({ : {}; const propertyId = parsedLocalStorageData.opa_ids[opa_id]; - propertyId - ? setIsPropertySavedToLocalStorage(true) - : setIsPropertySavedToLocalStorage(false); + if (propertyId) { + setIsPropertySavedToLocalStorage(true); + } else { + setIsPropertySavedToLocalStorage(false); + } }, []); if (!property) return null; diff --git a/src/config/config.ts b/src/config/config.ts index 6002630e..877bbe1a 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -1,8 +1,7 @@ const EMPTY_STRING = ''; export const mapboxAccessToken = - 'pk.eyJ1IjoibmxlYm92aXRzIiwiYSI6ImNsZXQ2Nzd3ZDBjZnYzcHFvYXhib2RqYzQifQ.PWg2LuNCH1E6-REjmYvdOg' || - EMPTY_STRING; + 'pk.eyJ1IjoibmxlYm92aXRzIiwiYSI6ImNsZXQ2Nzd3ZDBjZnYzcHFvYXhib2RqYzQifQ.PWg2LuNCH1E6-REjmYvdOg'; export const maptilerApiKey = process.env.NEXT_PUBLIC_MAPTILER_KEY || EMPTY_STRING; From 5fab8cf222f75c6fc516571dffa8705254933a3a Mon Sep 17 00:00:00 2001 From: Adam Levin Date: Mon, 24 Mar 2025 11:50:16 -0400 Subject: [PATCH 5/7] chore: add missing imports to new ETL pipeline --- data/src/main.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/data/src/main.py b/data/src/main.py index bc97fa43..096d85cc 100644 --- a/data/src/main.py +++ b/data/src/main.py @@ -2,6 +2,8 @@ import traceback import pandas as pd + +from config.config import tiles_file_id_prefix from config.psql import conn from new_etl.classes.data_diff import DiffReport from new_etl.classes.slack_reporters import ( @@ -10,6 +12,7 @@ send_pg_stats_to_slack, ) from new_etl.data_utils import ( + access_process, city_owned_properties, community_gardens, conservatorship, @@ -24,10 +27,12 @@ li_violations, nbhoods, negligent_devs, + opa_properties, owner_type, park_priority, phs_properties, ppr_properties, + priority_level, pwd_parcels, rco_geoms, tactical_urbanism, @@ -35,8 +40,7 @@ unsafe_buildings, vacant_properties, ) - -from config.config import tiles_file_id_prefix +from new_etl.database import to_postgis_with_schema # Ensure the directory containing awkde is in the Python path awkde_path = "/usr/src/app" From 2f1122ba9fbd1073c8bef69e6c396291ac2a9728 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 25 Mar 2025 14:58:00 +0000 Subject: [PATCH 6/7] chore(release): 1.0.0 [skip ci] # 1.0.0 (2025-03-25) ### Bug Fixes * **572:** fix webpack warnings + fix linting issues ([#574](https://github.com/adamzev/clean-and-green-philly/issues/574)) ([fbfd459](https://github.com/adamzev/clean-and-green-philly/commit/fbfd459ba147e51a2fd54bee61d5ca63fb74eb98)) * Add focus styling to header links ([a99065c](https://github.com/adamzev/clean-and-green-philly/commit/a99065cba1607b981702e7aa7e654f24c108ad6e)) * Add href to dropdown items to increase link size ([2eb4667](https://github.com/adamzev/clean-and-green-philly/commit/2eb4667e7b68f45489c51ea10aa7d15afd2a3c77)) * closing tooltip popup on map closes property details ([432e8c0](https://github.com/adamzev/clean-and-green-philly/commit/432e8c0a14e1e9cfa199b030019c0730a24741c6)) * correct the scrolling on the map page ([a850237](https://github.com/adamzev/clean-and-green-philly/commit/a8502372e243057e2b06559cb042d94ea894415a)) * Remove nested link and button ([d93e8bd](https://github.com/adamzev/clean-and-green-philly/commit/d93e8bd52d80cd8d5b1a30910aaa4b168a11b57a)) * Update footer markup structure for accessibility ([d5c2a33](https://github.com/adamzev/clean-and-green-philly/commit/d5c2a334f0e5c297f117dca5dc2972b56d7b3542)) ### Features * **247:** make the mapbox legend more legible ([bcf6915](https://github.com/adamzev/clean-and-green-philly/commit/bcf691566fc26e834547a43efd863de58abdf3d4)) * **293:** sort features by priority of high, medium, low ([8cd1058](https://github.com/adamzev/clean-and-green-philly/commit/8cd105872feb0065aa3d207d42dc5df76ef63dbc)) * **305:** expand the header width of single property table ([b25261e](https://github.com/adamzev/clean-and-green-philly/commit/b25261e5d9e26bdbd9694aa03b4964771528dd3b)) * **395:** add white background to backbutton bar ([a65f052](https://github.com/adamzev/clean-and-green-philly/commit/a65f052ca2e5c0eac2737f85b4997af6e993f750)) * **395:** make property selection back button sticky ([6601201](https://github.com/adamzev/clean-and-green-philly/commit/6601201fcf943f8e64a1341327095e9b7edc6b08)) * **457:** add filter count to button ([b35145a](https://github.com/adamzev/clean-and-green-philly/commit/b35145a1df5f2995294f829e0b7cde20ba0e0f29)) * **535:** add close download view button ([#579](https://github.com/adamzev/clean-and-green-philly/issues/579)) ([9bd2c53](https://github.com/adamzev/clean-and-green-philly/commit/9bd2c53aa3b49da8136fa6e7e850c4dc4d5e2d74)) * **544:** adjust remove property section ([#580](https://github.com/adamzev/clean-and-green-philly/issues/580)) ([900af8e](https://github.com/adamzev/clean-and-green-philly/commit/900af8e6fbfc89bd4ed83b17c9eed0a1d5a3de3b)) * **568:** restyle the property table ([#577](https://github.com/adamzev/clean-and-green-philly/issues/577)) ([2c8cc92](https://github.com/adamzev/clean-and-green-philly/commit/2c8cc92b7f28aecdbe65412476691baa50254292)) * Add arrow icon to link ([6bce3fa](https://github.com/adamzev/clean-and-green-philly/commit/6bce3fa84ad9827f2117a2d51ed2f2665e83481b)) * Add content to sidebar ([23d5c52](https://github.com/adamzev/clean-and-green-philly/commit/23d5c52c3fcd1eb1eff902e7d1fd37ab2fe41b6d)) * Add council district ([e576218](https://github.com/adamzev/clean-and-green-philly/commit/e5762185840f0bbc2289fede8481f5b39a16087d)) * Add extra data to single detail page ([48e34fe](https://github.com/adamzev/clean-and-green-philly/commit/48e34fe0a6317fc8fc0f1f5e745dd165000d437f)) * Add font ([c1a8b93](https://github.com/adamzev/clean-and-green-philly/commit/c1a8b93561dfc67c8eed31b3c8befa2b8ae984ec)) * Add font to map ([1491518](https://github.com/adamzev/clean-and-green-philly/commit/14915180857a482a25d96f9f45f7c838082e2d71)) * Add font to search field ([3b08069](https://github.com/adamzev/clean-and-green-philly/commit/3b080690ba92007545467bc2ce4bf3bcad26c899)) * Add info cards ([8170944](https://github.com/adamzev/clean-and-green-philly/commit/8170944fdb8d8be36af062012967323047bda748)) * Add missing data and atlas link; style table ([8c260d4](https://github.com/adamzev/clean-and-green-philly/commit/8c260d48e015ed6c8c29cc10b8936753cc013ff0)) * Add percentage, update column widths ([41caf77](https://github.com/adamzev/clean-and-green-philly/commit/41caf77c55eb0a6336abc80047ed83584d250a64)) * Add priority color square ([ad5a9fa](https://github.com/adamzev/clean-and-green-philly/commit/ad5a9faff3b9596256e680b3d6d95c54caefc7a7)) * add redirect from map to find-properties ([439ed6c](https://github.com/adamzev/clean-and-green-philly/commit/439ed6c7291251aed9751431cd5bdc2fa6883a15)) * Add row scope ([f945979](https://github.com/adamzev/clean-and-green-philly/commit/f945979edaee2ad5a003a5b5560a89cc25717f3b)) * Add spacing below Back button ([7de48c5](https://github.com/adamzev/clean-and-green-philly/commit/7de48c50f177c0275cebac0a4a7d9dfce8d2cd2c)) * Address a few more links ([b3b6733](https://github.com/adamzev/clean-and-green-philly/commit/b3b673375f1472f15d80bffeff378c973d6cb49d)) * Adjust table per requirements ([36e6cfa](https://github.com/adamzev/clean-and-green-philly/commit/36e6cfa5934defadcf1a8b8ad1c09ffe609d0ec5)) * Change Find Properties and Learn More to links ([1de0b47](https://github.com/adamzev/clean-and-green-philly/commit/1de0b474811ab2d4281d94c6a9d5882a8ebb0c13)) * Close sidebar if clicking on empty map ([612117d](https://github.com/adamzev/clean-and-green-philly/commit/612117d6c54bc62baaae4f773013e196232c2dba)) * Navigate to map on click; show popups ([183b6a2](https://github.com/adamzev/clean-and-green-philly/commit/183b6a224d651726a6e465d7c9549ef437626f9e)) * Open sidebar from map ([5474367](https://github.com/adamzev/clean-and-green-philly/commit/54743673e99ffd6b939009ad54e4d0a4252ba044)) * Pass selected property to map view ([663f142](https://github.com/adamzev/clean-and-green-philly/commit/663f14236ccb9246efa8882c0dfa44e8cbcba0f7)) * underline links ([5f23d09](https://github.com/adamzev/clean-and-green-philly/commit/5f23d09da9a7258b284ccfef54b1be0ee2a8e1f8)) * Update aria label and role ([765e5a4](https://github.com/adamzev/clean-and-green-philly/commit/765e5a4fef1941e93815ae4789093e047183101c)) --- CHANGELOG.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..b4fe9d8c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,48 @@ +# 1.0.0 (2025-03-25) + + +### Bug Fixes + +* **572:** fix webpack warnings + fix linting issues ([#574](https://github.com/adamzev/clean-and-green-philly/issues/574)) ([fbfd459](https://github.com/adamzev/clean-and-green-philly/commit/fbfd459ba147e51a2fd54bee61d5ca63fb74eb98)) +* Add focus styling to header links ([a99065c](https://github.com/adamzev/clean-and-green-philly/commit/a99065cba1607b981702e7aa7e654f24c108ad6e)) +* Add href to dropdown items to increase link size ([2eb4667](https://github.com/adamzev/clean-and-green-philly/commit/2eb4667e7b68f45489c51ea10aa7d15afd2a3c77)) +* closing tooltip popup on map closes property details ([432e8c0](https://github.com/adamzev/clean-and-green-philly/commit/432e8c0a14e1e9cfa199b030019c0730a24741c6)) +* correct the scrolling on the map page ([a850237](https://github.com/adamzev/clean-and-green-philly/commit/a8502372e243057e2b06559cb042d94ea894415a)) +* Remove nested link and button ([d93e8bd](https://github.com/adamzev/clean-and-green-philly/commit/d93e8bd52d80cd8d5b1a30910aaa4b168a11b57a)) +* Update footer markup structure for accessibility ([d5c2a33](https://github.com/adamzev/clean-and-green-philly/commit/d5c2a334f0e5c297f117dca5dc2972b56d7b3542)) + + +### Features + +* **247:** make the mapbox legend more legible ([bcf6915](https://github.com/adamzev/clean-and-green-philly/commit/bcf691566fc26e834547a43efd863de58abdf3d4)) +* **293:** sort features by priority of high, medium, low ([8cd1058](https://github.com/adamzev/clean-and-green-philly/commit/8cd105872feb0065aa3d207d42dc5df76ef63dbc)) +* **305:** expand the header width of single property table ([b25261e](https://github.com/adamzev/clean-and-green-philly/commit/b25261e5d9e26bdbd9694aa03b4964771528dd3b)) +* **395:** add white background to backbutton bar ([a65f052](https://github.com/adamzev/clean-and-green-philly/commit/a65f052ca2e5c0eac2737f85b4997af6e993f750)) +* **395:** make property selection back button sticky ([6601201](https://github.com/adamzev/clean-and-green-philly/commit/6601201fcf943f8e64a1341327095e9b7edc6b08)) +* **457:** add filter count to button ([b35145a](https://github.com/adamzev/clean-and-green-philly/commit/b35145a1df5f2995294f829e0b7cde20ba0e0f29)) +* **535:** add close download view button ([#579](https://github.com/adamzev/clean-and-green-philly/issues/579)) ([9bd2c53](https://github.com/adamzev/clean-and-green-philly/commit/9bd2c53aa3b49da8136fa6e7e850c4dc4d5e2d74)) +* **544:** adjust remove property section ([#580](https://github.com/adamzev/clean-and-green-philly/issues/580)) ([900af8e](https://github.com/adamzev/clean-and-green-philly/commit/900af8e6fbfc89bd4ed83b17c9eed0a1d5a3de3b)) +* **568:** restyle the property table ([#577](https://github.com/adamzev/clean-and-green-philly/issues/577)) ([2c8cc92](https://github.com/adamzev/clean-and-green-philly/commit/2c8cc92b7f28aecdbe65412476691baa50254292)) +* Add arrow icon to link ([6bce3fa](https://github.com/adamzev/clean-and-green-philly/commit/6bce3fa84ad9827f2117a2d51ed2f2665e83481b)) +* Add content to sidebar ([23d5c52](https://github.com/adamzev/clean-and-green-philly/commit/23d5c52c3fcd1eb1eff902e7d1fd37ab2fe41b6d)) +* Add council district ([e576218](https://github.com/adamzev/clean-and-green-philly/commit/e5762185840f0bbc2289fede8481f5b39a16087d)) +* Add extra data to single detail page ([48e34fe](https://github.com/adamzev/clean-and-green-philly/commit/48e34fe0a6317fc8fc0f1f5e745dd165000d437f)) +* Add font ([c1a8b93](https://github.com/adamzev/clean-and-green-philly/commit/c1a8b93561dfc67c8eed31b3c8befa2b8ae984ec)) +* Add font to map ([1491518](https://github.com/adamzev/clean-and-green-philly/commit/14915180857a482a25d96f9f45f7c838082e2d71)) +* Add font to search field ([3b08069](https://github.com/adamzev/clean-and-green-philly/commit/3b080690ba92007545467bc2ce4bf3bcad26c899)) +* Add info cards ([8170944](https://github.com/adamzev/clean-and-green-philly/commit/8170944fdb8d8be36af062012967323047bda748)) +* Add missing data and atlas link; style table ([8c260d4](https://github.com/adamzev/clean-and-green-philly/commit/8c260d48e015ed6c8c29cc10b8936753cc013ff0)) +* Add percentage, update column widths ([41caf77](https://github.com/adamzev/clean-and-green-philly/commit/41caf77c55eb0a6336abc80047ed83584d250a64)) +* Add priority color square ([ad5a9fa](https://github.com/adamzev/clean-and-green-philly/commit/ad5a9faff3b9596256e680b3d6d95c54caefc7a7)) +* add redirect from map to find-properties ([439ed6c](https://github.com/adamzev/clean-and-green-philly/commit/439ed6c7291251aed9751431cd5bdc2fa6883a15)) +* Add row scope ([f945979](https://github.com/adamzev/clean-and-green-philly/commit/f945979edaee2ad5a003a5b5560a89cc25717f3b)) +* Add spacing below Back button ([7de48c5](https://github.com/adamzev/clean-and-green-philly/commit/7de48c50f177c0275cebac0a4a7d9dfce8d2cd2c)) +* Address a few more links ([b3b6733](https://github.com/adamzev/clean-and-green-philly/commit/b3b673375f1472f15d80bffeff378c973d6cb49d)) +* Adjust table per requirements ([36e6cfa](https://github.com/adamzev/clean-and-green-philly/commit/36e6cfa5934defadcf1a8b8ad1c09ffe609d0ec5)) +* Change Find Properties and Learn More to links ([1de0b47](https://github.com/adamzev/clean-and-green-philly/commit/1de0b474811ab2d4281d94c6a9d5882a8ebb0c13)) +* Close sidebar if clicking on empty map ([612117d](https://github.com/adamzev/clean-and-green-philly/commit/612117d6c54bc62baaae4f773013e196232c2dba)) +* Navigate to map on click; show popups ([183b6a2](https://github.com/adamzev/clean-and-green-philly/commit/183b6a224d651726a6e465d7c9549ef437626f9e)) +* Open sidebar from map ([5474367](https://github.com/adamzev/clean-and-green-philly/commit/54743673e99ffd6b939009ad54e4d0a4252ba044)) +* Pass selected property to map view ([663f142](https://github.com/adamzev/clean-and-green-philly/commit/663f14236ccb9246efa8882c0dfa44e8cbcba0f7)) +* underline links ([5f23d09](https://github.com/adamzev/clean-and-green-philly/commit/5f23d09da9a7258b284ccfef54b1be0ee2a8e1f8)) +* Update aria label and role ([765e5a4](https://github.com/adamzev/clean-and-green-philly/commit/765e5a4fef1941e93815ae4789093e047183101c)) From 7e642f4191bb6ab613671ac6263460c76afeb1f8 Mon Sep 17 00:00:00 2001 From: Adam Levin Date: Tue, 25 Mar 2025 17:50:37 -0400 Subject: [PATCH 7/7] fix: removed old ETL pipeline Removed references in docker-compose Updated Dockerfile to run main.py Updated tests to use the new ETL pipeline Removed tests and created a ticket to add them back in that could not be directly switched --- .gitignore | 2 + data/Dockerfile | 2 +- data/Dockerfile-pg | 26 -- data/docker-compose.yml | 20 - data/src/classes/__init__.py | 0 data/src/classes/backup_archive_database.py | 132 ------ data/src/classes/diff_report.py | 225 ---------- data/src/classes/featurelayer.py | 409 ------------------- data/src/classes/slack_error_reporter.py | 16 - data/src/config/config.py | 1 - data/src/constants/__init__.py | 0 data/src/constants/services.py | 78 ---- data/src/data_utils/__init__.py | 27 -- data/src/data_utils/access_process.py | 43 -- data/src/data_utils/city_owned_properties.py | 81 ---- data/src/data_utils/community_gardens.py | 28 -- data/src/data_utils/conservatorship.py | 59 --- data/src/data_utils/contig_neighbors.py | 27 -- data/src/data_utils/deliquencies.py | 31 -- data/src/data_utils/dev_probability.py | 59 --- data/src/data_utils/drug_crimes.py | 10 - data/src/data_utils/gun_crimes.py | 8 - data/src/data_utils/imm_dang_buildings.py | 28 -- data/src/data_utils/kde.py | 159 ------- data/src/data_utils/l_and_i.py | 178 -------- data/src/data_utils/nbhoods.py | 25 -- data/src/data_utils/negligent_devs.py | 166 -------- data/src/data_utils/opa_properties.py | 29 -- data/src/data_utils/owner_type.py | 37 -- data/src/data_utils/park_priority.py | 135 ------ data/src/data_utils/phs_properties.py | 33 -- data/src/data_utils/ppr_properties.py | 53 --- data/src/data_utils/priority_level.py | 51 --- data/src/data_utils/rco_geoms.py | 57 --- data/src/data_utils/tactical_urbanism.py | 25 -- data/src/data_utils/tree_canopy.py | 32 -- data/src/data_utils/unsafe_buildings.py | 28 -- data/src/data_utils/utils.py | 42 -- data/src/data_utils/vacant_properties.py | 186 --------- data/src/script.py | 147 ------- data/src/test/conftest.py | 4 +- data/src/test/test_data_utils.py | 24 +- data/src/test/test_diff_backup.py | 114 ------ data/src/test/test_slack_error_reporter.py | 14 +- data/src/test/test_utils.py | 2 +- 45 files changed, 20 insertions(+), 2833 deletions(-) delete mode 100644 data/Dockerfile-pg delete mode 100644 data/src/classes/__init__.py delete mode 100644 data/src/classes/backup_archive_database.py delete mode 100644 data/src/classes/diff_report.py delete mode 100644 data/src/classes/featurelayer.py delete mode 100644 data/src/classes/slack_error_reporter.py delete mode 100644 data/src/constants/__init__.py delete mode 100644 data/src/constants/services.py delete mode 100644 data/src/data_utils/__init__.py delete mode 100644 data/src/data_utils/access_process.py delete mode 100644 data/src/data_utils/city_owned_properties.py delete mode 100644 data/src/data_utils/community_gardens.py delete mode 100644 data/src/data_utils/conservatorship.py delete mode 100644 data/src/data_utils/contig_neighbors.py delete mode 100644 data/src/data_utils/deliquencies.py delete mode 100644 data/src/data_utils/dev_probability.py delete mode 100644 data/src/data_utils/drug_crimes.py delete mode 100644 data/src/data_utils/gun_crimes.py delete mode 100644 data/src/data_utils/imm_dang_buildings.py delete mode 100644 data/src/data_utils/kde.py delete mode 100644 data/src/data_utils/l_and_i.py delete mode 100644 data/src/data_utils/nbhoods.py delete mode 100644 data/src/data_utils/negligent_devs.py delete mode 100644 data/src/data_utils/opa_properties.py delete mode 100644 data/src/data_utils/owner_type.py delete mode 100644 data/src/data_utils/park_priority.py delete mode 100644 data/src/data_utils/phs_properties.py delete mode 100644 data/src/data_utils/ppr_properties.py delete mode 100644 data/src/data_utils/priority_level.py delete mode 100644 data/src/data_utils/rco_geoms.py delete mode 100644 data/src/data_utils/tactical_urbanism.py delete mode 100644 data/src/data_utils/tree_canopy.py delete mode 100644 data/src/data_utils/unsafe_buildings.py delete mode 100644 data/src/data_utils/utils.py delete mode 100644 data/src/data_utils/vacant_properties.py delete mode 100644 data/src/script.py delete mode 100644 data/src/test/test_diff_backup.py diff --git a/.gitignore b/.gitignore index a4fe2518..618c28c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ ## Env files .env data.env +.envrc ## Data /notebooks/.ipynb_checkpoints/ @@ -32,6 +33,7 @@ data/src/tmp .DS_Store *.pem .vscode +.python-version # debug npm-debug.log* diff --git a/data/Dockerfile b/data/Dockerfile index d5cf8d40..381a4da0 100644 --- a/data/Dockerfile +++ b/data/Dockerfile @@ -57,4 +57,4 @@ WORKDIR /usr/src/app # Use Pipenv to run the script # Adjust the path to your main Python script if needed -CMD ["pipenv", "run", "python", "./script.py"] +CMD ["pipenv", "run", "python", "./main.py"] diff --git a/data/Dockerfile-pg b/data/Dockerfile-pg deleted file mode 100644 index d4d62d77..00000000 --- a/data/Dockerfile-pg +++ /dev/null @@ -1,26 +0,0 @@ -# -# NOTE: THIS DOCKERFILE IS GENERATED VIA "make update"! PLEASE DO NOT EDIT IT DIRECTLY. -# - -FROM postgres:16-bullseye - -LABEL maintainer="PostGIS Project - https://postgis.net" \ - org.opencontainers.image.description="PostGIS 3.4.3+dfsg-2.pgdg110+1 spatial database extension with PostgreSQL 16 bullseye" \ - org.opencontainers.image.source="https://github.com/postgis/docker-postgis" - -ENV POSTGIS_MAJOR 3 -ENV POSTGIS_VERSION 3.4.3+dfsg-2.pgdg110+1 - -RUN apt-get update \ - && apt-cache showpkg postgresql-$PG_MAJOR-postgis-$POSTGIS_MAJOR \ - && apt-get install -y --no-install-recommends \ - # ca-certificates: for accessing remote raster files; - # fix: https://github.com/postgis/docker-postgis/issues/307 - ca-certificates \ - \ - postgresql-$PG_MAJOR-postgis-$POSTGIS_MAJOR=$POSTGIS_VERSION \ - postgresql-$PG_MAJOR-postgis-$POSTGIS_MAJOR-scripts \ - && rm -rf /var/lib/apt/lists/* - -RUN mkdir -p /docker-entrypoint-initdb.d - diff --git a/data/docker-compose.yml b/data/docker-compose.yml index 5737d39a..11c169e9 100644 --- a/data/docker-compose.yml +++ b/data/docker-compose.yml @@ -55,25 +55,6 @@ services: - host.docker.internal:host-gateway network_mode: 'host' - postgres: - container_name: cagp-postgres - build: - context: . - dockerfile: Dockerfile-pg - environment: - PGPORT: 5433 - POSTGRES_PASSWORD: - restart: always - ports: - - '5433:5433' - volumes: - - database_volume:/var/lib/postgresql/data - - ./init_pg.sql:/docker-entrypoint-initdb.d/init_pg.sql - - /etc/timezone:/etc/timezone:ro - - /etc/localtime:/etc/localtime:ro - extra_hosts: - - host.docker.internal:host-gateway - postgres-timescale: container_name: cagp-postgres-timescale build: @@ -93,5 +74,4 @@ services: extra_hosts: - host.docker.internal:host-gateway volumes: - database_volume: timescale_database_volume: diff --git a/data/src/classes/__init__.py b/data/src/classes/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/data/src/classes/backup_archive_database.py b/data/src/classes/backup_archive_database.py deleted file mode 100644 index 60f5ef4f..00000000 --- a/data/src/classes/backup_archive_database.py +++ /dev/null @@ -1,132 +0,0 @@ -import logging as log -import os -import subprocess -from datetime import datetime, timedelta - -import sqlalchemy as sa -from config.config import log_level, max_backup_schema_days, tiles_file_id_prefix, tile_file_backup_directory -from config.psql import conn, local_engine, url -from data_utils.utils import mask_password -from sqlalchemy import inspect -from classes.featurelayer import google_cloud_bucket - -log.basicConfig(level=log_level) - -backup_schema_name: str = "backup_" -""" the prefix for the backup schemas """ - -date_time_format: str = "%Y_%m_%dt%H_%M_%S" -""" the datetime format for the backup schema names """ - - -class BackupArchiveDatabase: - """ - Class to manage creating a backup of the public schema before the etl refresh is run. After the etl job and data differences are reported, this class moves the current backup schema to a timestamped backup and prunes older backup schemas. - """ - - def __init__(self): - self.timestamp_string = datetime.now().strftime(date_time_format) - self.backup_schema_archive_name = backup_schema_name + self.timestamp_string - - def backup_schema(self): - """ - backup the whole public schema to another schema in the same db. - pgdump the public schema, replace public schema name with backup schema name, clean up the special column types, and import it with psql in one piped command - """ - - pgdump_command = ( - # first, dump the schema only where we can safely replace all 'public' strings with 'backup_' - "pg_dump " - + url - + " -s --schema public | " - + " sed 's/public/" + backup_schema_name + "/g'" - + " | sed 's/" - + backup_schema_name - + ".geometry/public.geometry/' | sed 's/" - + backup_schema_name - + ".spatial_ref_sys/public.spatial_ref_sys/'" - + " | sed 's/backup__/public_/g'" # ppr_properties.public_name column needs to be restored. - + " | psql -v ON_ERROR_STOP=1 " - + url - + " > /dev/null " - # then dump the data only and substitute the word public only where it is in DDL, not in the data - + " && pg_dump " - + url - + " -a --schema public | sed 's/COPY public./COPY " - + backup_schema_name - + "./g' | sed 's/" - + backup_schema_name - + ".geometry/public.geometry/' | sed 's/" - + backup_schema_name - + ".spatial_ref_sys/public.spatial_ref_sys/' | psql -v ON_ERROR_STOP=1 " - + url - ) - log.debug(mask_password(pgdump_command)) - complete_process = subprocess.run( - pgdump_command, - check=False, - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - ) - - if complete_process.returncode != 0 or complete_process.stderr: - raise RuntimeError( - "pg_dump command " - + mask_password(pgdump_command) - + " did not exit with success. " - + complete_process.stderr - ) - - def archive_backup_schema(self): - """ - mv backup_ schema to "backup_" + backup_timestamp - """ - sql = ( - "ALTER SCHEMA " - + backup_schema_name - + " RENAME TO " - + self.backup_schema_archive_name - ) - log.debug(sql) - conn.execute(sa.DDL(sql)) - - def prune_old_archives(self): - """ - drop backup schemas that are too old - """ - # list all backup schemas - schemas = inspect(local_engine).get_schema_names() - cutoff = datetime.now() - timedelta(days=max_backup_schema_days) - for schema in schemas: - if schema.startswith(backup_schema_name): - timestamp = schema.replace(backup_schema_name, "") - backed_up_time = datetime.strptime(timestamp, date_time_format) - if backed_up_time < cutoff: - sql = "drop schema " + schema + " cascade" - log.debug(sql) - conn.execute(sa.DDL(sql)) - - def is_backup_schema_exists(self) -> bool: - """ whether the backup schema exists - - Returns: - bool: whether true - """ - return backup_schema_name in inspect(local_engine).get_schema_names() - - def backup_tiles_file(self): - """backup the main tiles file to a timestamped copy in the backup/ folder in GCP - """ - bucket = google_cloud_bucket() - count: int = 0 - for blob in bucket.list_blobs(prefix=tiles_file_id_prefix): - suffix: str = '_' + self.timestamp_string - name, ext = os.path.splitext(blob.name) - backup_file_name: str = tile_file_backup_directory + "/" + name + suffix + ext - log.debug(backup_file_name) - bucket.copy_blob(blob,destination_bucket=bucket,new_name=backup_file_name) - count += 1 - if count == 0: - log.warning("No files were found to back up.") diff --git a/data/src/classes/diff_report.py b/data/src/classes/diff_report.py deleted file mode 100644 index 2ac7395f..00000000 --- a/data/src/classes/diff_report.py +++ /dev/null @@ -1,225 +0,0 @@ -import logging as log -import os -import re -import smtplib -import subprocess -from email.mime.text import MIMEText - -from classes.backup_archive_database import backup_schema_name -from classes.featurelayer import google_cloud_bucket -from config.config import ( - from_email, - log_level, - report_to_email, - report_to_slack_channel, - smtp_server, -) -from config.psql import conn, url -from data_utils.utils import mask_password -from slack_sdk import WebClient - -log.basicConfig(level=log_level) - -class DiffTable: - """Metadata about a table to be run through data-diff - """ - def __init__(self, table: str, pk_cols: list[str], where: str = None): - """constructor - - Args: - table (str): the name of the table in postgres - pk_cols (list[str]): the list of columns in the primary key - where (str, optional): any additional where clause to limit the rows being compared - """ - self.table = table - self.pk_cols = pk_cols - self.where = where - -class DiffReport: - """ - Class to manage computing data differences for all tables between the newly imported schema and the last schema. Build a report of summary differences for all tables. Log detailed differences to a table in the old backed-up schema. Post difference summary to Slack and or email. - """ - - def __init__(self, timestamp_string: str = None): - """constructor - - Args: - timestamp_string (str, optional): This should be the same timestamp used in the backup to keep things consistent. We only use this as the folder name for the diff detail files in GCP. Defaults to None. - """ - self.diff_tables = self._list_diff_tables() - self.timestamp_string = timestamp_string - self.report: str = "The back-end data has been fully refreshed. Here is the difference report on " + str(len(self.diff_tables)) + " key tables.\nLegend: table A = new data, table B = old data.\n\n" - - def run(self): - """ - run the report and slack or email it. - """ - - for diff_table in self.diff_tables: - log.debug("Process table %s with pks %s", diff_table.table, str(diff_table.pk_cols)) - summary = diff_table.table + "\n" + self.compare_table(diff_table) - # if no differences, do not report. - if self._summary_shows_differences(summary): - self.report += summary - self.report += "Details: " + self.detail_report(diff_table.table) + "\n" - else: - self.report += diff_table.table + "\nNo difference\n" - self.report += "\n" - log.debug("\n") - log.debug(self.report) - self.send_report_to_slack() - self.email_report() - - def _summary_shows_differences(self, summary: str) -> bool: - """check the data-diff summary report to see if there are any differences - - Args: - summary (str): the summary output - - Returns: - bool: whether any add, deletes or updates were reported - """ - return not ( - "0 rows exclusive to table A" in summary - and "0 rows exclusive to table B" in summary - and "0 rows updated" in summary - ) - - def detail_report(self, table: str) -> str: - """Generate the html from the detail diff report and upload to Google cloud as an html file - Args: - table (str): the name of the core table being compared - - Returns: - str: the full url of the report - """ - return self._save_detail_report_to_cloud( - self.generate_table_detail_report(table), table - ) - - def _save_detail_report_to_cloud(self, html: str, table: str) -> str: - """Save this html to a public cloud folder in Google named with the timestamp of the backup - - Args: - html (str): the html content - table (str): the name of the core table being compared - - Returns: - str: the full url of the report - """ - path: str = "diff/" + self.timestamp_string + "/" + table + ".html" - bucket = google_cloud_bucket() - blob = bucket.blob(path) - blob.upload_from_string(html, content_type="text/html") - return "https://storage.googleapis.com/" + bucket.name + "/" + path - - def generate_table_detail_report(self, table: str) -> str: - """ - generate an html table of the details of differences in this table from the materialized diff table in the backup schema from data-diff - """ - sql: str = "select * from " + backup_schema_name + "." + table + "_diff" - cur = conn.connection.cursor() - cur.execute(sql) - html: str = "" - - column_names = [desc[0] for desc in cur.description] - for column in column_names: - html += "" - html += "" - for row in cur.fetchall(): - html += "" - for value in row: - html += "" - html += "" - html += "
" + column + "
" + str(value) + "
" - return html - - def _list_diff_tables(self) -> list[DiffTable]: - """ - list table metadata to do the diff on - Returns: - list[DiffTable]: the list of metadata - """ - return [ - DiffTable(table="vacant_properties",pk_cols=["opa_id", "parcel_type"],where="opa_id is not null"), - DiffTable(table="li_complaints",pk_cols=["service_request_id"]), - DiffTable(table="li_violations",pk_cols=["violationnumber", "opa_account_num"],where="opa_account_num is not null"), - DiffTable(table="opa_properties",pk_cols=["parcel_number"]), - DiffTable(table="property_tax_delinquencies",pk_cols=["opa_number"],where="opa_number <> 0") - ] - - def compare_table(self, diff_table: DiffTable) -> str: - """ - run data-diff to compare the newly imported table in the public schema to the table in the backup schema. - We could use the data-diff python API but the cl is much clearer and has features I could not find in the API. - """ - table = diff_table.table - pks = diff_table.pk_cols - - # compare the tables and output the summary stats to include in the report. Materialize the details - # of the differences to a table in the backup schema named table_name_diff - data_diff_command = ( - "data-diff " - + url - + " public." - + table - + " " - + backup_schema_name - + "." - + table - + " -k " - + " -k ".join(pks) - + " -c '%' -m " - + backup_schema_name - + "." - + table - + "_diff --stats" - + " --table-write-limit 100000" - + (" -w '" + diff_table.where + "'" if diff_table.where else "") - ) - log.debug(mask_password(data_diff_command)) - - complete_process = subprocess.run( - data_diff_command, check=False, shell=True, capture_output=True - ) - - if complete_process.returncode != 0 or complete_process.stderr: - raise RuntimeError( - "data-diff command did not exit with success. " - + complete_process.stderr.decode() - ) - output = complete_process.stdout.decode() - return re.sub(r"\nExtra-Info:.*", "", output, flags=re.DOTALL) - - def send_report_to_slack(self): - """ - post the summary report to the slack channel if configured. - """ - if report_to_slack_channel: - token = os.environ["CAGP_SLACK_API_TOKEN"] - client = WebClient(token=token) - - # Send a message - client.chat_postMessage( - channel=report_to_slack_channel, - text=self.report, - username="CAGP Diff Bot", - ) - - def email_report(self): - """ - email the summary report if configured. - """ - if report_to_email: - # Create a text/plain message - msg = MIMEText(self.report) - msg["Subject"] = "Clean & Green Philly: Data difference report" - msg["From"] = from_email - msg["To"] = report_to_email - - # Send the message via our own SMTP server - s = smtplib.SMTP(smtp_server) - s.sendmail(from_email, [report_to_email], msg.as_string()) - s.quit() - - diff --git a/data/src/classes/featurelayer.py b/data/src/classes/featurelayer.py deleted file mode 100644 index f3eff73d..00000000 --- a/data/src/classes/featurelayer.py +++ /dev/null @@ -1,409 +0,0 @@ -import logging as log -import os -import subprocess -import traceback - -import geopandas as gpd -import pandas as pd -import requests -import sqlalchemy as sa -from config.config import ( - FORCE_RELOAD, - USE_CRS, - log_level, - min_tiles_file_size_in_bytes, - write_production_tiles_file, -) -from config.psql import conn, local_engine -from esridump.dumper import EsriDumper -from google.cloud import storage -from google.cloud.storage.bucket import Bucket -from shapely import Point, wkb - -log.basicConfig(level=log_level) - - -def google_cloud_bucket() -> Bucket: - """Build the google cloud bucket with name configured in your environ or default of cleanandgreenphl - - Returns: - Bucket: the gcp bucket - """ - credentials_path = os.path.expanduser("/app/service-account-key.json") - - if not os.path.exists(credentials_path): - raise FileNotFoundError(f"Credentials file not found at {credentials_path}") - - os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = credentials_path - bucket_name = os.getenv("GOOGLE_CLOUD_BUCKET_NAME", "cleanandgreenphl") - project_name = os.getenv("GOOGLE_CLOUD_PROJECT", "clean-and-green-philly") - - storage_client = storage.Client(project=project_name) - return storage_client.bucket(bucket_name) - - - - -class FeatureLayer: - """ - FeatureLayer is a class to represent a GIS dataset. It can be initialized with a URL to an Esri Feature Service, a SQL query to Carto, or a GeoDataFrame. - """ - - def __init__( - self, - name, - esri_rest_urls=None, - carto_sql_queries=None, - gdf=None, - crs=USE_CRS, - force_reload=FORCE_RELOAD, - from_xy=False, - use_wkb_geom_field=None, - cols: list[str] = None, - bucket: Bucket = None - ): - self.name = name - self.esri_rest_urls = ( - [esri_rest_urls] if isinstance(esri_rest_urls, str) else esri_rest_urls - ) - self.carto_sql_queries = ( - [carto_sql_queries] - if isinstance(carto_sql_queries, str) - else carto_sql_queries - ) - self.gdf = gdf - self.crs = crs - self.cols = cols - self.psql_table = name.lower().replace(" ", "_") - self.input_crs = "EPSG:4326" if not from_xy else USE_CRS - self.use_wkb_geom_field = use_wkb_geom_field - self.bucket = bucket or google_cloud_bucket() - - inputs = [self.esri_rest_urls, self.carto_sql_queries, self.gdf] - non_none_inputs = [i for i in inputs if i is not None] - - if len(non_none_inputs) > 0: - if self.esri_rest_urls is not None: - self.type = "esri" - elif self.carto_sql_queries is not None: - self.type = "carto" - elif self.gdf is not None: - self.type = "gdf" - - if force_reload: - self.load_data() - else: - psql_exists = self.check_psql() - if not psql_exists: - self.load_data() - else: - print(f"Initialized FeatureLayer {self.name} with no data.") - - def check_psql(self): - try: - if not sa.inspect(local_engine).has_table(self.psql_table): - print(f"Table {self.psql_table} does not exist") - return False - psql_table = gpd.read_postgis( - f"SELECT * FROM {self.psql_table}", conn, geom_col="geometry" - ) - if len(psql_table) == 0: - return False - else: - print(f"Loading data for {self.name} from psql...") - self.gdf = psql_table - return True - except Exception as e: - print(f"Error loading data for {self.name}: {e}") - return False - - def load_data(self): - print(f"Loading data for {self.name} from {self.type}...") - if self.type == "gdf": - pass - else: - try: - if self.type == "esri": - if self.esri_rest_urls is None: - raise ValueError("Must provide a URL to load data from Esri") - - gdfs = [] - for url in self.esri_rest_urls: - parcel_type = ( - "Land" - if "Vacant_Indicators_Land" in url - else "Building" - if "Vacant_Indicators_Bldg" in url - else None - ) - self.dumper = EsriDumper(url) - features = [feature for feature in self.dumper] - - geojson_features = { - "type": "FeatureCollection", - "features": features, - } - - this_gdf = gpd.GeoDataFrame.from_features( - geojson_features, crs=self.input_crs - ) - - # Check if 'X' and 'Y' columns exist and create geometry if necessary - if "X" in this_gdf.columns and "Y" in this_gdf.columns: - this_gdf["geometry"] = this_gdf.apply( - lambda row: Point(row["X"], row["Y"]), axis=1 - ) - elif "geometry" not in this_gdf.columns: - raise ValueError( - "No geometry information found in the data." - ) - - this_gdf = this_gdf.to_crs(USE_CRS) - - # Assign the parcel_type to the GeoDataFrame - if parcel_type: - this_gdf["parcel_type"] = parcel_type - - gdfs.append(this_gdf) - - self.gdf = pd.concat(gdfs, ignore_index=True) - - elif self.type == "carto": - if self.carto_sql_queries is None: - raise ValueError( - "Must provide a SQL query to load data from Carto" - ) - - gdfs = [] - for sql_query in self.carto_sql_queries: - response = requests.get( - "https://phl.carto.com/api/v2/sql", params={"q": sql_query} - ) - - data = response.json()["rows"] - df = pd.DataFrame(data) - geometry = ( - wkb.loads(df[self.use_wkb_geom_field], hex=True) - if self.use_wkb_geom_field - else gpd.points_from_xy(df.x, df.y) - ) - - gdf = gpd.GeoDataFrame( - df, - geometry=geometry, - crs=self.input_crs, - ) - gdf = gdf.to_crs(USE_CRS) - - gdfs.append(gdf) - self.gdf = pd.concat(gdfs, ignore_index=True) - - # Drop columns - if self.cols: - self.cols.append("geometry") - self.gdf = self.gdf[self.cols] - - # save self.gdf to psql - # rename columns to lowercase for table creation in postgres - if self.cols: - self.gdf = self.gdf.rename( - columns={x: x.lower() for x in self.cols} - ) - self.gdf.to_postgis( - name=self.psql_table, - con=conn, - if_exists="replace", - chunksize=1000, - ) - except Exception as e: - print(f"Error loading data for {self.name}: {e}") - traceback.print_exc() - self.gdf = None - - def spatial_join(self, other_layer, how="left", predicate="intersects"): - """ - Spatial joins in this script are generally left intersect joins. - They also can create duplicates, so we drop duplicates after the join. - Note: We may want to revisit the duplicates. - """ - - # If other_layer.gdf isn't a geodataframe, try to make it one - if not isinstance(other_layer.gdf, gpd.GeoDataFrame): - try: - other_layer.rebuild_gdf() - - except Exception as e: - print(f"Error converting other_layer to GeoDataFrame: {e}") - return - - self.gdf = gpd.sjoin(self.gdf, other_layer.gdf, how=how, predicate=predicate) - self.gdf.drop(columns=["index_right"], inplace=True) - self.gdf.drop_duplicates(inplace=True) - - # Coerce opa_id to integer and drop rows where opa_id is null or non-numeric - self.gdf.loc[:, "opa_id"] = pd.to_numeric(self.gdf["opa_id"], errors="coerce") - self.gdf = self.gdf.dropna(subset=["opa_id"]) - - def opa_join(self, other_df, opa_column): - """ - Join 2 dataframes based on opa_id and keep the 'geometry' column from the left dataframe if it exists in both. - """ - - # Coerce opa_column to integer and drop rows where opa_column is null or non-numeric - other_df.loc[:, opa_column] = pd.to_numeric( - other_df[opa_column], errors="coerce" - ) - other_df = other_df.dropna(subset=[opa_column]) - - # Coerce opa_id to integer and drop rows where opa_id is null or non-numeric - self.gdf.loc[:, "opa_id"] = pd.to_numeric(self.gdf["opa_id"], errors="coerce") - self.gdf = self.gdf.dropna(subset=["opa_id"]) - - # Perform the merge - joined = self.gdf.merge( - other_df, how="left", right_on=opa_column, left_on="opa_id" - ) - - # Check if 'geometry' column exists in both dataframes and clean up - if "geometry_x" in joined.columns and "geometry_y" in joined.columns: - joined = joined.drop(columns=["geometry_y"]).copy() # Ensure a full copy - joined = joined.rename(columns={"geometry_x": "geometry"}) - - if opa_column != "opa_id": - joined = joined.drop(columns=[opa_column]) - - # Assign the joined DataFrame to self.gdf as a full copy - self.gdf = joined.copy() - self.rebuild_gdf() - - def rebuild_gdf(self): - self.gdf = gpd.GeoDataFrame(self.gdf, geometry="geometry", crs=self.crs) - - def create_centroid_gdf(self): - """ - Convert the geometry of the GeoDataFrame to centroids. - """ - self.centroid_gdf = self.gdf.copy() - self.centroid_gdf.loc[:, "geometry"] = self.gdf["geometry"].centroid - - def build_and_publish(self, tiles_file_id_prefix: str) -> None: - """ - Builds PMTiles and a Parquet file from a GeoDataFrame and publishes them to Google Cloud Storage. - - Args: - tiles_file_id_prefix (str): The ID prefix used for naming the PMTiles and Parquet files, coming from config. - - Raises: - ValueError: Raised if the generated PMTiles file is smaller than the minimum allowed size, indicating a potential corruption or incomplete file. - """ - zoom_threshold: int = 13 - - # Export the GeoDataFrame to a temporary GeoJSON file - temp_geojson_points: str = f"tmp/temp_{tiles_file_id_prefix}_points.geojson" - temp_geojson_polygons: str = f"tmp/temp_{tiles_file_id_prefix}_polygons.geojson" - temp_pmtiles_points: str = f"tmp/temp_{tiles_file_id_prefix}_points.pmtiles" - temp_pmtiles_polygons: str = f"tmp/temp_{tiles_file_id_prefix}_polygons.pmtiles" - temp_merged_pmtiles: str = f"tmp/temp_{tiles_file_id_prefix}_merged.pmtiles" - temp_parquet: str = f"tmp/{tiles_file_id_prefix}.parquet" - - # Reproject - gdf_wm = self.gdf.to_crs(epsg=4326) - gdf_wm.to_file(temp_geojson_polygons, driver="GeoJSON") - - # Create points dataset - self.centroid_gdf = self.gdf.copy() - self.centroid_gdf["geometry"] = self.centroid_gdf["geometry"].centroid - self.centroid_gdf = self.centroid_gdf.to_crs(epsg=4326) - self.centroid_gdf.to_file(temp_geojson_points, driver="GeoJSON") - - # Load the GeoJSON from the polygons, drop geometry, and save as Parquet - gdf_polygons = gpd.read_file(temp_geojson_polygons) - df_no_geom = gdf_polygons.drop(columns=["geometry"]) - - # Check if the DataFrame has fewer than 25,000 rows - num_rows, num_cols = df_no_geom.shape - if num_rows < 25000: - print( - f"Parquet file has {num_rows} rows, which is fewer than 25,000. Skipping upload." - ) - return - - # Save the DataFrame as Parquet - df_no_geom.to_parquet(temp_parquet) - - # Upload Parquet to Google Cloud Storage - blob_parquet = self.bucket.blob(f"{tiles_file_id_prefix}.parquet") - try: - blob_parquet.upload_from_filename(temp_parquet) - parquet_size = os.stat(temp_parquet).st_size - parquet_size_mb = parquet_size / (1024 * 1024) - print( - f"Parquet upload successful! Size: {parquet_size} bytes ({parquet_size_mb:.2f} MB), Dimensions: {num_rows} rows, {num_cols} columns." - ) - except Exception as e: - print(f"Parquet upload failed: {e}") - return - - # Command for generating PMTiles for points up to zoom level zoom_threshold - points_command: list[str] = [ - "tippecanoe", - f"--output={temp_pmtiles_points}", - f"--maximum-zoom={zoom_threshold}", - "--minimum-zoom=10", - "-zg", - "-aC", - "-r0", - temp_geojson_points, - "-l", - "vacant_properties_tiles_points", - "--force", - ] - - # Command for generating PMTiles for polygons from zoom level zoom_threshold - polygons_command: list[str] = [ - "tippecanoe", - f"--output={temp_pmtiles_polygons}", - f"--minimum-zoom={zoom_threshold}", - "--maximum-zoom=16", - "-zg", - "--no-tile-size-limit", - temp_geojson_polygons, - "-l", - "vacant_properties_tiles_polygons", - "--force", - ] - - # Command for merging the two PMTiles files into a single output file - merge_command: list[str] = [ - "tile-join", - f"--output={temp_merged_pmtiles}", - "--no-tile-size-limit", - temp_pmtiles_polygons, - temp_pmtiles_points, - "--force", - ] - - # Run the commands - for command in [points_command, polygons_command, merge_command]: - subprocess.run(command) - - write_files: list[str] = [f"{tiles_file_id_prefix}_staging.pmtiles"] - - if write_production_tiles_file: - write_files.append(f"{tiles_file_id_prefix}.pmtiles") - - # Check whether the temp saved tiles files is big enough. - file_size: int = os.stat(temp_merged_pmtiles).st_size - if file_size < min_tiles_file_size_in_bytes: - raise ValueError( - f"{temp_merged_pmtiles} is {file_size} bytes in size but should be at least {min_tiles_file_size_in_bytes}. Therefore, we are not uploading any files to the GCP bucket. The file may be corrupt or incomplete." - ) - - # Upload PMTiles to Google Cloud Storage - for file in write_files: - blob = self.bucket.blob(file) - try: - blob.upload_from_filename(temp_merged_pmtiles) - print(f"PMTiles upload successful for {file}!") - except Exception as e: - print(f"PMTiles upload failed for {file}: {e}") \ No newline at end of file diff --git a/data/src/classes/slack_error_reporter.py b/data/src/classes/slack_error_reporter.py deleted file mode 100644 index 1c443d4b..00000000 --- a/data/src/classes/slack_error_reporter.py +++ /dev/null @@ -1,16 +0,0 @@ -import os -from slack_sdk import WebClient - - -def send_error_to_slack(error_message: str) -> None: - """Send error message to Slack.""" - token: str | None = os.getenv("CAGP_SLACK_API_TOKEN") # token can be None - if token: - client = WebClient(token=token) - client.chat_postMessage( - channel="clean-and-green-philly-back-end", # Replace with actual Slack channel ID - text=error_message, - username="Backend Error Reporter", - ) - else: - raise ValueError("Slack API token not found in environment variables.") diff --git a/data/src/config/config.py b/data/src/config/config.py index 7b7fa01c..4b240cf2 100644 --- a/data/src/config/config.py +++ b/data/src/config/config.py @@ -1,5 +1,4 @@ import logging -import os from pathlib import Path FORCE_RELOAD = False diff --git a/data/src/constants/__init__.py b/data/src/constants/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/data/src/constants/services.py b/data/src/constants/services.py deleted file mode 100644 index dcc4daac..00000000 --- a/data/src/constants/services.py +++ /dev/null @@ -1,78 +0,0 @@ -import datetime - -VACANT_PROPS_LAYERS_TO_LOAD = [ - "https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/Vacant_Indicators_Land/FeatureServer/0/", - "https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/Vacant_Indicators_Bldg/FeatureServer/0/", -] - -COUNCIL_DISTRICTS_TO_LOAD = [ - "https://services.arcgis.com/fLeGjb7u4uXqeF9q/arcgis/rest/services/Council_Districts_2024/FeatureServer/0/" -] - -CITY_OWNED_PROPERTIES_TO_LOAD = [ - "https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/LAMAAssets/FeatureServer/0/" -] - -PHS_LAYERS_TO_LOAD = [ - "https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/phs_landcare/FeatureServer/0", -] - -RCOS_LAYERS_TO_LOAD = [ - "https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/Zoning_RCO/FeatureServer/0/" -] - -COMMUNITY_GARDENS_TO_LOAD = [ - "https://services2.arcgis.com/qjOOiLCYeUtwT7x7/arcgis/rest/services/PHS_NGT_Supported_Current_view/FeatureServer/0/" -] - -PPR_PROPERTIES_TO_LOAD = [ - "https://services.arcgis.com/fLeGjb7u4uXqeF9q/ArcGIS/rest/services/PPR_Properties/FeatureServer/0" -] - -one_year_ago = (datetime.datetime.now() - datetime.timedelta(days=365)).strftime( - "%Y-%m-%d" -) - -# Load data for complaints from L&I -COMPLAINTS_SQL_QUERY = f"SELECT address, service_request_id, subject, status, service_name, service_code, lat AS y, lon AS x FROM public_cases_fc WHERE requested_datetime >= '{one_year_ago}' AND lat IS NOT NULL" - -VIOLATIONS_SQL_QUERY = f"SELECT parcel_id_num, casenumber, casecreateddate, casetype, casestatus, violationnumber, violationcodetitle, violationstatus, opa_account_num, address, opa_owner, geocode_x AS x, geocode_y AS y FROM violations WHERE violationdate >= '{one_year_ago}' AND geocode_x IS NOT NULL" - -GUNCRIME_SQL_QUERY = f"SELECT text_general_code, dispatch_date, point_x AS x, point_y AS y FROM incidents_part1_part2 WHERE dispatch_date_time >= '{one_year_ago}' AND text_general_code IN ('Aggravated Assault Firearm', 'Robbery Firearm') AND point_x IS NOT NULL" - -DRUGCRIME_SQL_QUERY = f"SELECT text_general_code, dispatch_date, point_x AS x, point_y AS y FROM incidents_part1_part2 WHERE dispatch_date_time >= '{one_year_ago}' AND text_general_code IN ('Narcotic / Drug Law Violations') AND point_x IS NOT NULL" - -DELINQUENCIES_QUERY = "SELECT * FROM real_estate_tax_delinquencies" - -OPA_PROPERTIES_QUERY = "SELECT building_code_description, market_value, sale_date, sale_price, parcel_number, owner_1, owner_2, mailing_address_1, mailing_address_2, mailing_care_of, mailing_street, mailing_zip, mailing_city_state, zip_code, zoning, the_geom FROM opa_properties_public" - -PWD_PARCELS_QUERY = "SELECT *, the_geom FROM pwd_parcels" - -UNSAFE_BUILDINGS_QUERY = "SELECT * FROM unsafe" - -IMMINENT_DANGER_BUILDINGS_QUERY = "SELECT * FROM imm_dang" - -PERMITS_QUERY = f""" - SELECT - address, - addressobjectid, - approvedscopeofwork, - commercialorresidential, - opa_account_num, - permittype, - status, - unit_num, - unit_type, - permitissuedate, - typeofwork, - the_geom, - ST_AsGeoJSON(the_geom)::json AS the_geom_geojson - FROM permits - WHERE permitissuedate >= '{one_year_ago}' - """ - -NBHOODS_URL = "https://raw.githubusercontent.com/opendataphilly/open-geo-data/master/philadelphia-neighborhoods/philadelphia-neighborhoods.geojson" - -CENSUS_BGS_URL = ( - "https://opendata.arcgis.com/datasets/2f982bada233478ea0100528227febce_0.geojson" -) \ No newline at end of file diff --git a/data/src/data_utils/__init__.py b/data/src/data_utils/__init__.py deleted file mode 100644 index e1709a69..00000000 --- a/data/src/data_utils/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -from .city_owned_properties import city_owned_properties -from .phs_properties import phs_properties -from .l_and_i import l_and_i -from .rco_geoms import rco_geoms -from .tree_canopy import tree_canopy -from .nbhoods import nbhoods -from .gun_crimes import gun_crimes -from .deliquencies import deliquencies -from .opa_properties import opa_properties -from .vacant_properties import vacant_properties -from .priority_level import priority_level -from .access_process import access_process - -__all__ = [ - "city_owned_properties", - "phs_properties", - "l_and_i", - "rco_geoms", - "tree_canopy", - "nbhoods", - "gun_crimes", - "deliquencies", - "opa_properties", - "vacant_properties", - "priority_level", - "access_process", -] diff --git a/data/src/data_utils/access_process.py b/data/src/data_utils/access_process.py deleted file mode 100644 index 7c8e79de..00000000 --- a/data/src/data_utils/access_process.py +++ /dev/null @@ -1,43 +0,0 @@ -from typing import Any - - -def access_process(dataset: Any) -> Any: - """ - Process a dataset to determine the access process for each property based on - city ownership and market value. The result is added as a new column in the dataset. - - Args: - dataset (Any): The dataset containing a GeoDataFrame named `gdf` with - columns "city_owner_agency" and "market_value". - - Returns: - Any: The updated dataset with an additional "access_process" column. - - Side Effects: - Prints the distribution of the "access_process" column. - """ - access_processes = [] - - for _, row in dataset.gdf.iterrows(): - # Decision Points - city_owner_agency = row["city_owner_agency"] - market_value_over_1000 = ( - row["market_value"] and float(row["market_value"]) > 1000 - ) - - # Simplified decision logic - if city_owner_agency == "Land Bank (PHDC)": - access_process = "Go through Land Bank" - elif city_owner_agency == "PRA": - access_process = "Do Nothing" - else: - if market_value_over_1000: - access_process = "Private Land Use Agreement" - else: - access_process = "Buy Property" - - access_processes.append(access_process) - - dataset.gdf["access_process"] = access_processes - - return dataset diff --git a/data/src/data_utils/city_owned_properties.py b/data/src/data_utils/city_owned_properties.py deleted file mode 100644 index a5b21980..00000000 --- a/data/src/data_utils/city_owned_properties.py +++ /dev/null @@ -1,81 +0,0 @@ -from typing import Any -from classes.featurelayer import FeatureLayer -from constants.services import CITY_OWNED_PROPERTIES_TO_LOAD - -def city_owned_properties(primary_featurelayer: FeatureLayer) -> FeatureLayer: - """ - Processes city-owned property data by joining it with the primary feature layer, - renaming columns, and updating access information for properties based on ownership. - All instances where the "city_owner_agency" is "PLB" are changed to "Land Bank (PHDC)". - - Args: - primary_featurelayer (FeatureLayer): The primary feature layer to which city-owned - property data will be joined. - - Returns: - FeatureLayer: The updated primary feature layer with processed city ownership - information. - """ - city_owned_properties = FeatureLayer( - name="City Owned Properties", - esri_rest_urls=CITY_OWNED_PROPERTIES_TO_LOAD, - cols=["OPABRT", "AGENCY", "SIDEYARDELIGIBLE"], - ) - - city_owned_properties.gdf.dropna(subset=["opabrt"], inplace=True) - - primary_featurelayer.opa_join(city_owned_properties.gdf, "opabrt") - - rename_columns = { - "agency": "city_owner_agency", - "sideyardeligible": "side_yard_eligible", - } - primary_featurelayer.gdf.rename(columns=rename_columns, inplace=True) - - primary_featurelayer.gdf.loc[ - primary_featurelayer.gdf["owner_1"].isin( - [ - "PHILADELPHIA HOUSING AUTH", - "PHILADELPHIA LAND BANK", - "REDEVELOPMENT AUTHORITY", - "PHILA REDEVELOPMENT AUTH", - ] - ), - "city_owner_agency", - ] = primary_featurelayer.gdf["owner_1"].replace( - { - "PHILADELPHIA HOUSING AUTH": "PHA", - "PHILADELPHIA LAND BANK": "Land Bank (PHDC)", - "REDEVELOPMENT AUTHORITY": "PRA", - "PHILA REDEVELOPMENT AUTH": "PRA", - } - ) - - primary_featurelayer.gdf.loc[ - (primary_featurelayer.gdf["owner_1"] == "CITY OF PHILA") - & ( - primary_featurelayer.gdf["owner_2"].str.contains( - "PUBLIC PROP|PUBLC PROP", na=False - ) - ), - "city_owner_agency", - ] = "DPP" - - primary_featurelayer.gdf.loc[ - primary_featurelayer.gdf["owner_1"].isin( - ["CITY OF PHILADELPHIA", "CITY OF PHILA"] - ) - & primary_featurelayer.gdf["owner_2"].isna(), - "city_owner_agency", - ] = "City of Philadelphia" - - primary_featurelayer.gdf.loc[:, "side_yard_eligible"] = primary_featurelayer.gdf[ - "side_yard_eligible" - ].fillna("No") - - # Update all instances where city_owner_agency is "PLB" to "Land Bank (PHDC)" - primary_featurelayer.gdf.loc[ - primary_featurelayer.gdf["city_owner_agency"] == "PLB", "city_owner_agency" - ] = "Land Bank (PHDC)" - - return primary_featurelayer diff --git a/data/src/data_utils/community_gardens.py b/data/src/data_utils/community_gardens.py deleted file mode 100644 index 4bed0284..00000000 --- a/data/src/data_utils/community_gardens.py +++ /dev/null @@ -1,28 +0,0 @@ -from classes.featurelayer import FeatureLayer -from constants.services import COMMUNITY_GARDENS_TO_LOAD - - -def community_gardens(primary_featurelayer): - # this script *removes* (rather than adds) known community gardens from the dataset in order to protect them from potential predatory developers - community_gardens = FeatureLayer( - name="Community Gardens", esri_rest_urls=COMMUNITY_GARDENS_TO_LOAD - ) - - community_gardens.gdf = community_gardens.gdf[["Site_Name", "geometry"]] - - primary_featurelayer.spatial_join(community_gardens) - - # Create a boolean mask where 'site_Name' is not null - mask = primary_featurelayer.gdf["Site_Name"].notnull() - - count_dropped = mask.sum() - print(f"Number of community gardens being dropped: {count_dropped}") - - # Use this mask to drop rows where 'site_Name' is not null - primary_featurelayer.gdf = primary_featurelayer.gdf.drop( - primary_featurelayer.gdf[mask].index - ) - - primary_featurelayer.gdf = primary_featurelayer.gdf.drop(columns=["Site_Name"]) - - return primary_featurelayer diff --git a/data/src/data_utils/conservatorship.py b/data/src/data_utils/conservatorship.py deleted file mode 100644 index 5f9c9793..00000000 --- a/data/src/data_utils/conservatorship.py +++ /dev/null @@ -1,59 +0,0 @@ -import datetime -from dateutil.parser import parse -import pytz - -est = pytz.timezone("US/Eastern") -six_months_ago = (datetime.datetime.now() - datetime.timedelta(days=180)).astimezone( - est -) - -blight_words = [ - "weed", - "rubbish", - "garbage", - "tire", - "debris", - "clean", - "waste", - "vegetation", - "dumping", - "scrap", - "auto", - "vehicle", - "graffiti", - "dangerous", -] - - -def conservatorship(primary_featurelayer): - conservatorships = [] - - for idx, row in primary_featurelayer.gdf.iterrows(): - city_owner_agency = row["city_owner_agency"] - sheriff_sale = row["sheriff_sale"] == "Y" - market_value_over_1000 = ( - row["market_value"] and float(row["market_value"]) > 1000 - ) - li_complaints_lower = str(row["li_complaints"]).lower().split(" ") - contains_blight_word = any(word in li_complaints_lower for word in blight_words) - - try: - sale_date = parse(row["sale_date"]).astimezone(est) - sale_date_6_months_ago = sale_date <= six_months_ago - except (TypeError, ValueError): - sale_date_6_months_ago = False - - # Simplified decision logic - if city_owner_agency == "Land Bank (PHDC)" or ( - not sale_date_6_months_ago and market_value_over_1000 - ): - conservatorship = "No" - elif contains_blight_word and not sheriff_sale and sale_date_6_months_ago: - conservatorship = "Yes" - else: - conservatorship = "No" - - conservatorships.append(conservatorship) - - primary_featurelayer.gdf["conservatorship"] = conservatorships - return primary_featurelayer diff --git a/data/src/data_utils/contig_neighbors.py b/data/src/data_utils/contig_neighbors.py deleted file mode 100644 index 1c811a15..00000000 --- a/data/src/data_utils/contig_neighbors.py +++ /dev/null @@ -1,27 +0,0 @@ -import warnings - -import networkx as nx -from libpysal.weights import Queen - - -def contig_neighbors(primary_featurelayer): - parcels = primary_featurelayer.gdf - - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", category=FutureWarning) - warnings.filterwarnings( - "ignore", - category=UserWarning, - message="The weights matrix is not fully connected", - ) - - w = Queen.from_dataframe(parcels) - - g = w.to_networkx() - - # Calculate the number of contiguous neighbors for each feature in parcels - n_contiguous = [len(nx.node_connected_component(g, i)) for i in range(len(parcels))] - - primary_featurelayer.gdf["n_contiguous"] = n_contiguous - - return primary_featurelayer diff --git a/data/src/data_utils/deliquencies.py b/data/src/data_utils/deliquencies.py deleted file mode 100644 index 16f8f205..00000000 --- a/data/src/data_utils/deliquencies.py +++ /dev/null @@ -1,31 +0,0 @@ -from classes.featurelayer import FeatureLayer -from constants.services import DELINQUENCIES_QUERY - - -def deliquencies(primary_featurelayer): - tax_deliquencies = FeatureLayer( - name="Property Tax Delinquencies", - carto_sql_queries=DELINQUENCIES_QUERY, - use_wkb_geom_field="the_geom", - cols=[ - "opa_number", - "total_due", - "is_actionable", - "payment_agreement", - "num_years_owed", - "most_recent_year_owed", - "total_assessment", - "sheriff_sale", - ], - ) - - primary_featurelayer.opa_join( - tax_deliquencies.gdf, - "opa_number", - ) - - primary_featurelayer.gdf.loc[:, "sheriff_sale"] = primary_featurelayer.gdf[ - "sheriff_sale" - ].fillna("N") - - return primary_featurelayer diff --git a/data/src/data_utils/dev_probability.py b/data/src/data_utils/dev_probability.py deleted file mode 100644 index 4c8a220f..00000000 --- a/data/src/data_utils/dev_probability.py +++ /dev/null @@ -1,59 +0,0 @@ -import geopandas as gpd -import jenkspy -import pandas as pd -import requests -from classes.featurelayer import FeatureLayer -from constants.services import CENSUS_BGS_URL, PERMITS_QUERY - -from config.config import USE_CRS - - -def dev_probability(primary_featurelayer): - census_bgs_gdf = gpd.read_file(CENSUS_BGS_URL) - census_bgs_gdf = census_bgs_gdf.to_crs(USE_CRS) - - base_url = "https://phl.carto.com/api/v2/sql" - response = requests.get(f"{base_url}?q={PERMITS_QUERY}&format=GeoJSON") - - if response.status_code == 200: - try: - permits_gdf = gpd.GeoDataFrame.from_features( - response.json(), crs="EPSG:4326" - ) - print("GeoDataFrame created successfully.") - except Exception as e: - print(f"Failed to convert response to GeoDataFrame: {e}") - return primary_featurelayer - else: - truncated_response = response.content[:500] - print( - f"Failed to fetch permits data. HTTP status code: {response.status_code}. Response text: {truncated_response}" - ) - return primary_featurelayer - - permits_gdf = permits_gdf.to_crs(USE_CRS) - - joined_gdf = gpd.sjoin(permits_gdf, census_bgs_gdf, how="inner", predicate="within") - - permit_counts = joined_gdf.groupby("index_right").size() - census_bgs_gdf["permit_count"] = census_bgs_gdf.index.map(permit_counts) - census_bgs_gdf["permit_count"] = census_bgs_gdf["permit_count"].fillna(0) - - # Classify development probability using Jenks natural breaks - breaks = jenkspy.jenks_breaks(census_bgs_gdf["permit_count"], n_classes=3) - census_bgs_gdf["dev_rank"] = pd.cut( - census_bgs_gdf["permit_count"], bins=breaks, labels=["Low", "Medium", "High"] - ).astype(str) - - updated_census_bgs = FeatureLayer( - name="Updated Census Block Groups", - gdf=census_bgs_gdf[["permit_count", "dev_rank", "geometry"]], - use_wkb_geom_field="geometry", - cols=["permit_count", "dev_rank"], - ) - - updated_census_bgs.gdf = updated_census_bgs.gdf.to_crs(USE_CRS) - - primary_featurelayer.spatial_join(updated_census_bgs) - - return primary_featurelayer diff --git a/data/src/data_utils/drug_crimes.py b/data/src/data_utils/drug_crimes.py deleted file mode 100644 index 61a4a43c..00000000 --- a/data/src/data_utils/drug_crimes.py +++ /dev/null @@ -1,10 +0,0 @@ -from constants.services import DRUGCRIME_SQL_QUERY - - -from data_utils.kde import apply_kde_to_primary - - -def drug_crimes(primary_featurelayer): - return apply_kde_to_primary( - primary_featurelayer, "Drug Crimes", DRUGCRIME_SQL_QUERY - ) diff --git a/data/src/data_utils/gun_crimes.py b/data/src/data_utils/gun_crimes.py deleted file mode 100644 index 27155546..00000000 --- a/data/src/data_utils/gun_crimes.py +++ /dev/null @@ -1,8 +0,0 @@ -from constants.services import GUNCRIME_SQL_QUERY - - -from data_utils.kde import apply_kde_to_primary - - -def gun_crimes(primary_featurelayer): - return apply_kde_to_primary(primary_featurelayer, "Gun Crimes", GUNCRIME_SQL_QUERY) diff --git a/data/src/data_utils/imm_dang_buildings.py b/data/src/data_utils/imm_dang_buildings.py deleted file mode 100644 index 7e7041ba..00000000 --- a/data/src/data_utils/imm_dang_buildings.py +++ /dev/null @@ -1,28 +0,0 @@ -from classes.featurelayer import FeatureLayer -from constants.services import IMMINENT_DANGER_BUILDINGS_QUERY - - -def imm_dang_buildings(primary_featurelayer): - imm_dang_buildings = FeatureLayer( - name="Imminently Dangerous Buildings", - use_wkb_geom_field="the_geom", - carto_sql_queries=IMMINENT_DANGER_BUILDINGS_QUERY, - cols=["opa_account_num"], - ) - - imm_dang_buildings.gdf.loc[:, "imm_dang_building"] = "Y" - - imm_dang_buildings.gdf = imm_dang_buildings.gdf.rename( - columns={"opa_account_num": "opa_number"} - ) - - primary_featurelayer.opa_join( - imm_dang_buildings.gdf, - "opa_number", - ) - - primary_featurelayer.gdf.loc[:, "imm_dang_building"] = primary_featurelayer.gdf[ - "imm_dang_building" - ].fillna("N") - - return primary_featurelayer diff --git a/data/src/data_utils/kde.py b/data/src/data_utils/kde.py deleted file mode 100644 index 477cc306..00000000 --- a/data/src/data_utils/kde.py +++ /dev/null @@ -1,159 +0,0 @@ -import numpy as np -import rasterio -from awkde.awkde import GaussianKDE -from classes.featurelayer import FeatureLayer -from config.config import USE_CRS -from rasterio.transform import Affine -from tqdm import tqdm -from concurrent.futures import ProcessPoolExecutor, as_completed - -import mapclassify - -resolution = 1320 # 0.25 miles (in feet, bc the CRS is 2272) -batch_size = 100000 - - -def kde_predict_chunk(kde, chunk): - """Helper function to predict KDE for a chunk of grid points.""" - return kde.predict(chunk) - - -def generic_kde(name, query, resolution=resolution, batch_size=batch_size): - print(f"Initializing FeatureLayer for {name}") - - feature_layer = FeatureLayer(name=name, carto_sql_queries=query) - - coords = np.array([geom.xy for geom in feature_layer.gdf.geometry]) - x, y = coords[:, 0, :].flatten(), coords[:, 1, :].flatten() - - X = np.column_stack((x, y)) - - x_grid, y_grid = ( - np.linspace(x.min(), x.max(), resolution), - np.linspace(y.min(), y.max(), resolution), - ) - xx, yy = np.meshgrid(x_grid, y_grid) - grid_points = np.column_stack((xx.ravel(), yy.ravel())) - - print(f"Fitting KDE for {name} data") - kde = GaussianKDE(glob_bw=0.1, alpha=0.999, diag_cov=True) - kde.fit(X) - - print(f"Predicting KDE values for grid of size {grid_points.shape}") - - # Split grid points into chunks - chunks = [ - grid_points[i : i + batch_size] for i in range(0, len(grid_points), batch_size) - ] - - # Run predictions in parallel - z = np.zeros(len(grid_points)) # Placeholder for predicted values - - with ProcessPoolExecutor() as executor: - # Submit the tasks first, wrapped with tqdm to monitor as they're submitted - futures = { - executor.submit(kde_predict_chunk, kde, chunk): i - for i, chunk in enumerate(tqdm(chunks, desc="Submitting tasks")) - } - - # Now wrap the as_completed with tqdm for progress tracking - for future in tqdm( - as_completed(futures), total=len(futures), desc="Processing tasks" - ): - i = futures[future] - z[i * batch_size : (i + 1) * batch_size] = future.result() - - zz = z.reshape(xx.shape) - - x_res, y_res = ( - (x.max() - x.min()) / (resolution - 1), - (y.max() - y.min()) / (resolution - 1), - ) - min_x, min_y = x.min(), y.min() - - transform = Affine.translation(min_x, min_y) * Affine.scale(x_res, y_res) - - raster_filename = f"tmp/{name.lower().replace(' ', '_')}.tif" - print(f"Saving raster to {raster_filename}") - - with rasterio.open( - raster_filename, - "w", - driver="GTiff", - height=zz.shape[0], - width=zz.shape[1], - count=1, - dtype=zz.dtype, - crs=USE_CRS, - transform=transform, - ) as dst: - dst.write(zz, 1) - - return raster_filename, X - - -def apply_kde_to_primary(primary_featurelayer, name, query, resolution=resolution): - # Generate KDE and raster file - raster_filename, crime_coords = generic_kde(name, query, resolution) - - # Add centroid column temporarily - primary_featurelayer.gdf["centroid"] = primary_featurelayer.gdf.geometry.centroid - - # Create list of (x, y) coordinates for centroids - coord_list = [ - (x, y) - for x, y in zip( - primary_featurelayer.gdf["centroid"].x, - primary_featurelayer.gdf["centroid"].y, - ) - ] - - # Remove the temporary centroid column - primary_featurelayer.gdf = primary_featurelayer.gdf.drop(columns=["centroid"]) - - # Open the generated raster file and sample the KDE density values at the centroids - with rasterio.open(raster_filename) as src: - sampled_values = [x[0] for x in src.sample(coord_list)] - - # Create a column for the density values - density_column = f"{name.lower().replace(' ', '_')}_density" - primary_featurelayer.gdf[density_column] = sampled_values - - # Calculate percentiles using mapclassify.Percentiles - percentile_breaks = list(range(101)) # Percentile breaks from 0 to 100 - classifier = mapclassify.Percentiles( - primary_featurelayer.gdf[density_column], pct=percentile_breaks - ) - - # Assign the percentile bins to the density values - primary_featurelayer.gdf[density_column + "_percentile"] = ( - classifier.yb - ) # yb gives the bin index - - # Apply percentile labels (e.g., 1st Percentile, 2nd Percentile, etc.) - primary_featurelayer.gdf[density_column + "_label"] = primary_featurelayer.gdf[ - density_column + "_percentile" - ].apply(label_percentile) - - # Convert the percentile column to float and drop the density column - primary_featurelayer.gdf[density_column + "_percentile"] = primary_featurelayer.gdf[ - density_column + "_percentile" - ].astype(float) - - primary_featurelayer.gdf = primary_featurelayer.gdf.drop(columns=[density_column]) - - print(f"Finished processing {name}") - return primary_featurelayer - - -def label_percentile(value): - if 10 <= value % 100 <= 13: - return f"{value}th Percentile" - elif value % 10 == 1: - return f"{value}st Percentile" - elif value % 10 == 2: - return f"{value}nd Percentile" - elif value % 10 == 3: - return f"{value}rd Percentile" - else: - return f"{value}th Percentile" diff --git a/data/src/data_utils/l_and_i.py b/data/src/data_utils/l_and_i.py deleted file mode 100644 index 27f28147..00000000 --- a/data/src/data_utils/l_and_i.py +++ /dev/null @@ -1,178 +0,0 @@ -import pandas as pd -import geopandas as gpd -from typing import List -from classes.featurelayer import FeatureLayer -from constants.services import COMPLAINTS_SQL_QUERY, VIOLATIONS_SQL_QUERY - -def l_and_i(primary_featurelayer: FeatureLayer) -> FeatureLayer: - """ - Process L&I (Licenses and Inspections) data for complaints and violations. - - This function filters and processes L&I complaints and violations data, - joining it with the primary feature layer based on spatial relationships - and OPA (Office of Property Assessment) identifiers. - - Args: - primary_featurelayer (FeatureLayer): The primary feature layer to join L&I data to. - - Returns: - FeatureLayer: The primary feature layer updated with L&I data. - """ - keywords: List[str] = [ - 'dumping', 'blight', 'rubbish', 'weeds', 'graffiti', - 'abandoned', 'sanitation', 'litter', 'vacant', 'trash', - 'unsafe' - ] - - # Load complaints data from L&I - l_and_i_complaints: FeatureLayer = FeatureLayer( - name="LI Complaints", - carto_sql_queries=COMPLAINTS_SQL_QUERY - ) - - # Filter for rows where 'subject' contains any of the keywords - l_and_i_complaints.gdf = l_and_i_complaints.gdf[ - l_and_i_complaints.gdf["subject"].str.lower().str.contains('|'.join(keywords)) - ] - - # Filter for only Status = 'Open' - l_and_i_complaints.gdf = l_and_i_complaints.gdf[ - l_and_i_complaints.gdf["status"].str.lower() == "open" - ] - - # Group by geometry and concatenate the violationcodetitle values into a list with a semicolon separator - l_and_i_complaints.gdf = ( - l_and_i_complaints.gdf.groupby("geometry")["service_name"] - .apply(lambda x: "; ".join([val for val in x if val is not None])) - .reset_index() - ) - - l_and_i_complaints.rebuild_gdf() - - # rename the column to 'li_complaints' - l_and_i_complaints.gdf.rename( - columns={"service_name": "li_complaints"}, inplace=True - ) - - # Load data for violations from L&I - l_and_i_violations: FeatureLayer = FeatureLayer( - name="LI Violations", - carto_sql_queries=VIOLATIONS_SQL_QUERY, - from_xy=True - ) - - # Filter for rows where 'casetype' contains any of the keywords, handling NaN values - l_and_i_violations.gdf = l_and_i_violations.gdf[ - l_and_i_violations.gdf["violationcodetitle"].fillna('').str.lower().str.contains('|'.join(keywords)) - ] - - all_violations_count_df: pd.DataFrame = ( - l_and_i_violations.gdf.groupby("opa_account_num") - .count() - .reset_index()[["opa_account_num", "violationnumber", "geometry"]] - ) - all_violations_count_df = all_violations_count_df.rename( - columns={"violationnumber": "all_violations_past_year"} - ) - # filter for only cases where the casestatus is 'IN VIOLATION' or 'UNDER INVESTIGATION' - violations_gdf: gpd.GeoDataFrame = l_and_i_violations.gdf[ - (l_and_i_violations.gdf["violationstatus"].str.lower() == "open") - ] - - open_violations_count_df: pd.DataFrame = ( - violations_gdf.groupby("opa_account_num") - .count() - .reset_index()[["opa_account_num", "violationnumber", "geometry"]] - ) - open_violations_count_df = open_violations_count_df.rename( - columns={"violationnumber": "open_violations_past_year"} - ) - # join the all_violations_count_df and open_violations_count_df dataframes on opa_account_num - violations_count_gdf: gpd.GeoDataFrame = all_violations_count_df.merge( - open_violations_count_df, how="left", on="opa_account_num" - ) - - # replace NaN values with 0 - violations_count_gdf.fillna(0, inplace=True) - - # convert the all_violations_past_year and open_violations_past_year columns to integers - violations_count_gdf["all_violations_past_year"] = violations_count_gdf[ - "all_violations_past_year" - ].astype(int) - violations_count_gdf["open_violations_past_year"] = violations_count_gdf[ - "open_violations_past_year" - ].astype(int) - violations_count_gdf = violations_count_gdf[ - ["opa_account_num", "all_violations_past_year", "open_violations_past_year"] - ] - - # collapse violations_gdf by address and concatenate the violationcodetitle values into a list with a semicolon separator - l_and_i_violations.gdf = ( - l_and_i_violations.gdf.groupby("geometry")["violationcodetitle"] - .apply(lambda x: "; ".join([val for val in x if val is not None])) - .reset_index() - ) - l_and_i_complaints.rebuild_gdf() - - # rename the column to 'li_violations' - l_and_i_violations.gdf.rename( - columns={"violationcodetitle": "li_code_violations"}, inplace=True - ) - - # Violations can work with an OPA join - primary_featurelayer.opa_join( - violations_count_gdf, - "opa_account_num", - ) - - # Complaints need a spatial join, but we need to take special care to merge on just the parcel geoms first to get opa_id - complaints_with_opa_id: gpd.GeoDataFrame = primary_featurelayer.gdf.sjoin( - l_and_i_complaints.gdf, how="left", predicate="contains" - ) - complaints_with_opa_id.drop(columns=["index_right"], inplace=True) - - # Concatenate the complaints values into a list with a semicolon separator by opa_id - complaints_with_opa_id = ( - complaints_with_opa_id.groupby("opa_id")["li_complaints"] - .apply(lambda x: "; ".join([str(val) for val in x if val is not None])) - .reset_index()[["opa_id", "li_complaints"]] - ) - - # Clean up the NaN values in the li_complaints column - def remove_nan_strings(x: str) -> str | None: - """ - Remove 'nan' strings from the input. - - Args: - x (str): Input string. - - Returns: - str | None: Cleaned string or None if only 'nan' values. - """ - if x == "nan" or ("nan;" in x): - return None - else: - return x - - complaints_with_opa_id["li_complaints"] = complaints_with_opa_id[ - "li_complaints" - ].apply(remove_nan_strings) - - # Merge the complaints values back into the primary_featurelayer - primary_featurelayer.opa_join( - complaints_with_opa_id, - "opa_id", - ) - - primary_featurelayer.gdf[ - ["all_violations_past_year", "open_violations_past_year"] - ] = ( - primary_featurelayer.gdf[ - ["all_violations_past_year", "open_violations_past_year"] - ] - .apply(lambda x: pd.to_numeric(x, errors="coerce")) - .fillna(0) - .astype(int) - ) - - return primary_featurelayer \ No newline at end of file diff --git a/data/src/data_utils/nbhoods.py b/data/src/data_utils/nbhoods.py deleted file mode 100644 index 6fde4bd0..00000000 --- a/data/src/data_utils/nbhoods.py +++ /dev/null @@ -1,25 +0,0 @@ -import geopandas as gpd -from classes.featurelayer import FeatureLayer -from constants.services import NBHOODS_URL - -from config.config import USE_CRS - - -def nbhoods(primary_featurelayer): - phl_nbhoods = gpd.read_file(NBHOODS_URL) - - # Correct the column name to uppercase if needed - if 'MAPNAME' in phl_nbhoods.columns: - phl_nbhoods.rename(columns={"MAPNAME": "neighborhood"}, inplace=True) - - phl_nbhoods = phl_nbhoods.to_crs(USE_CRS) - - nbhoods = FeatureLayer("Neighborhoods") - nbhoods.gdf = phl_nbhoods - - red_cols_to_keep = ["neighborhood", "geometry"] - nbhoods.gdf = nbhoods.gdf[red_cols_to_keep] - - primary_featurelayer.spatial_join(nbhoods) - - return primary_featurelayer diff --git a/data/src/data_utils/negligent_devs.py b/data/src/data_utils/negligent_devs.py deleted file mode 100644 index aa95532c..00000000 --- a/data/src/data_utils/negligent_devs.py +++ /dev/null @@ -1,166 +0,0 @@ -import re - -import pandas as pd - -replacements = { - "STREET": "ST", - "AVENUE": "AVE", - "ROAD": "RD", - "BOULEVARD": "BLVD", - "PLACE": "PL", - "FLOOR": "FL", - "FLR": "FL", - "FIRST": "1ST", - "SECOND": "2ND", - "THIRD": "3RD", - "FOURTH": "4TH", - "FIFTH": "5TH", - "SIXTH": "6TH", - "SEVENTH": "7TH", - "EIGHTH": "8TH", - "NINTH": "9TH", - "NORTH": "N", - "SOUTH": "S", - "EAST": "E", - "WEST": "W", - "SUITE": "STE", - "LA": "LN", - "LANE": "LN", - "PARKWAY": "PKY", -} - - -def standardize_street(street): - if not isinstance(street, str): - return "" - for full, abbr in replacements.items(): - street = re.sub(r"\b{}\b".format(full), abbr, street, flags=re.IGNORECASE) - return street - - -def create_standardized_address(row): - parts = [ - row["mailing_address_1"].strip() - if pd.notnull(row["mailing_address_1"]) - else "", - row["mailing_address_2"].strip() - if pd.notnull(row["mailing_address_2"]) - else "", - row["mailing_street"].strip() if pd.notnull(row["mailing_street"]) else "", - row["mailing_city_state"].strip() - if pd.notnull(row["mailing_city_state"]) - else "", - row["mailing_zip"].strip() if pd.notnull(row["mailing_zip"]) else "", - ] - standardized_address = ", ".join([part for part in parts if part]) - return standardized_address.lower() - - -def negligent_devs(primary_featurelayer): - devs = primary_featurelayer.gdf - - print("Columns in 'devs' DataFrame:", devs.columns) - - print("Initial properties data:") - print(devs[['opa_id', 'city_owner_agency', 'mailing_street']].head(10)) - - city_owners = devs.loc[~devs["city_owner_agency"].isna() & (devs["city_owner_agency"] != "")].copy() - non_city_owners = devs.loc[devs["city_owner_agency"].isna() | (devs["city_owner_agency"] == "")].copy() - - print(f"City owners shape: {city_owners.shape}, Non-city owners shape: {non_city_owners.shape}") - - # Log before standardizing addresses - print("Non-city owners mailing streets before standardization:") - print(non_city_owners[['opa_id', 'mailing_street']].head(10)) - - non_city_owners.loc[:, "mailing_street"] = ( - non_city_owners["mailing_street"].astype(str).apply(standardize_street) - ) - - print("Non-city owners mailing streets after standardization:") - print(non_city_owners[['opa_id', 'mailing_street']].head(10)) - - for term in ["ST", "AVE", "RD", "BLVD"]: - non_city_owners.loc[:, "mailing_street"] = non_city_owners[ - "mailing_street" - ].replace(regex={f"{term}.*": term}) - - # Log after applying term replacement - print("Non-city owners mailing streets after term replacement:") - print(non_city_owners[['opa_id', 'mailing_street']].head(10)) - - # Fill missing address components - non_city_owners.loc[:, "mailing_address_1"] = non_city_owners[ - "mailing_address_1" - ].fillna("") - non_city_owners.loc[:, "mailing_address_2"] = non_city_owners[ - "mailing_address_2" - ].fillna("") - non_city_owners.loc[:, "mailing_street"] = non_city_owners["mailing_street"].fillna( - "" - ) - non_city_owners.loc[:, "mailing_city_state"] = non_city_owners[ - "mailing_city_state" - ].fillna("") - non_city_owners.loc[:, "mailing_zip"] = non_city_owners["mailing_zip"].fillna("") - - # Log addresses before creating standardized address - print("Non-city owners mailing details before creating standardized address:") - print(non_city_owners[['opa_id', 'mailing_street', 'mailing_city_state', 'mailing_zip']].head(10)) - - non_city_owners.loc[:, "standardized_address"] = non_city_owners.apply( - create_standardized_address, axis=1 - ) - - # Log standardized addresses and counts - print("Standardized addresses with counts:") - address_counts = ( - non_city_owners.groupby("standardized_address") - .size() - .reset_index(name="property_count") - ) - print(address_counts.head(10)) - - sorted_address_counts = address_counts.sort_values( - by="property_count", ascending=False - ) - print("Top standardized addresses by property count:") - print(sorted_address_counts.head(10)) - - non_city_owners = non_city_owners.merge( - sorted_address_counts, on="standardized_address", how="left" - ) - - # Log merged data for city owners - city_owner_counts = ( - city_owners.groupby("city_owner_agency") - .size() - .reset_index(name="property_count") - ) - print("City owner counts:") - print(city_owner_counts.head(10)) - - city_owners = city_owners.merge( - city_owner_counts, on="city_owner_agency", how="left" - ) - - devs_combined = pd.concat([city_owners, non_city_owners], axis=0) - - # Final check on the merged data before updating primary_featurelayer - print("Combined data with property counts:") - print(devs_combined[['opa_id', 'property_count']].head(10)) - - primary_featurelayer.gdf = primary_featurelayer.gdf.merge( - devs_combined[["opa_id", "property_count"]], on="opa_id", how="left" - ) - primary_featurelayer.gdf.rename( - columns={"property_count": "n_properties_owned"}, inplace=True - ) - primary_featurelayer.gdf.loc[:, "negligent_dev"] = ( - primary_featurelayer.gdf["n_properties_owned"] > 5 - ) & (primary_featurelayer.gdf["city_owner_agency"].isna() | (primary_featurelayer.gdf["city_owner_agency"] == "")) - - print("Final feature layer data with negligent_dev flag:") - print(primary_featurelayer.gdf[['opa_id', 'n_properties_owned', 'negligent_dev']].head(10)) - - return primary_featurelayer diff --git a/data/src/data_utils/opa_properties.py b/data/src/data_utils/opa_properties.py deleted file mode 100644 index 2d02f42f..00000000 --- a/data/src/data_utils/opa_properties.py +++ /dev/null @@ -1,29 +0,0 @@ -from classes.featurelayer import FeatureLayer -from constants.services import OPA_PROPERTIES_QUERY - - -def opa_properties(primary_featurelayer): - opa = FeatureLayer( - name="OPA Properties", - carto_sql_queries=OPA_PROPERTIES_QUERY, - use_wkb_geom_field="the_geom", - cols=[ - "market_value", - "sale_date", - "sale_price", - "parcel_number", - "mailing_address_1", - "mailing_address_2", - "mailing_care_of", - "mailing_city_state", - "mailing_street", - "mailing_zip" - ] - ) - - primary_featurelayer.opa_join( - opa.gdf, - "parcel_number", - ) - - return primary_featurelayer diff --git a/data/src/data_utils/owner_type.py b/data/src/data_utils/owner_type.py deleted file mode 100644 index 291364df..00000000 --- a/data/src/data_utils/owner_type.py +++ /dev/null @@ -1,37 +0,0 @@ -import pandas as pd -from classes.featurelayer import FeatureLayer - -def owner_type(primary_featurelayer: FeatureLayer) -> FeatureLayer: - """ - Determines the ownership type for each property in the primary feature layer based on - the 'owner_1', 'owner_2', and 'city_owner_agency' columns. The ownership type is set as: - - "Public" if 'city_owner_agency' is not NA. - - "Business (LLC)" if 'city_owner_agency' is NA and "LLC" is found in 'owner_1' or 'owner_2'. - - "Individual" if 'city_owner_agency' is NA and "LLC" is not found in 'owner_1' or 'owner_2'. - - Args: - primary_featurelayer (FeatureLayer): The feature layer containing property ownership data. - - Returns: - FeatureLayer: The updated feature layer with the 'owner_type' column added. - """ - owner_types = [] - - for _, row in primary_featurelayer.gdf.iterrows(): - # Extract owner1, owner2, and city_owner_agency - owner1 = str(row["owner_1"]).lower() - owner2 = str(row["owner_2"]).lower() - city_owner_agency = row["city_owner_agency"] - - # Determine ownership type based on the conditions - if pd.notna(city_owner_agency): - owner_types.append("Public") - elif " llc" in owner1 or " llc" in owner2: - owner_types.append("Business (LLC)") - else: - owner_types.append("Individual") - - # Add the 'owner_type' column to the GeoDataFrame - primary_featurelayer.gdf["owner_type"] = owner_types - - return primary_featurelayer diff --git a/data/src/data_utils/park_priority.py b/data/src/data_utils/park_priority.py deleted file mode 100644 index 7a97fb3b..00000000 --- a/data/src/data_utils/park_priority.py +++ /dev/null @@ -1,135 +0,0 @@ -import os -import zipfile -from io import BytesIO -from typing import List, Union - -import geopandas as gpd -import requests -from bs4 import BeautifulSoup -from classes.featurelayer import FeatureLayer -from config.config import USE_CRS -from tqdm import tqdm -import pyogrio - - -def get_latest_shapefile_url() -> str: - """ - Scrapes the TPL website to get the URL of the latest shapefile. - - Returns: - str: The URL of the latest shapefile. - - Raises: - ValueError: If the shapefile link is not found on the page. - """ - url: str = "https://www.tpl.org/park-data-downloads" - response: requests.Response = requests.get(url) - soup: BeautifulSoup = BeautifulSoup(response.content, "html.parser") - - shapefile_link: Union[BeautifulSoup, None] = soup.find("a", string="Shapefile") - if shapefile_link: - return str(shapefile_link["href"]) - else: - raise ValueError("Shapefile link not found on the page") - - -def download_and_process_shapefile( - geojson_path: str, park_url: str, target_files: List[str], file_name_prefix: str -) -> gpd.GeoDataFrame: - """ - Downloads and processes the shapefile to create a GeoDataFrame for Philadelphia parks. - - Args: - geojson_path (str): Path to save the GeoJSON file. - park_url (str): URL to download the shapefile. - target_files (List[str]): List of files to extract from the shapefile. - file_name_prefix (str): Prefix for the file names to be extracted. - - Returns: - gpd.GeoDataFrame: GeoDataFrame containing the processed park data. - """ - print("Downloading and processing park priority data...") - response: requests.Response = requests.get(park_url, stream=True) - total_size: int = int(response.headers.get("content-length", 0)) - - with tqdm( - total=total_size, unit="iB", unit_scale=True, desc="Downloading" - ) as progress_bar: - buffer: BytesIO = BytesIO() - for data in response.iter_content(1024): - size: int = buffer.write(data) - progress_bar.update(size) - - with zipfile.ZipFile(buffer) as zip_ref: - for file_name in tqdm(target_files, desc="Extracting"): - zip_ref.extract(file_name, "tmp/") - - print("Processing shapefile...") - pa_parks: gpd.GeoDataFrame = gpd.read_file( - "tmp/" + file_name_prefix + "_ParkPriorityAreas.shp" - ) - pa_parks = pa_parks.to_crs(USE_CRS) - - phl_parks: gpd.GeoDataFrame = pa_parks[pa_parks["ID"].str.startswith("42101")] - phl_parks = phl_parks.loc[:, ["ParkNeed", "geometry"]] - - if isinstance(phl_parks, gpd.GeoDataFrame): - phl_parks.rename(columns={"ParkNeed": "park_priority"}, inplace=True) - else: - raise TypeError("Expected a GeoDataFrame, got Series or another type instead") - - print(f"Writing filtered data to GeoJSON: {geojson_path}") - phl_parks.to_file(geojson_path, driver="GeoJSON") - - return phl_parks - - -def park_priority(primary_featurelayer: FeatureLayer) -> FeatureLayer: - """ - Downloads and processes park priority data, then joins it with the primary feature layer. - - Args: - primary_featurelayer (FeatureLayer): The primary feature layer to join with park priority data. - - Returns: - FeatureLayer: The primary feature layer with park priority data joined. - """ - park_url: str = get_latest_shapefile_url() - print(f"Downloading park priority data from: {park_url}") - - file_name_prefix: str = "Parkserve" - target_files: List[str] = [ - file_name_prefix + "_ParkPriorityAreas.shp", - file_name_prefix + "_ParkPriorityAreas.dbf", - file_name_prefix + "_ParkPriorityAreas.shx", - file_name_prefix + "_ParkPriorityAreas.prj", - file_name_prefix + "_ParkPriorityAreas.CPG", - file_name_prefix + "_ParkPriorityAreas.sbn", - file_name_prefix + "_ParkPriorityAreas.sbx", - ] - geojson_path: str = "tmp/phl_parks.geojson" - - os.makedirs("tmp/", exist_ok=True) - - try: - if os.path.exists(geojson_path): - print(f"GeoJSON file already exists, loading from {geojson_path}") - phl_parks: gpd.GeoDataFrame = gpd.read_file(geojson_path) - else: - raise pyogrio.errors.DataSourceError( - "GeoJSON file missing, forcing download." - ) - - except (pyogrio.errors.DataSourceError, ValueError) as e: - print(f"Error loading GeoJSON: {e}. Re-downloading and processing shapefile.") - if os.path.exists(geojson_path): - os.remove(geojson_path) # Delete the corrupted GeoJSON if it exists - phl_parks = download_and_process_shapefile( - geojson_path, park_url, target_files, file_name_prefix - ) - - park_priority_layer: FeatureLayer = FeatureLayer("Park Priority") - park_priority_layer.gdf = phl_parks - - primary_featurelayer.spatial_join(park_priority_layer) - return primary_featurelayer diff --git a/data/src/data_utils/phs_properties.py b/data/src/data_utils/phs_properties.py deleted file mode 100644 index c906c2d1..00000000 --- a/data/src/data_utils/phs_properties.py +++ /dev/null @@ -1,33 +0,0 @@ -from classes.featurelayer import FeatureLayer -from constants.services import PHS_LAYERS_TO_LOAD - -def phs_properties(primary_featurelayer: FeatureLayer) -> FeatureLayer: - """ - Perform a spatial join between the primary feature layer and the PHS properties layer, - then update the primary feature layer with a new column 'phs_care_program' indicating - if the property is part of the PHS care program. - - Args: - primary_featurelayer (FeatureLayer): The primary feature layer to join with the PHS properties layer. - - Returns: - FeatureLayer: The updated primary feature layer with the 'phs_care_program' column. - """ - - phs_properties = FeatureLayer( - name="PHS Properties", esri_rest_urls=PHS_LAYERS_TO_LOAD, cols=["program"] - ) - - # Perform spatial join between primary feature layer and PHS properties - primary_featurelayer.spatial_join(phs_properties) - - # Initialize 'phs_care_program' column with default "no" for all rows - primary_featurelayer.gdf["phs_care_program"] = "No" - - # Set 'phs_care_program' to "yes" for matched rows - primary_featurelayer.gdf.loc[primary_featurelayer.gdf["program"].notna(), "phs_care_program"] = "Yes" - - # Rebuild the GeoDataFrame after updates - primary_featurelayer.rebuild_gdf() - - return primary_featurelayer diff --git a/data/src/data_utils/ppr_properties.py b/data/src/data_utils/ppr_properties.py deleted file mode 100644 index 48111b35..00000000 --- a/data/src/data_utils/ppr_properties.py +++ /dev/null @@ -1,53 +0,0 @@ -import io - -import geopandas as gpd -import requests -from classes.featurelayer import FeatureLayer -from constants.services import PPR_PROPERTIES_TO_LOAD - -from config.config import USE_CRS - - -def ppr_properties(primary_featurelayer): - fallback_url = 'https://opendata.arcgis.com/datasets/d52445160ab14380a673e5849203eb64_0.geojson' - - try: - - ppr_properties = FeatureLayer( - name="PPR Properties", - esri_rest_urls=PPR_PROPERTIES_TO_LOAD, - cols=["PUBLIC_NAME"] - ) - - if ppr_properties.gdf is None or ppr_properties.gdf.empty: - raise ValueError("PPR properties GeoDataFrame is empty or failed to load from Esri REST URL.") - - print("Loaded PPR properties from Esri REST URL.") - - except Exception as e: - print(f"Error loading PPR properties from Esri REST URL: {e}") - print("Falling back to loading from GeoJSON URL.") - - response = requests.get(fallback_url) - response.raise_for_status() - ppr_properties_gdf = gpd.read_file(io.BytesIO(response.content)) - - ppr_properties = FeatureLayer(name="PPR Properties") - ppr_properties.gdf = ppr_properties_gdf - - ppr_properties.gdf = ppr_properties.gdf[["public_name", "geometry"]] - - ppr_properties.gdf = ppr_properties.gdf.to_crs(USE_CRS) - - primary_featurelayer.spatial_join(ppr_properties) - - mask = primary_featurelayer.gdf["public_name"].notnull() - - count_dropped = mask.sum() - print(f"Number of PPR properties being dropped: {count_dropped}") - - primary_featurelayer.gdf = primary_featurelayer.gdf.drop(primary_featurelayer.gdf[mask].index) - - primary_featurelayer.gdf = primary_featurelayer.gdf.drop(columns=["public_name"]) - - return primary_featurelayer \ No newline at end of file diff --git a/data/src/data_utils/priority_level.py b/data/src/data_utils/priority_level.py deleted file mode 100644 index 33097de3..00000000 --- a/data/src/data_utils/priority_level.py +++ /dev/null @@ -1,51 +0,0 @@ -def priority_level(dataset): - priority_levels = [] - for idx, row in dataset.gdf.iterrows(): - priority_level = "" - - # Decision Points - guncrime_density_percentile = row["gun_crimes_density_percentile"] - in_phs_landcare = row["phs_care_program"] == "yes" - has_li_complaint_or_violation = ( - row["li_complaints"] is not None - and float(row["all_violations_past_year"]) > 0 - ) - very_low_tree_canopy = row["tree_canopy_gap"] >= 0.3 - - # Updated logic based on percentile values - if guncrime_density_percentile <= 50: - # Low Gun Crime Density (Bottom 50%) - priority_level = "Low" - - elif guncrime_density_percentile > 75: - # High Gun Crime Density (Top 25%) - - if has_li_complaint_or_violation: - priority_level = "High" - else: - if in_phs_landcare: - if very_low_tree_canopy: - priority_level = "High" - else: - priority_level = "Medium" - else: - priority_level = "High" - - else: - # Medium Gun Crime Density (Between 50% and 75%) - if has_li_complaint_or_violation: - if in_phs_landcare: - priority_level = "Medium" - else: - if very_low_tree_canopy: - priority_level = "High" - else: - priority_level = "Medium" - else: - priority_level = "Low" - - priority_levels.append(priority_level) - - dataset.gdf["priority_level"] = priority_levels - - return dataset diff --git a/data/src/data_utils/rco_geoms.py b/data/src/data_utils/rco_geoms.py deleted file mode 100644 index 6aa3dca6..00000000 --- a/data/src/data_utils/rco_geoms.py +++ /dev/null @@ -1,57 +0,0 @@ -from classes.featurelayer import FeatureLayer -from constants.services import RCOS_LAYERS_TO_LOAD -import pandas as pd - -pd.set_option("future.no_silent_downcasting", True) - - -def rco_geoms(primary_featurelayer): - rco_geoms = FeatureLayer(name="RCOs", esri_rest_urls=RCOS_LAYERS_TO_LOAD) - - rco_aggregate_cols = [ - "ORGANIZATION_NAME", - "ORGANIZATION_ADDRESS", - "PRIMARY_EMAIL", - "PRIMARY_PHONE", - ] - - rco_use_cols = ["rco_info", "rco_names", "geometry"] - - rco_geoms.gdf.loc[:, "rco_info"] = rco_geoms.gdf[rco_aggregate_cols].apply( - lambda x: "; ".join(map(str, x)), axis=1 - ) - - rco_geoms.gdf.loc[:, "rco_names"] = rco_geoms.gdf["ORGANIZATION_NAME"] - - rco_geoms.gdf = rco_geoms.gdf.loc[:, rco_use_cols].copy() - rco_geoms.rebuild_gdf() - - primary_featurelayer.spatial_join(rco_geoms) - - # Collapse columns and aggregate rco_info - group_columns = [ - col for col in primary_featurelayer.gdf.columns if col not in rco_use_cols - ] - - for col in group_columns: - # Use .infer_objects() after fillna() to fix the warning - primary_featurelayer.gdf.loc[:, col] = ( - primary_featurelayer.gdf[col].fillna("").infer_objects(copy=False) - ) - - primary_featurelayer.gdf = ( - primary_featurelayer.gdf.groupby(group_columns) - .agg( - { - "rco_info": lambda x: "|".join(map(str, x)), - "rco_names": lambda x: "|".join(map(str, x)), - "geometry": "first", - } - ) - .reset_index() - ) - - primary_featurelayer.gdf.drop_duplicates(inplace=True) - primary_featurelayer.rebuild_gdf() - - return primary_featurelayer diff --git a/data/src/data_utils/tactical_urbanism.py b/data/src/data_utils/tactical_urbanism.py deleted file mode 100644 index df15a0f2..00000000 --- a/data/src/data_utils/tactical_urbanism.py +++ /dev/null @@ -1,25 +0,0 @@ -def tactical_urbanism(dataset): - unsafe_words = [ - "dangerous", - ] - - tactical_urbanism_values = [] - - for idx, row in dataset.gdf.iterrows(): - li_complaints_lower = str(row["li_complaints"]).lower().split(" ") - contains_unsafe_word = any(word in li_complaints_lower for word in unsafe_words) - - if ( - row["parcel_type"] == "Land" - and row["unsafe_building"] == "N" - and row["imm_dang_building"] == "N" - and not contains_unsafe_word - ): - tactical_urbanism = "Yes" - else: - tactical_urbanism = "No" - - tactical_urbanism_values.append(tactical_urbanism) - - dataset.gdf["tactical_urbanism"] = tactical_urbanism_values - return dataset diff --git a/data/src/data_utils/tree_canopy.py b/data/src/data_utils/tree_canopy.py deleted file mode 100644 index bc133893..00000000 --- a/data/src/data_utils/tree_canopy.py +++ /dev/null @@ -1,32 +0,0 @@ -import requests -import io -import zipfile -import geopandas as gpd -from classes.featurelayer import FeatureLayer -from config.config import USE_CRS - - -def tree_canopy(primary_featurelayer): - tree_url = ( - "https://national-tes-data-share.s3.amazonaws.com/national_tes_share/pa.zip.zip" - ) - - tree_response = requests.get(tree_url) - - with io.BytesIO(tree_response.content) as f: - with zipfile.ZipFile(f, "r") as zip_ref: - zip_ref.extractall("tmp/") - - pa_trees = gpd.read_file("tmp/pa.shp") - pa_trees = pa_trees.to_crs(USE_CRS) - phl_trees = pa_trees[pa_trees["county"] == "Philadelphia County"] - phl_trees = phl_trees[["tc_gap", "geometry"]] - - phl_trees.rename(columns={"tc_gap": "tree_canopy_gap"}, inplace=True) - - tree_canopy = FeatureLayer("Tree Canopy") - tree_canopy.gdf = phl_trees - - primary_featurelayer.spatial_join(tree_canopy) - - return primary_featurelayer diff --git a/data/src/data_utils/unsafe_buildings.py b/data/src/data_utils/unsafe_buildings.py deleted file mode 100644 index b44edd00..00000000 --- a/data/src/data_utils/unsafe_buildings.py +++ /dev/null @@ -1,28 +0,0 @@ -from classes.featurelayer import FeatureLayer -from constants.services import UNSAFE_BUILDINGS_QUERY - - -def unsafe_buildings(primary_featurelayer): - unsafe_buildings = FeatureLayer( - name="Unsafe Buildings", - carto_sql_queries=UNSAFE_BUILDINGS_QUERY, - use_wkb_geom_field="the_geom", - cols=["opa_account_num"], - ) - - unsafe_buildings.gdf.loc[:, "unsafe_building"] = "Y" - - unsafe_buildings.gdf = unsafe_buildings.gdf.rename( - columns={"opa_account_num": "opa_number"} - ) - - primary_featurelayer.opa_join( - unsafe_buildings.gdf, - "opa_number", - ) - - primary_featurelayer.gdf.loc[:, "unsafe_building"] = primary_featurelayer.gdf[ - "unsafe_building" - ].fillna("N") - - return primary_featurelayer diff --git a/data/src/data_utils/utils.py b/data/src/data_utils/utils.py deleted file mode 100644 index b7b9ef4e..00000000 --- a/data/src/data_utils/utils.py +++ /dev/null @@ -1,42 +0,0 @@ -import os -import re - -import requests - - -def mask_password(value: str): - """remove the password from this postgresql connect string so we don't write it to logs, etc. - - Args: - value (str): the unmasked string containing one or more postgres connect string. - - Returns: - _type_: the string with the password replaced by MASKED - """ - return re.sub(":\w+@", ":MASKED@", value) - - -def save_stream_url(url: str) -> str: - """download the file from this url to the tmp/ directory by streaming in a memory-friendly way. - If local file already exists, use it and don't download. - Args: - url (str): the url of the zip file - - Returns: - str: the relative local path of the saved zip file - """ - local_filename = "tmp/" + url.split('/')[-1] - if os.path.exists(local_filename): - return local_filename - - with requests.get(url, stream=True) as r: - r.raise_for_status() - with open(local_filename, 'wb') as f: - for chunk in r.iter_content(chunk_size=8192): - # If you have chunk encoded response uncomment if - # and set chunk_size parameter to None. - #if chunk: - f.write(chunk) - f.close() - r.close() - return local_filename diff --git a/data/src/data_utils/vacant_properties.py b/data/src/data_utils/vacant_properties.py deleted file mode 100644 index d6573218..00000000 --- a/data/src/data_utils/vacant_properties.py +++ /dev/null @@ -1,186 +0,0 @@ -from classes.featurelayer import FeatureLayer, google_cloud_bucket -from constants.services import VACANT_PROPS_LAYERS_TO_LOAD -import geopandas as gpd -from config.config import USE_CRS -from io import BytesIO - -import pandas as pd - - -def load_backup_data_from_gcs(file_name: str) -> gpd.GeoDataFrame: - bucket = google_cloud_bucket() - blob = bucket.blob(file_name) - if not blob.exists(): - raise FileNotFoundError(f"File {file_name} not found in the GCS bucket.") - - file_bytes = blob.download_as_bytes() - try: - gdf = gpd.read_file(BytesIO(file_bytes)) - except Exception as e: - raise ValueError(f"Error reading GeoJSON file: {e}") - - print("Loaded backup data from GCS.") - - # Ensure column names are consistent - gdf = gdf.rename( - columns={ - "ADDRESS": "address", - "OWNER1": "owner_1", - "OWNER2": "owner_2", - "BLDG_DESC": "building_description", - "CouncilDistrict": "council_district", - "ZoningBaseDistrict": "zoning_base_district", - "ZipCode": "zipcode", - "OPA_ID": "opa_id", - } - ) - - return gdf - - -def check_null_percentage(df: pd.DataFrame, threshold: float = 0.05): - """Checks if any column in the dataframe has more than the given threshold of null values.""" - null_percentages = df.isnull().mean() - for col, pct in null_percentages.items(): - if col not in ["owner1", "owner2"] and pct > threshold: - raise ValueError( - f"Column '{col}' has more than {threshold * 100}% null values ({pct * 100}%)." - ) - - -def vacant_properties() -> FeatureLayer: - vacant_properties = FeatureLayer( - name="Vacant Properties", - esri_rest_urls=VACANT_PROPS_LAYERS_TO_LOAD, - cols=[ - "ADDRESS", - "OWNER1", - "OWNER2", - "BLDG_DESC", - "COUNCILDISTRICT", - "ZONINGBASEDISTRICT", - "ZIPCODE", - "OPA_ID", - "parcel_type", - ], - ) - - # Rename columns for consistency in the original data - vacant_properties.gdf = vacant_properties.gdf.rename( - columns={ - "ADDRESS": "address", - "OWNER1": "owner_1", - "OWNER2": "owner_2", - "BLDG_DESC": "building_description", - "COUNCILDISTRICT": "council_district", - "ZONINGBASEDISTRICT": "zoning_base_district", - "ZIPCODE": "zipcode", - "OPA_ID": "opa_id", - } - ) - - vacant_land_gdf = vacant_properties.gdf[ - vacant_properties.gdf["parcel_type"] == "Land" - ] - print(f"Vacant land data size: {len(vacant_land_gdf)} rows.") - - if len(vacant_land_gdf) < 20000: - print("Vacant land data is below the threshold. Loading backup data from GCS.") - backup_gdf = load_backup_data_from_gcs("vacant_indicators_land_06_2024.geojson") - - # Ensure CRS is consistent with project-wide CRS (USE_CRS) - if backup_gdf.crs != USE_CRS: - print(f"Reprojecting backup data from {backup_gdf.crs} to {USE_CRS}") - backup_gdf = backup_gdf.to_crs(USE_CRS) - - # Ensure CRS is the same - if backup_gdf.crs != vacant_properties.gdf.crs: - backup_gdf = backup_gdf.to_crs(vacant_properties.gdf.crs) - - # Map backup dataset column names to match the original dataset - backup_gdf = backup_gdf.rename( - columns={ - "owner_1": "owner1", - "owner_2": "owner2", - "building_description": "bldg_desc", - "council_district": "councildistrict", - "zoning_base_district": "zoningbasedistrict", - } - ) - - # Set parcel_type to "Land" for backup data - backup_gdf["parcel_type"] = "Land" - - # Select only the columns present in the original dataset - backup_gdf = backup_gdf[vacant_properties.gdf.columns] - - # Ensure all necessary columns are present in backup data - for col in vacant_properties.gdf.columns: - if col not in backup_gdf.columns: - backup_gdf[col] = None - - # Check for column mismatches between original and backup datasets - for col in vacant_properties.gdf.columns: - if vacant_properties.gdf[col].dtype != backup_gdf[col].dtype: - print( - f"Warning: Data type mismatch in column '{col}'. Original: {vacant_properties.gdf[col].dtype}, Backup: {backup_gdf[col].dtype}" - ) - - # Verify if backup data contains more than expected null values - check_null_percentage(backup_gdf) - - # Remove existing Land data - vacant_properties.gdf = vacant_properties.gdf[ - vacant_properties.gdf["parcel_type"] != "Land" - ] - - # Concatenate the backup data with the existing data - print(f"Appending backup data ({len(backup_gdf)} rows) to the existing data.") - vacant_properties.gdf = pd.concat( - [vacant_properties.gdf, backup_gdf], ignore_index=True - ) - - # Ensure concatenated data is still a GeoDataFrame - vacant_properties.gdf = gpd.GeoDataFrame( - vacant_properties.gdf, geometry="geometry" - ) - - vacant_properties.gdf.dropna(subset=["opa_id"], inplace=True) - - # Final null value check before returning - check_null_percentage(vacant_properties.gdf) - - # Final column renaming and selection - vacant_properties.gdf = vacant_properties.gdf.rename( - columns={ - "owner1": "owner_1", - "owner2": "owner_2", - "councildistrict": "council_district", - "zoningbasedistrict": "zoning_base_district", - } - ) - - # Select only the final columns needed - final_columns = [ - "address", - "owner_1", - "owner_2", - "council_district", - "zoning_base_district", - "zipcode", - "opa_id", - "parcel_type", - "geometry", - ] - - vacant_properties.gdf = vacant_properties.gdf[final_columns] - - # Ensure concatenated data is still a GeoDataFrame - vacant_properties.gdf = gpd.GeoDataFrame(vacant_properties.gdf, geometry="geometry") - - before_drop = vacant_properties.gdf.shape[0] - vacant_properties.gdf = vacant_properties.gdf.drop_duplicates(subset="opa_id") - after_drop = vacant_properties.gdf.shape[0] - print(f"Duplicate vacant properties dropped: {before_drop - after_drop}") - - return vacant_properties diff --git a/data/src/script.py b/data/src/script.py deleted file mode 100644 index cf42ace6..00000000 --- a/data/src/script.py +++ /dev/null @@ -1,147 +0,0 @@ -import sys -import time - -from classes.backup_archive_database import BackupArchiveDatabase -from classes.diff_report import DiffReport -from config.config import FORCE_RELOAD, tiles_file_id_prefix -from config.psql import conn -from data_utils.access_process import access_process -from data_utils.city_owned_properties import city_owned_properties -from data_utils.community_gardens import community_gardens -from data_utils.conservatorship import conservatorship -from data_utils.contig_neighbors import contig_neighbors -from data_utils.deliquencies import deliquencies -from data_utils.dev_probability import dev_probability -from data_utils.drug_crimes import drug_crimes -from data_utils.gun_crimes import gun_crimes -from data_utils.imm_dang_buildings import imm_dang_buildings -from data_utils.l_and_i import l_and_i -from data_utils.owner_type import owner_type -from data_utils.nbhoods import nbhoods -from data_utils.negligent_devs import negligent_devs -from data_utils.opa_properties import opa_properties -from data_utils.park_priority import park_priority -from data_utils.phs_properties import phs_properties -from data_utils.ppr_properties import ppr_properties -from data_utils.priority_level import priority_level -from data_utils.rco_geoms import rco_geoms -from data_utils.tactical_urbanism import tactical_urbanism -from data_utils.tree_canopy import tree_canopy -from data_utils.unsafe_buildings import unsafe_buildings -from data_utils.vacant_properties import vacant_properties - -import traceback - -from classes.slack_error_reporter import send_error_to_slack - -# Ensure the directory containing awkde is in the Python path -awkde_path = "/usr/src/app" -if awkde_path not in sys.path: - sys.path.append(awkde_path) - -try: - services = [ - city_owned_properties, - phs_properties, - l_and_i, - rco_geoms, - tree_canopy, - nbhoods, - gun_crimes, - drug_crimes, - deliquencies, - opa_properties, - unsafe_buildings, - imm_dang_buildings, - tactical_urbanism, - conservatorship, - owner_type, - community_gardens, - park_priority, - ppr_properties, - contig_neighbors, - dev_probability, - negligent_devs, - ] - - # backup sql schema if we are reloading data - backup: BackupArchiveDatabase = None - if FORCE_RELOAD: - # first archive any remaining backup that may exist from a previous run that errored - backup = BackupArchiveDatabase() - if backup.is_backup_schema_exists(): - backup.archive_backup_schema() - conn.commit() - time.sleep(1) # make sure we get a different timestamp - backup = ( - BackupArchiveDatabase() - ) # create a new one so we get a new timestamp - - backup.backup_schema() - conn.commit() - - # Load Vacant Property Data - dataset = vacant_properties() - - # Load and join other datasets - for service in services: - dataset = service(dataset) - - before_drop = dataset.gdf.shape[0] - dataset.gdf = dataset.gdf.drop_duplicates(subset="opa_id") - after_drop = dataset.gdf.shape[0] - print( - f"Duplicate dataset rows dropped after initial services: {before_drop - after_drop}" - ) - - # Add Priority Level - dataset = priority_level(dataset) - - # Print the distribution of "priority_level" - distribution = dataset.gdf["priority_level"].value_counts() - print("Distribution of priority level:") - print(distribution) - - # Add Access Process - dataset = access_process(dataset) - - # Print the distribution of "access_process" - distribution = dataset.gdf["access_process"].value_counts() - print("Distribution of access process:") - print(distribution) - - before_drop = dataset.gdf.shape[0] - dataset.gdf = dataset.gdf.drop_duplicates(subset="opa_id") - after_drop = dataset.gdf.shape[0] - print(f"Duplicate final dataset rows droppeds: {before_drop - after_drop}") - - # back up old tiles file whether we are reloading data or not - if backup is None: - backup = BackupArchiveDatabase() - backup.backup_tiles_file() - - # Finalize in Postgres - dataset.gdf.to_postgis( - "vacant_properties_end", conn, if_exists="replace", index=False - ) - - conn.commit() - - # Post to GCP - dataset.build_and_publish(tiles_file_id_prefix) - - # if we are reloading, run the diff report, then archive the backup and finally prune old archives - if FORCE_RELOAD: - diff_report = DiffReport(timestamp_string=backup.timestamp_string) - diff_report.run() - backup.archive_backup_schema() - conn.commit() - backup.prune_old_archives() - conn.commit() - - conn.close() - -except Exception as e: - error_message = f"Error in backend job: {str(e)}\n\n{traceback.format_exc()}" - send_error_to_slack(error_message) - raise # Optionally re-raise the exception diff --git a/data/src/test/conftest.py b/data/src/test/conftest.py index a447bdbb..c7d2608a 100644 --- a/data/src/test/conftest.py +++ b/data/src/test/conftest.py @@ -8,7 +8,9 @@ def mock_gcp_bucket(monkeypatch): mock_bucket = MagicMock(spec=Bucket) - monkeypatch.setattr("classes.featurelayer.google_cloud_bucket", lambda: mock_bucket) + monkeypatch.setattr( + "new_etl.classes.featurelayer.google_cloud_bucket", lambda: mock_bucket + ) return mock_bucket diff --git a/data/src/test/test_data_utils.py b/data/src/test/test_data_utils.py index eeed7740..cc1e6c6c 100644 --- a/data/src/test/test_data_utils.py +++ b/data/src/test/test_data_utils.py @@ -4,12 +4,10 @@ from unittest.mock import MagicMock, Mock, patch import geopandas as gpd -from data_utils.park_priority import get_latest_shapefile_url, park_priority -from data_utils.ppr_properties import ppr_properties -from data_utils.vacant_properties import vacant_properties from shapely.geometry import Point from config.config import USE_CRS +from new_etl.data_utils.park_priority import get_latest_shapefile_url, park_priority class TestDataUtils(unittest.TestCase): @@ -37,7 +35,9 @@ def setUpClass(cls): def setUp(self): # Set up the mocks that will be used in each test - self.patcher1 = patch("data_utils.vacant_properties.google_cloud_bucket") + self.patcher1 = patch( + "new_etl.data_utils.vacant_properties.google_cloud_bucket" + ) self.patcher2 = patch("geopandas.read_file") self.mock_gcs = self.patcher1.start() @@ -66,7 +66,7 @@ def test_get_latest_shapefile_url(self): self.assertTrue(url.startswith("https://")) self.assertTrue(url.endswith(".zip")) - @patch("data_utils.park_priority.requests.get") + @patch("new_etl.data_utils.park_priority.requests.get") def test_get_latest_shapefile_url_mock(self, mock_get): """ Test the get_latest_shapefile_url function. @@ -81,7 +81,7 @@ def test_get_latest_shapefile_url_mock(self, mock_get): self.assertEqual(url, "https://example.com/shapefile.zip") @patch( - "data_utils.park_priority.requests.get" + "new_etl.data_utils.park_priority.requests.get" ) # Mock requests.get globally in park_priority @patch("geopandas.read_file") @patch("geopandas.GeoDataFrame.to_file") # Mock to_file to prevent actual writing @@ -159,18 +159,6 @@ def test_park_priority( self.assertEqual(result, mock_primary_layer) - def test_ppr_properties(self): - """ - Test the ppr properties layer. Simply construct the class for now to see if it works. - """ - ppr_properties(vacant_properties()) - - def test_vacant_properties(self): - """ - Test the vacant properties layer. Simply construct the class to see if it works. - """ - vacant_properties() - if __name__ == "__main__": unittest.main() diff --git a/data/src/test/test_diff_backup.py b/data/src/test/test_diff_backup.py deleted file mode 100644 index f3dfb9c3..00000000 --- a/data/src/test/test_diff_backup.py +++ /dev/null @@ -1,114 +0,0 @@ -import os -from datetime import datetime - -import pytest -from classes.backup_archive_database import ( - BackupArchiveDatabase, - backup_schema_name, - date_time_format, -) -from classes.diff_report import DiffReport -from classes.featurelayer import google_cloud_bucket -from config.psql import conn, local_engine -from sqlalchemy import inspect - -pytestmark = pytest.mark.skip( - reason="Skipping tests. The tests in test_diff_backup are designed for stateful, manual testing." -) - - -class TestDiffBackup: - """ - test methods for data diffing and backing up - """ - - backup = BackupArchiveDatabase() - - def test_backup(self): - """ - test the backup workflow without archiving - """ - assert backup_schema_name not in inspect(local_engine).get_schema_names() - TestDiffBackup.backup.backup_schema() - assert backup_schema_name in inspect(local_engine).get_schema_names() - - def test_archive(self): - """ - test the backup archiving - """ - TestDiffBackup.backup.archive_backup_schema() - conn.commit() - assert backup_schema_name not in inspect(local_engine).get_schema_names() - - def test_prune_old_archives(self): - """ - test dropping backups that are too old - """ - TestDiffBackup.backup.prune_old_archives() - conn.commit() - - def test_diff(self): - """ - test the diff, assumes the backup_ table is there - """ - diff = DiffReport(timestamp_string=TestDiffBackup.backup.timestamp_string) - diff.run() - - def test_generate_table_detail_report(self): - """print out the html for the vacant_properties diff""" - diff = DiffReport() - html = diff.generate_table_detail_report("vacant_properties") - print(html) - - def test_detail_report(self): - """print out the url for the generated and uploaded detail report for vacant_properties diff""" - diff = DiffReport(timestamp_string=datetime.now().strftime(date_time_format)) - url = diff.detail_report("vacant_properties") - print(url) - - @pytest.mark.skipif( - not os.getenv("INTEGRATION_TESTING"), - reason="For manual integration testing only. Export INTEGRATION_TESTING=True to run", - ) - def test_upload_to_gcp(self): - """test a simple upload to Google cloud""" - bucket = google_cloud_bucket() - blob = bucket.blob("test.txt") - blob.upload_from_string("test") - - @pytest.mark.skipif( - not os.getenv("INTEGRATION_TESTING"), - reason="For manual integration testing only. Export INTEGRATION_TESTING=True to run", - ) - def test_send_report_to_slack(self): - """CAREFUL: if configured, this will send a message to Slack, potentially our prod channel""" - diff = DiffReport() - diff.report = "This is the report" - diff.send_report_to_slack() - - @pytest.mark.skipif( - not os.getenv("INTEGRATION_TESTING"), - reason="For manual integration testing only. Export INTEGRATION_TESTING=True to run", - ) - def test_email_report(self): - """CAREFUL: if configured, this will send email if configured""" - diff = DiffReport() - diff.report = "This is the report" - diff.email_report() - - def test_is_backup_schema_exists(self): - """test method for whether the backup schema exists""" - if TestDiffBackup.backup.is_backup_schema_exists(): - TestDiffBackup.backup.archive_backup_schema() - conn.commit() - assert not TestDiffBackup.backup.is_backup_schema_exists() - else: - TestDiffBackup.backup.backup_schema() - assert TestDiffBackup.backup.is_backup_schema_exists() - TestDiffBackup.backup.archive_backup_schema() - conn.commit() - assert not TestDiffBackup.backup.is_backup_schema_exists() - - def test_backup_tiles_file(self): - """test backing up the tiles file""" - TestDiffBackup.backup.backup_tiles_file() diff --git a/data/src/test/test_slack_error_reporter.py b/data/src/test/test_slack_error_reporter.py index 4a30653b..4ff2dbea 100644 --- a/data/src/test/test_slack_error_reporter.py +++ b/data/src/test/test_slack_error_reporter.py @@ -5,17 +5,17 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/..") -from classes.slack_error_reporter import ( - send_error_to_slack, -) # Ensure correct file import +from new_etl.classes.slack_reporters import ( + send_error_to_slack, # Ensure correct file import +) class TestSlackNotifier(unittest.TestCase): @patch( - "classes.slack_error_reporter.WebClient.chat_postMessage" + "new_etl.classes.slack_reporters.WebClient.chat_postMessage" ) # Correct patching @patch( - "classes.slack_error_reporter.os.getenv", return_value="mock_slack_token" + "new_etl.classes.slack_reporters.os.getenv", return_value="mock_slack_token" ) # Correct patching def test_send_error_to_slack(self, _mock_getenv, mock_slack_post): """Test that Slack error reporting is triggered correctly.""" @@ -33,10 +33,10 @@ def test_send_error_to_slack(self, _mock_getenv, mock_slack_post): ) @patch( - "classes.slack_error_reporter.WebClient.chat_postMessage" + "new_etl.classes.slack_reporters.WebClient.chat_postMessage" ) # Correct patching @patch( - "classes.slack_error_reporter.os.getenv", return_value=None + "new_etl.classes.slack_reporters.os.getenv", return_value=None ) # Simulate missing Slack token def test_no_error_no_slack_message(self, _mock_getenv, mock_slack_post): """Test that Slack notification is not triggered if there's no error.""" diff --git a/data/src/test/test_utils.py b/data/src/test/test_utils.py index 9ea090f4..d8dd1bff 100644 --- a/data/src/test/test_utils.py +++ b/data/src/test/test_utils.py @@ -1,6 +1,6 @@ import re -from data_utils import utils +from new_etl.data_utils import utils class TestUtils: