@next-degree/pickle-shared-js 0.12.7 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{company_service_sanity-2J1ZuUnu.d.cts → company_service_sanity-BzaIPM-N.d.ts} +2297 -2297
- package/dist/{company_service_sanity-KaAGfnNV.d.ts → company_service_sanity-Zy8TiORb.d.cts} +2297 -2297
- package/dist/components/buttons/BackButton.cjs +5 -8
- package/dist/components/buttons/BackButton.cjs.map +1 -1
- package/dist/components/buttons/BackButton.d.cts +2 -2
- package/dist/components/buttons/BackButton.d.ts +2 -2
- package/dist/components/buttons/BackButton.js +5 -8
- package/dist/components/buttons/BackButton.js.map +1 -1
- package/dist/components/company/CompanyBenefits.cjs +1 -5
- package/dist/components/company/CompanyBenefits.cjs.map +1 -1
- package/dist/components/company/CompanyBenefits.d.cts +2 -2
- package/dist/components/company/CompanyBenefits.d.ts +2 -2
- package/dist/components/company/CompanyBenefits.js +1 -5
- package/dist/components/company/CompanyBenefits.js.map +1 -1
- package/dist/components/company/CompanyInformation.cjs +23 -44
- package/dist/components/company/CompanyInformation.cjs.map +1 -1
- package/dist/components/company/CompanyInformation.d.cts +2 -2
- package/dist/components/company/CompanyInformation.d.ts +2 -2
- package/dist/components/company/CompanyInformation.js +23 -44
- package/dist/components/company/CompanyInformation.js.map +1 -1
- package/dist/components/company/CompanyTake.cjs +12 -26
- package/dist/components/company/CompanyTake.cjs.map +1 -1
- package/dist/components/company/CompanyTake.d.cts +2 -2
- package/dist/components/company/CompanyTake.d.ts +2 -2
- package/dist/components/company/CompanyTake.js +12 -26
- package/dist/components/company/CompanyTake.js.map +1 -1
- package/dist/components/jobCard/JobLocation.cjs +23 -34
- package/dist/components/jobCard/JobLocation.cjs.map +1 -1
- package/dist/components/jobCard/JobLocation.d.cts +3 -3
- package/dist/components/jobCard/JobLocation.d.ts +3 -3
- package/dist/components/jobCard/JobLocation.js +23 -34
- package/dist/components/jobCard/JobLocation.js.map +1 -1
- package/dist/components/jobPost/JobDescription.cjs +164 -30
- package/dist/components/jobPost/JobDescription.cjs.map +1 -1
- package/dist/components/jobPost/JobDescription.d.cts +2 -2
- package/dist/components/jobPost/JobDescription.d.ts +2 -2
- package/dist/components/jobPost/JobDescription.js +164 -30
- package/dist/components/jobPost/JobDescription.js.map +1 -1
- package/dist/components/jobPost/JobHeader.cjs +110 -138
- package/dist/components/jobPost/JobHeader.cjs.map +1 -1
- package/dist/components/jobPost/JobHeader.d.cts +2 -2
- package/dist/components/jobPost/JobHeader.d.ts +2 -2
- package/dist/components/jobPost/JobHeader.js +110 -138
- package/dist/components/jobPost/JobHeader.js.map +1 -1
- package/dist/components/jobPost/JobPost.cjs +382 -318
- package/dist/components/jobPost/JobPost.cjs.map +1 -1
- package/dist/components/jobPost/JobPost.d.cts +3 -3
- package/dist/components/jobPost/JobPost.d.ts +3 -3
- package/dist/components/jobPost/JobPost.js +344 -280
- package/dist/components/jobPost/JobPost.js.map +1 -1
- package/dist/components/primitives/avatar.cjs +3 -4
- package/dist/components/primitives/avatar.cjs.map +1 -1
- package/dist/components/primitives/avatar.js +3 -4
- package/dist/components/primitives/avatar.js.map +1 -1
- package/dist/components/primitives/command.cjs +37 -50
- package/dist/components/primitives/command.cjs.map +1 -1
- package/dist/components/primitives/command.d.cts +5 -6
- package/dist/components/primitives/command.d.ts +5 -6
- package/dist/components/primitives/command.js +37 -50
- package/dist/components/primitives/command.js.map +1 -1
- package/dist/components/primitives/dialog.cjs +18 -27
- package/dist/components/primitives/dialog.cjs.map +1 -1
- package/dist/components/primitives/dialog.d.cts +2 -3
- package/dist/components/primitives/dialog.d.ts +2 -3
- package/dist/components/primitives/dialog.js +18 -27
- package/dist/components/primitives/dialog.js.map +1 -1
- package/dist/components/primitives/input-otp.cjs +8 -11
- package/dist/components/primitives/input-otp.cjs.map +1 -1
- package/dist/components/primitives/input-otp.d.cts +2 -2
- package/dist/components/primitives/input-otp.d.ts +2 -2
- package/dist/components/primitives/input-otp.js +8 -11
- package/dist/components/primitives/input-otp.js.map +1 -1
- package/dist/components/primitives/popover.cjs +2 -3
- package/dist/components/primitives/popover.cjs.map +1 -1
- package/dist/components/primitives/popover.js +2 -3
- package/dist/components/primitives/popover.js.map +1 -1
- package/dist/components/primitives/radio-group.cjs +12 -16
- package/dist/components/primitives/radio-group.cjs.map +1 -1
- package/dist/components/primitives/radio-group.js +12 -16
- package/dist/components/primitives/radio-group.js.map +1 -1
- package/dist/components/primitives/separator.cjs +1 -2
- package/dist/components/primitives/separator.cjs.map +1 -1
- package/dist/components/primitives/separator.js +1 -2
- package/dist/components/primitives/separator.js.map +1 -1
- package/dist/components/primitives/tooltip.cjs +1 -2
- package/dist/components/primitives/tooltip.cjs.map +1 -1
- package/dist/components/primitives/tooltip.js +1 -2
- package/dist/components/primitives/tooltip.js.map +1 -1
- package/dist/components/ui/Avatar.cjs +6 -11
- package/dist/components/ui/Avatar.cjs.map +1 -1
- package/dist/components/ui/Avatar.d.cts +3 -3
- package/dist/components/ui/Avatar.d.ts +3 -3
- package/dist/components/ui/Avatar.js +6 -11
- package/dist/components/ui/Avatar.js.map +1 -1
- package/dist/components/ui/Badge.cjs +12 -2
- package/dist/components/ui/Badge.cjs.map +1 -1
- package/dist/components/ui/Badge.d.cts +1 -2
- package/dist/components/ui/Badge.d.ts +1 -2
- package/dist/components/ui/Badge.js +2 -2
- package/dist/components/ui/Badge.js.map +1 -1
- package/dist/components/ui/Button.cjs +163 -8
- package/dist/components/ui/Button.cjs.map +1 -1
- package/dist/components/ui/Button.d.cts +4 -8
- package/dist/components/ui/Button.d.ts +4 -8
- package/dist/components/ui/Button.js +153 -8
- package/dist/components/ui/Button.js.map +1 -1
- package/dist/components/ui/Checkbox.cjs +18 -28
- package/dist/components/ui/Checkbox.cjs.map +1 -1
- package/dist/components/ui/Checkbox.js +18 -28
- package/dist/components/ui/Checkbox.js.map +1 -1
- package/dist/components/ui/Chip.cjs +12 -2
- package/dist/components/ui/Chip.cjs.map +1 -1
- package/dist/components/ui/Chip.d.cts +2 -3
- package/dist/components/ui/Chip.d.ts +2 -3
- package/dist/components/ui/Chip.js +2 -2
- package/dist/components/ui/Chip.js.map +1 -1
- package/dist/components/ui/Combobox.cjs +171 -233
- package/dist/components/ui/Combobox.cjs.map +1 -1
- package/dist/components/ui/Combobox.js +171 -233
- package/dist/components/ui/Combobox.js.map +1 -1
- package/dist/components/ui/Counter.cjs +56 -74
- package/dist/components/ui/Counter.cjs.map +1 -1
- package/dist/components/ui/Counter.js +56 -74
- package/dist/components/ui/Counter.js.map +1 -1
- package/dist/components/ui/DatePicker.cjs +44 -68
- package/dist/components/ui/DatePicker.cjs.map +1 -1
- package/dist/components/ui/DatePicker.js +44 -68
- package/dist/components/ui/DatePicker.js.map +1 -1
- package/dist/components/ui/DismissibleBanner.cjs +13 -16
- package/dist/components/ui/DismissibleBanner.cjs.map +1 -1
- package/dist/components/ui/DismissibleBanner.d.cts +2 -2
- package/dist/components/ui/DismissibleBanner.d.ts +2 -2
- package/dist/components/ui/DismissibleBanner.js +13 -16
- package/dist/components/ui/DismissibleBanner.js.map +1 -1
- package/dist/components/ui/ErrorMessage.cjs +1 -2
- package/dist/components/ui/ErrorMessage.cjs.map +1 -1
- package/dist/components/ui/ErrorMessage.d.cts +2 -2
- package/dist/components/ui/ErrorMessage.d.ts +2 -2
- package/dist/components/ui/ErrorMessage.js +1 -2
- package/dist/components/ui/ErrorMessage.js.map +1 -1
- package/dist/components/ui/Icon.cjs +1 -2
- package/dist/components/ui/Icon.cjs.map +1 -1
- package/dist/components/ui/Icon.js +1 -2
- package/dist/components/ui/Icon.js.map +1 -1
- package/dist/components/ui/Input.cjs +48 -68
- package/dist/components/ui/Input.cjs.map +1 -1
- package/dist/components/ui/Input.js +48 -68
- package/dist/components/ui/Input.js.map +1 -1
- package/dist/components/ui/InputOtp.cjs +56 -73
- package/dist/components/ui/InputOtp.cjs.map +1 -1
- package/dist/components/ui/InputOtp.js +56 -73
- package/dist/components/ui/InputOtp.js.map +1 -1
- package/dist/components/ui/Label.cjs +14 -24
- package/dist/components/ui/Label.cjs.map +1 -1
- package/dist/components/ui/Label.d.cts +2 -2
- package/dist/components/ui/Label.d.ts +2 -2
- package/dist/components/ui/Label.js +14 -24
- package/dist/components/ui/Label.js.map +1 -1
- package/dist/components/ui/LinkButton.cjs +5 -5
- package/dist/components/ui/LinkButton.cjs.map +1 -1
- package/dist/components/ui/LinkButton.d.cts +1 -2
- package/dist/components/ui/LinkButton.d.ts +1 -2
- package/dist/components/ui/LinkButton.js +5 -5
- package/dist/components/ui/LinkButton.js.map +1 -1
- package/dist/components/ui/ListItem.cjs +32 -48
- package/dist/components/ui/ListItem.cjs.map +1 -1
- package/dist/components/ui/ListItem.d.cts +2 -2
- package/dist/components/ui/ListItem.d.ts +2 -2
- package/dist/components/ui/ListItem.js +32 -48
- package/dist/components/ui/ListItem.js.map +1 -1
- package/dist/components/ui/Map/ClusterMarker.cjs +80 -0
- package/dist/components/ui/Map/ClusterMarker.cjs.map +1 -0
- package/dist/components/ui/Map/ClusterMarker.d.cts +6 -0
- package/dist/components/ui/Map/ClusterMarker.d.ts +6 -0
- package/dist/components/ui/Map/ClusterMarker.js +56 -0
- package/dist/components/ui/Map/ClusterMarker.js.map +1 -0
- package/dist/components/ui/Map/FocusCircle.cjs +86 -0
- package/dist/components/ui/Map/FocusCircle.cjs.map +1 -0
- package/dist/components/ui/Map/FocusCircle.d.cts +5 -0
- package/dist/components/ui/Map/FocusCircle.d.ts +5 -0
- package/dist/components/ui/Map/FocusCircle.js +62 -0
- package/dist/components/ui/Map/FocusCircle.js.map +1 -0
- package/dist/components/ui/Map/IndividualMarker.cjs +60 -0
- package/dist/components/ui/Map/IndividualMarker.cjs.map +1 -0
- package/dist/components/ui/Map/IndividualMarker.d.cts +6 -0
- package/dist/components/ui/Map/IndividualMarker.d.ts +6 -0
- package/dist/components/ui/Map/IndividualMarker.js +36 -0
- package/dist/components/ui/Map/IndividualMarker.js.map +1 -0
- package/dist/components/ui/Map/MapComponent.cjs +401 -0
- package/dist/components/ui/Map/MapComponent.cjs.map +1 -0
- package/dist/components/ui/Map/MapComponent.d.cts +6 -0
- package/dist/components/ui/Map/MapComponent.d.ts +6 -0
- package/dist/components/ui/Map/MapComponent.js +367 -0
- package/dist/components/ui/Map/MapComponent.js.map +1 -0
- package/dist/components/ui/Map/MapContent.cjs +279 -0
- package/dist/components/ui/Map/MapContent.cjs.map +1 -0
- package/dist/components/ui/Map/MapContent.d.cts +6 -0
- package/dist/components/ui/Map/MapContent.d.ts +6 -0
- package/dist/components/ui/Map/MapContent.js +255 -0
- package/dist/components/ui/Map/MapContent.js.map +1 -0
- package/dist/components/ui/Map/clustering.cjs +105 -0
- package/dist/components/ui/Map/clustering.cjs.map +1 -0
- package/dist/components/ui/Map/clustering.d.cts +17 -0
- package/dist/components/ui/Map/clustering.d.ts +17 -0
- package/dist/components/ui/Map/clustering.js +77 -0
- package/dist/components/ui/Map/clustering.js.map +1 -0
- package/dist/components/ui/Map/constants.cjs +65 -0
- package/dist/components/ui/Map/constants.cjs.map +1 -0
- package/dist/components/ui/Map/constants.d.cts +28 -0
- package/dist/components/ui/Map/constants.d.ts +28 -0
- package/dist/components/ui/Map/constants.js +34 -0
- package/dist/components/ui/Map/constants.js.map +1 -0
- package/dist/components/ui/Map/hooks.cjs +96 -0
- package/dist/components/ui/Map/hooks.cjs.map +1 -0
- package/dist/components/ui/Map/hooks.d.cts +17 -0
- package/dist/components/ui/Map/hooks.d.ts +17 -0
- package/dist/components/ui/Map/hooks.js +59 -0
- package/dist/components/ui/Map/hooks.js.map +1 -0
- package/dist/components/ui/Map/index.cjs +402 -0
- package/dist/components/ui/Map/index.cjs.map +1 -0
- package/dist/components/ui/Map/index.d.cts +3 -0
- package/dist/components/ui/Map/index.d.ts +3 -0
- package/dist/components/ui/Map/index.js +365 -0
- package/dist/components/ui/Map/index.js.map +1 -0
- package/dist/components/ui/Map/types.cjs +19 -0
- package/dist/components/ui/Map/types.cjs.map +1 -0
- package/dist/components/ui/Map/types.d.cts +82 -0
- package/dist/components/ui/Map/types.d.ts +82 -0
- package/dist/components/ui/Map/types.js +1 -0
- package/dist/components/ui/Map/types.js.map +1 -0
- package/dist/components/ui/Map/utils.cjs +80 -0
- package/dist/components/ui/Map/utils.cjs.map +1 -0
- package/dist/components/ui/Map/utils.d.cts +9 -0
- package/dist/components/ui/Map/utils.d.ts +9 -0
- package/dist/components/ui/Map/utils.js +49 -0
- package/dist/components/ui/Map/utils.js.map +1 -0
- package/dist/components/ui/PlacesQueryInput.cjs +71 -94
- package/dist/components/ui/PlacesQueryInput.cjs.map +1 -1
- package/dist/components/ui/PlacesQueryInput.d.cts +2 -2
- package/dist/components/ui/PlacesQueryInput.d.ts +2 -2
- package/dist/components/ui/PlacesQueryInput.js +71 -94
- package/dist/components/ui/PlacesQueryInput.js.map +1 -1
- package/dist/components/ui/Radio.cjs +49 -69
- package/dist/components/ui/Radio.cjs.map +1 -1
- package/dist/components/ui/Radio.js +49 -69
- package/dist/components/ui/Radio.js.map +1 -1
- package/dist/components/ui/ReadMore.cjs +163 -25
- package/dist/components/ui/ReadMore.cjs.map +1 -1
- package/dist/components/ui/ReadMore.d.cts +2 -2
- package/dist/components/ui/ReadMore.d.ts +2 -2
- package/dist/components/ui/ReadMore.js +163 -25
- package/dist/components/ui/ReadMore.js.map +1 -1
- package/dist/components/ui/Select.cjs +138 -172
- package/dist/components/ui/Select.cjs.map +1 -1
- package/dist/components/ui/Select.js +132 -166
- package/dist/components/ui/Select.js.map +1 -1
- package/dist/components/ui/StepTabs.cjs +24 -27
- package/dist/components/ui/StepTabs.cjs.map +1 -1
- package/dist/components/ui/StepTabs.d.cts +3 -3
- package/dist/components/ui/StepTabs.d.ts +3 -3
- package/dist/components/ui/StepTabs.js +24 -27
- package/dist/components/ui/StepTabs.js.map +1 -1
- package/dist/components/ui/Switch.cjs +13 -21
- package/dist/components/ui/Switch.cjs.map +1 -1
- package/dist/components/ui/Switch.js +13 -21
- package/dist/components/ui/Switch.js.map +1 -1
- package/dist/components/ui/buttonShadcn.cjs +1 -2
- package/dist/components/ui/buttonShadcn.cjs.map +1 -1
- package/dist/components/ui/buttonShadcn.js +1 -2
- package/dist/components/ui/buttonShadcn.js.map +1 -1
- package/dist/components/ui/calendar.cjs +5 -6
- package/dist/components/ui/calendar.cjs.map +1 -1
- package/dist/components/ui/calendar.d.cts +1 -2
- package/dist/components/ui/calendar.d.ts +1 -2
- package/dist/components/ui/calendar.js +5 -6
- package/dist/components/ui/calendar.js.map +1 -1
- package/dist/contexts/WindowHistoryProvider.cjs +1 -2
- package/dist/contexts/WindowHistoryProvider.cjs.map +1 -1
- package/dist/contexts/WindowHistoryProvider.d.cts +1 -2
- package/dist/contexts/WindowHistoryProvider.d.ts +1 -2
- package/dist/contexts/WindowHistoryProvider.js +1 -2
- package/dist/contexts/WindowHistoryProvider.js.map +1 -1
- package/dist/{displayText-DahwdHdi.d.ts → displayText-DIxMXVLl.d.ts} +2 -2
- package/dist/{displayText-DW0qiJqh.d.cts → displayText-DRyxjHTZ.d.cts} +2 -2
- package/dist/hooks/useDisplayText.d.cts +3 -3
- package/dist/hooks/useDisplayText.d.ts +3 -3
- package/dist/hooks/useWindowHistory.cjs +0 -1
- package/dist/hooks/useWindowHistory.cjs.map +1 -1
- package/dist/hooks/useWindowHistory.d.cts +0 -1
- package/dist/hooks/useWindowHistory.d.ts +0 -1
- package/dist/hooks/useWindowHistory.js +0 -1
- package/dist/hooks/useWindowHistory.js.map +1 -1
- package/dist/index.cjs +1343 -1111
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +1293 -1061
- package/dist/index.js.map +1 -1
- package/dist/{job_posting_service_latest-C_TEBzCf.d.cts → job_posting_service_latest-7q4A7RpW.d.cts} +1171 -1171
- package/dist/{job_posting_service_latest-C_TEBzCf.d.ts → job_posting_service_latest-7q4A7RpW.d.ts} +1171 -1171
- package/dist/{job_posting_service_latest-DdgK8Nnz.d.cts → job_posting_service_latest-BrZndMS6.d.cts} +1171 -1171
- package/dist/{job_posting_service_latest-DdgK8Nnz.d.ts → job_posting_service_latest-BrZndMS6.d.ts} +1171 -1171
- package/dist/{job_posting_service_sanity-BNq-Am9N.d.cts → job_posting_service_sanity-B5NZ-7tI.d.cts} +2126 -2126
- package/dist/{job_posting_service_sanity-BKo9TBDT.d.ts → job_posting_service_sanity-LlRkfIpt.d.ts} +2126 -2126
- package/dist/lib/locations.d.cts +3 -3
- package/dist/lib/locations.d.ts +3 -3
- package/dist/lib/mappings.d.cts +3 -3
- package/dist/lib/mappings.d.ts +3 -3
- package/dist/lib/salaryRange.d.cts +1 -1
- package/dist/lib/salaryRange.d.ts +1 -1
- package/dist/services/displayText.d.cts +3 -3
- package/dist/services/displayText.d.ts +3 -3
- package/dist/styles/globals.css +149 -6
- package/dist/styles/globals.css.map +1 -1
- package/dist/types/data/company_service_latest.d.cts +1 -1
- package/dist/types/data/company_service_latest.d.ts +1 -1
- package/dist/types/data/job_posting_service_latest.d.cts +1 -1
- package/dist/types/data/job_posting_service_latest.d.ts +1 -1
- package/dist/types/data/shared_pickle_output_latest.d.cts +1 -1
- package/dist/types/data/shared_pickle_output_latest.d.ts +1 -1
- package/dist/types/index.d.cts +6 -6
- package/dist/types/index.d.ts +6 -6
- package/dist/types/latest/company_service_latest.d.cts +1 -1
- package/dist/types/latest/company_service_latest.d.ts +1 -1
- package/dist/types/latest/custom/company_service_sanity.d.cts +3 -3
- package/dist/types/latest/custom/company_service_sanity.d.ts +3 -3
- package/dist/types/latest/custom/job_posting_service_sanity.d.cts +3 -3
- package/dist/types/latest/custom/job_posting_service_sanity.d.ts +3 -3
- package/dist/types/latest/job_posting_service_latest.d.cts +1 -1
- package/dist/types/latest/job_posting_service_latest.d.ts +1 -1
- package/dist/types/latest/shared_pickle_output_latest.d.cts +1 -1
- package/dist/types/latest/shared_pickle_output_latest.d.ts +1 -1
- package/package.json +4 -3
- package/dist/components/ui/MapComponent.cjs +0 -61
- package/dist/components/ui/MapComponent.cjs.map +0 -1
- package/dist/components/ui/MapComponent.d.cts +0 -15
- package/dist/components/ui/MapComponent.d.ts +0 -15
- package/dist/components/ui/MapComponent.js +0 -41
- package/dist/components/ui/MapComponent.js.map +0 -1
- package/dist/{company_service_latest-CITz7F53.d.cts → company_service_latest-BwbaqchJ.d.cts} +1220 -1220
- package/dist/{company_service_latest-CITz7F53.d.ts → company_service_latest-BwbaqchJ.d.ts} +1220 -1220
- package/dist/{company_service_latest-C7Moeufo.d.cts → company_service_latest-FHqG4LjA.d.cts} +1220 -1220
- package/dist/{company_service_latest-C7Moeufo.d.ts → company_service_latest-FHqG4LjA.d.ts} +1220 -1220
- package/dist/{shared_pickle_output_latest-CXBCG04N.d.cts → shared_pickle_output_latest-CKHNY1lx.d.cts} +42 -42
- package/dist/{shared_pickle_output_latest-CXBCG04N.d.ts → shared_pickle_output_latest-CKHNY1lx.d.ts} +42 -42
- package/dist/{shared_pickle_output_latest-CtvHTPeX.d.cts → shared_pickle_output_latest-DIPgxUul.d.cts} +42 -42
- package/dist/{shared_pickle_output_latest-CtvHTPeX.d.ts → shared_pickle_output_latest-DIPgxUul.d.ts} +42 -42
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ui/Map/MapContent.tsx","../../../../src/components/ui/Map/ClusterMarker.tsx","../../../../src/components/ui/Map/constants.ts","../../../../src/components/ui/Map/utils.ts","../../../../src/components/ui/Map/FocusCircle.tsx","../../../../src/components/ui/Map/IndividualMarker.tsx","../../../../src/lib/utils.ts"],"sourcesContent":["'use client'\n\nimport { AdvancedMarker, Map, Pin, useMap, useMapsLibrary } from '@vis.gl/react-google-maps'\nimport { useCallback } from 'react'\n\nimport { ClusterMarker } from '@/components/ui/Map/ClusterMarker'\nimport { PIN_COLORS } from '@/components/ui/Map/constants'\nimport { FocusCircle } from '@/components/ui/Map/FocusCircle'\nimport { IndividualMarker } from '@/components/ui/Map/IndividualMarker'\nimport type { MapContentProps, PinData } from '@/components/ui/Map/types'\nimport { cn } from '@/lib/utils'\n\nexport function MapContent<T = PinData>({\n mapId,\n mapCenter,\n mapZoom,\n position,\n coordinates,\n clusters,\n supercluster,\n onPinHover,\n onPinClick,\n focusPoint,\n radiusMiles,\n className,\n setBounds,\n setZoomLevel,\n}: MapContentProps<T>) {\n const map = useMap()\n const mapsLibrary = useMapsLibrary('maps')\n\n const zoomToLevel = useCallback(\n (newZoom: number) => {\n if (map) {\n map.setZoom(newZoom)\n }\n },\n [map]\n )\n\n const handleBoundsChanged = (e: {\n detail: { bounds: { south: number; west: number; north: number; east: number } }\n }) => {\n if (e.detail.bounds) {\n const bounds = e.detail.bounds\n setBounds([\n [bounds.south, bounds.west],\n [bounds.north, bounds.east],\n ])\n }\n }\n\n const handleZoomChanged = (e: { detail: { zoom: number } }) => {\n if (e.detail.zoom) {\n setZoomLevel(e.detail.zoom)\n }\n }\n\n const handleCameraChanged = (e: { detail: { zoom: number } }) => {\n if (e.detail.zoom) {\n setZoomLevel(e.detail.zoom)\n }\n }\n\n return (\n <div className={cn('relative h-screen max-w-full', className)}>\n <Map\n defaultZoom={mapZoom}\n defaultCenter={mapCenter}\n mapId={mapId}\n keyboardShortcuts={true}\n disableDefaultUI={true}\n zoomControl={true}\n onBoundsChanged={handleBoundsChanged}\n onZoomChanged={handleZoomChanged}\n onCameraChanged={handleCameraChanged}\n >\n {position && !coordinates && (\n <AdvancedMarker position={position}>\n <Pin {...PIN_COLORS} />\n </AdvancedMarker>\n )}\n\n {coordinates &&\n clusters.map((cluster) => {\n const { cluster: isCluster } = cluster.properties\n\n if (isCluster) {\n return (\n <ClusterMarker\n key={`cluster-${cluster.id}`}\n cluster={cluster}\n coordinates={coordinates}\n onPinClick={onPinClick}\n onPinHover={onPinHover}\n zoomToLevel={zoomToLevel}\n supercluster={supercluster}\n />\n )\n }\n\n const originalPoint = coordinates[cluster.properties.pointId!]\n return (\n <IndividualMarker\n key={`marker-${cluster.properties.pointId}`}\n coordinate={originalPoint}\n onPinClick={onPinClick}\n onPinHover={onPinHover}\n />\n )\n })}\n\n {coordinates &&\n clusters.length === 0 &&\n coordinates.map((coord, index) => (\n <IndividualMarker\n key={`fallback-${index}`}\n coordinate={coord}\n onPinClick={onPinClick}\n onPinHover={onPinHover}\n />\n ))}\n\n {focusPoint && radiusMiles && (\n <FocusCircle\n focusPoint={focusPoint}\n radiusMiles={radiusMiles}\n map={map}\n mapsLibrary={mapsLibrary}\n />\n )}\n </Map>\n </div>\n )\n}\n","'use client'\n\nimport { AdvancedMarker } from '@vis.gl/react-google-maps'\n\nimport type { ClusterMarkerProps, PinData } from '@/components/ui/Map/types'\nimport { filterClusterCoordinates } from '@/components/ui/Map/utils'\n\nexport function ClusterMarker<T = PinData>({\n cluster,\n coordinates,\n onPinClick,\n onPinHover,\n zoomToLevel,\n supercluster,\n}: ClusterMarkerProps<T>) {\n const [lng, lat] = cluster.geometry.coordinates\n const { point_count: pointCount } = cluster.properties\n\n const handleClick = () => {\n const clusterCoordinates = filterClusterCoordinates(coordinates, lat, lng)\n onPinClick?.(clusterCoordinates)\n\n const expansionZoom = supercluster.getClusterExpansionZoom(cluster.id)\n zoomToLevel(expansionZoom)\n }\n\n const handleMouseEnter = () => {\n const clusterCoordinates = filterClusterCoordinates(coordinates, lat, lng)\n onPinHover?.(clusterCoordinates)\n }\n\n const handleMouseLeave = () => onPinHover?.(null)\n\n return (\n <AdvancedMarker\n key={`cluster-${cluster.id}`}\n position={{ lat, lng }}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n >\n <div className=\"relative flex items-center justify-center\" id=\"CLUSTER_MARKER\">\n <div className=\"flex h-8 w-8 items-center justify-center rounded-full border-2 border-white bg-red-500 text-sm font-bold text-white shadow-lg\">\n {pointCount || '?'}\n </div>\n </div>\n </AdvancedMarker>\n )\n}\n","export const DEFAULT_POSITION = { lat: 40.715021, lng: -74.00459 }\nexport const DEFAULT_ZOOM = 10\nexport const CLUSTER_PIN_SCALE = 1.5\nexport const CLUSTER_DISTANCE_THRESHOLD = 0.001\n\nexport const PIN_COLORS = {\n background: '#0B5441',\n borderColor: '#EBFDF1',\n glyphColor: '#D4F500',\n} as const\n\nexport const FOCUS_CIRCLE_STYLES = {\n strokeColor: '#0B5441',\n strokeOpacity: 0.8,\n strokeWeight: 2,\n fillColor: '#0B5441',\n fillOpacity: 0.1,\n clickable: false,\n zIndex: 1,\n} as const\n\nexport const CLUSTERING_CONFIG = {\n radius: 60,\n maxZoom: 16,\n minPoints: 2,\n} as const\n","import { CLUSTER_DISTANCE_THRESHOLD, DEFAULT_POSITION } from '@/components/ui/Map/constants'\nimport type { Coordinate, PinData } from '@/components/ui/Map/types'\n\nexport function getCenterForCoordinates<T = PinData>(coords: Coordinate<T>[]): Coordinate<T> {\n if (coords.length === 0) return DEFAULT_POSITION as Coordinate<T>\n\n const avgLat = coords.reduce((sum, coord) => sum + coord.lat, 0) / coords.length\n const avgLng = coords.reduce((sum, coord) => sum + coord.lng, 0) / coords.length\n\n return { lat: avgLat, lng: avgLng }\n}\n\nexport function getZoomForCoordinates<T = PinData>(\n coords: Coordinate<T>[],\n defaultZoom: number\n): number {\n if (coords.length <= 1) return defaultZoom\n\n const lats = coords.map((coord) => coord.lat)\n const lngs = coords.map((coord) => coord.lng)\n\n const latDiff = Math.max(...lats) - Math.min(...lats)\n const lngDiff = Math.max(...lngs) - Math.min(...lngs)\n const maxDiff = Math.max(latDiff, lngDiff)\n\n if (maxDiff > 0.1) return 8\n if (maxDiff > 0.05) return 10\n if (maxDiff > 0.01) return 12\n return 14\n}\n\nexport function getClusteringRadius(zoom: number): number {\n if (zoom <= 8) return 200\n if (zoom <= 12) return 150\n return 100\n}\n\nexport function filterClusterCoordinates<T = PinData>(\n coordinates: Coordinate<T>[],\n clusterLat: number,\n clusterLng: number\n): Coordinate<T>[] {\n return coordinates.filter((coord) => {\n const latDiff = Math.abs(coord.lat - clusterLat)\n const lngDiff = Math.abs(coord.lng - clusterLng)\n const distance = Math.sqrt(latDiff * latDiff + lngDiff * lngDiff)\n return distance < CLUSTER_DISTANCE_THRESHOLD\n })\n}\n\nexport function calculateDistance<T = PinData>(\n coord1: Coordinate<T>,\n coord2: Coordinate<T>\n): number {\n const latDiff = Math.abs(coord1.lat - coord2.lat)\n const lngDiff = Math.abs(coord1.lng - coord2.lng)\n return Math.sqrt(latDiff * latDiff + lngDiff * lngDiff)\n}\n","'use client'\n\nimport { useEffect, useMemo, useRef } from 'react'\n\nimport { FOCUS_CIRCLE_STYLES } from '@/components/ui/Map/constants'\nimport type { FocusCircleProps, PinData } from '@/components/ui/Map/types'\n\nexport function FocusCircle<T = PinData>({\n focusPoint,\n radiusMiles,\n map,\n mapsLibrary,\n}: FocusCircleProps<T>) {\n const circleRef = useRef<google.maps.Circle | null>(null)\n\n const circleProps = useMemo(() => {\n if (!focusPoint || !radiusMiles) return null\n return {\n center: focusPoint,\n radius: radiusMiles * 1609.34,\n }\n }, [focusPoint, radiusMiles])\n\n useEffect(() => {\n if (!map || !mapsLibrary || !circleProps) {\n return\n }\n\n if (!circleRef.current) {\n const circle = new google.maps.Circle({\n center: circleProps.center,\n radius: circleProps.radius,\n ...FOCUS_CIRCLE_STYLES,\n map: map,\n })\n\n circleRef.current = circle\n } else {\n circleRef.current.setCenter(circleProps.center)\n circleRef.current.setRadius(circleProps.radius)\n }\n }, [map, mapsLibrary, circleProps])\n\n useEffect(() => {\n return () => {\n if (circleRef.current) {\n circleRef.current.setMap(null)\n circleRef.current = null\n }\n }\n }, [])\n\n return null\n}\n","'use client'\n\nimport { AdvancedMarker, Pin } from '@vis.gl/react-google-maps'\n\nimport { PIN_COLORS } from '@/components/ui/Map/constants'\nimport type { IndividualMarkerProps, PinData } from '@/components/ui/Map/types'\n\nexport function IndividualMarker<T = PinData>({\n coordinate,\n onPinClick,\n onPinHover,\n}: IndividualMarkerProps<T>) {\n const handleMouseEnter = () => onPinHover?.(coordinate)\n const handleMouseLeave = () => onPinHover?.(null)\n const handleClick = () => onPinClick?.(coordinate)\n\n return (\n <AdvancedMarker\n position={{ lat: coordinate.lat, lng: coordinate.lng }}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleClick}\n >\n <Pin {...PIN_COLORS} />\n </AdvancedMarker>\n )\n}\n","import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":"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","names":["import_react_google_maps","import_react","import_react_google_maps"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { PinData, MapContentProps } from './types.cjs';
|
|
3
|
+
|
|
4
|
+
declare function MapContent<T = PinData>({ mapId, mapCenter, mapZoom, position, coordinates, clusters, supercluster, onPinHover, onPinClick, focusPoint, radiusMiles, className, setBounds, setZoomLevel, }: MapContentProps<T>): React.JSX.Element;
|
|
5
|
+
|
|
6
|
+
export { MapContent };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { PinData, MapContentProps } from './types.js';
|
|
3
|
+
|
|
4
|
+
declare function MapContent<T = PinData>({ mapId, mapCenter, mapZoom, position, coordinates, clusters, supercluster, onPinHover, onPinClick, focusPoint, radiusMiles, className, setBounds, setZoomLevel, }: MapContentProps<T>): React.JSX.Element;
|
|
5
|
+
|
|
6
|
+
export { MapContent };
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/components/ui/Map/MapContent.tsx
|
|
4
|
+
import { AdvancedMarker as AdvancedMarker3, Map, Pin as Pin2, useMap, useMapsLibrary } from "@vis.gl/react-google-maps";
|
|
5
|
+
import { useCallback } from "react";
|
|
6
|
+
|
|
7
|
+
// src/components/ui/Map/ClusterMarker.tsx
|
|
8
|
+
import { AdvancedMarker } from "@vis.gl/react-google-maps";
|
|
9
|
+
|
|
10
|
+
// src/components/ui/Map/constants.ts
|
|
11
|
+
var CLUSTER_DISTANCE_THRESHOLD = 1e-3;
|
|
12
|
+
var PIN_COLORS = {
|
|
13
|
+
background: "#0B5441",
|
|
14
|
+
borderColor: "#EBFDF1",
|
|
15
|
+
glyphColor: "#D4F500"
|
|
16
|
+
};
|
|
17
|
+
var FOCUS_CIRCLE_STYLES = {
|
|
18
|
+
strokeColor: "#0B5441",
|
|
19
|
+
strokeOpacity: 0.8,
|
|
20
|
+
strokeWeight: 2,
|
|
21
|
+
fillColor: "#0B5441",
|
|
22
|
+
fillOpacity: 0.1,
|
|
23
|
+
clickable: false,
|
|
24
|
+
zIndex: 1
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// src/components/ui/Map/utils.ts
|
|
28
|
+
function filterClusterCoordinates(coordinates, clusterLat, clusterLng) {
|
|
29
|
+
return coordinates.filter((coord) => {
|
|
30
|
+
const latDiff = Math.abs(coord.lat - clusterLat);
|
|
31
|
+
const lngDiff = Math.abs(coord.lng - clusterLng);
|
|
32
|
+
const distance = Math.sqrt(latDiff * latDiff + lngDiff * lngDiff);
|
|
33
|
+
return distance < CLUSTER_DISTANCE_THRESHOLD;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/components/ui/Map/ClusterMarker.tsx
|
|
38
|
+
function ClusterMarker({
|
|
39
|
+
cluster,
|
|
40
|
+
coordinates,
|
|
41
|
+
onPinClick,
|
|
42
|
+
onPinHover,
|
|
43
|
+
zoomToLevel,
|
|
44
|
+
supercluster
|
|
45
|
+
}) {
|
|
46
|
+
const [lng, lat] = cluster.geometry.coordinates;
|
|
47
|
+
const { point_count: pointCount } = cluster.properties;
|
|
48
|
+
const handleClick = () => {
|
|
49
|
+
const clusterCoordinates = filterClusterCoordinates(coordinates, lat, lng);
|
|
50
|
+
onPinClick?.(clusterCoordinates);
|
|
51
|
+
const expansionZoom = supercluster.getClusterExpansionZoom(cluster.id);
|
|
52
|
+
zoomToLevel(expansionZoom);
|
|
53
|
+
};
|
|
54
|
+
const handleMouseEnter = () => {
|
|
55
|
+
const clusterCoordinates = filterClusterCoordinates(coordinates, lat, lng);
|
|
56
|
+
onPinHover?.(clusterCoordinates);
|
|
57
|
+
};
|
|
58
|
+
const handleMouseLeave = () => onPinHover?.(null);
|
|
59
|
+
return /* @__PURE__ */ React.createElement(
|
|
60
|
+
AdvancedMarker,
|
|
61
|
+
{
|
|
62
|
+
key: `cluster-${cluster.id}`,
|
|
63
|
+
position: { lat, lng },
|
|
64
|
+
onClick: handleClick,
|
|
65
|
+
onMouseEnter: handleMouseEnter,
|
|
66
|
+
onMouseLeave: handleMouseLeave
|
|
67
|
+
},
|
|
68
|
+
/* @__PURE__ */ React.createElement("div", { className: "relative flex items-center justify-center", id: "CLUSTER_MARKER" }, /* @__PURE__ */ React.createElement("div", { className: "flex h-8 w-8 items-center justify-center rounded-full border-2 border-white bg-red-500 text-sm font-bold text-white shadow-lg" }, pointCount || "?"))
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/components/ui/Map/FocusCircle.tsx
|
|
73
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
74
|
+
function FocusCircle({
|
|
75
|
+
focusPoint,
|
|
76
|
+
radiusMiles,
|
|
77
|
+
map,
|
|
78
|
+
mapsLibrary
|
|
79
|
+
}) {
|
|
80
|
+
const circleRef = useRef(null);
|
|
81
|
+
const circleProps = useMemo(() => {
|
|
82
|
+
if (!focusPoint || !radiusMiles) return null;
|
|
83
|
+
return {
|
|
84
|
+
center: focusPoint,
|
|
85
|
+
radius: radiusMiles * 1609.34
|
|
86
|
+
};
|
|
87
|
+
}, [focusPoint, radiusMiles]);
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (!map || !mapsLibrary || !circleProps) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (!circleRef.current) {
|
|
93
|
+
const circle = new google.maps.Circle({
|
|
94
|
+
center: circleProps.center,
|
|
95
|
+
radius: circleProps.radius,
|
|
96
|
+
...FOCUS_CIRCLE_STYLES,
|
|
97
|
+
map
|
|
98
|
+
});
|
|
99
|
+
circleRef.current = circle;
|
|
100
|
+
} else {
|
|
101
|
+
circleRef.current.setCenter(circleProps.center);
|
|
102
|
+
circleRef.current.setRadius(circleProps.radius);
|
|
103
|
+
}
|
|
104
|
+
}, [map, mapsLibrary, circleProps]);
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
return () => {
|
|
107
|
+
if (circleRef.current) {
|
|
108
|
+
circleRef.current.setMap(null);
|
|
109
|
+
circleRef.current = null;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}, []);
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/components/ui/Map/IndividualMarker.tsx
|
|
117
|
+
import { AdvancedMarker as AdvancedMarker2, Pin } from "@vis.gl/react-google-maps";
|
|
118
|
+
function IndividualMarker({
|
|
119
|
+
coordinate,
|
|
120
|
+
onPinClick,
|
|
121
|
+
onPinHover
|
|
122
|
+
}) {
|
|
123
|
+
const handleMouseEnter = () => onPinHover?.(coordinate);
|
|
124
|
+
const handleMouseLeave = () => onPinHover?.(null);
|
|
125
|
+
const handleClick = () => onPinClick?.(coordinate);
|
|
126
|
+
return /* @__PURE__ */ React.createElement(
|
|
127
|
+
AdvancedMarker2,
|
|
128
|
+
{
|
|
129
|
+
position: { lat: coordinate.lat, lng: coordinate.lng },
|
|
130
|
+
onMouseEnter: handleMouseEnter,
|
|
131
|
+
onMouseLeave: handleMouseLeave,
|
|
132
|
+
onClick: handleClick
|
|
133
|
+
},
|
|
134
|
+
/* @__PURE__ */ React.createElement(Pin, { ...PIN_COLORS })
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/lib/utils.ts
|
|
139
|
+
import { clsx } from "clsx";
|
|
140
|
+
import { twMerge } from "tailwind-merge";
|
|
141
|
+
function cn(...inputs) {
|
|
142
|
+
return twMerge(clsx(inputs));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/components/ui/Map/MapContent.tsx
|
|
146
|
+
function MapContent({
|
|
147
|
+
mapId,
|
|
148
|
+
mapCenter,
|
|
149
|
+
mapZoom,
|
|
150
|
+
position,
|
|
151
|
+
coordinates,
|
|
152
|
+
clusters,
|
|
153
|
+
supercluster,
|
|
154
|
+
onPinHover,
|
|
155
|
+
onPinClick,
|
|
156
|
+
focusPoint,
|
|
157
|
+
radiusMiles,
|
|
158
|
+
className,
|
|
159
|
+
setBounds,
|
|
160
|
+
setZoomLevel
|
|
161
|
+
}) {
|
|
162
|
+
const map = useMap();
|
|
163
|
+
const mapsLibrary = useMapsLibrary("maps");
|
|
164
|
+
const zoomToLevel = useCallback(
|
|
165
|
+
(newZoom) => {
|
|
166
|
+
if (map) {
|
|
167
|
+
map.setZoom(newZoom);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
[map]
|
|
171
|
+
);
|
|
172
|
+
const handleBoundsChanged = (e) => {
|
|
173
|
+
if (e.detail.bounds) {
|
|
174
|
+
const bounds = e.detail.bounds;
|
|
175
|
+
setBounds([
|
|
176
|
+
[bounds.south, bounds.west],
|
|
177
|
+
[bounds.north, bounds.east]
|
|
178
|
+
]);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const handleZoomChanged = (e) => {
|
|
182
|
+
if (e.detail.zoom) {
|
|
183
|
+
setZoomLevel(e.detail.zoom);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const handleCameraChanged = (e) => {
|
|
187
|
+
if (e.detail.zoom) {
|
|
188
|
+
setZoomLevel(e.detail.zoom);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
return /* @__PURE__ */ React.createElement("div", { className: cn("relative h-screen max-w-full", className) }, /* @__PURE__ */ React.createElement(
|
|
192
|
+
Map,
|
|
193
|
+
{
|
|
194
|
+
defaultZoom: mapZoom,
|
|
195
|
+
defaultCenter: mapCenter,
|
|
196
|
+
mapId,
|
|
197
|
+
keyboardShortcuts: true,
|
|
198
|
+
disableDefaultUI: true,
|
|
199
|
+
zoomControl: true,
|
|
200
|
+
onBoundsChanged: handleBoundsChanged,
|
|
201
|
+
onZoomChanged: handleZoomChanged,
|
|
202
|
+
onCameraChanged: handleCameraChanged
|
|
203
|
+
},
|
|
204
|
+
position && !coordinates && /* @__PURE__ */ React.createElement(AdvancedMarker3, { position }, /* @__PURE__ */ React.createElement(Pin2, { ...PIN_COLORS })),
|
|
205
|
+
coordinates && clusters.map((cluster) => {
|
|
206
|
+
const { cluster: isCluster } = cluster.properties;
|
|
207
|
+
if (isCluster) {
|
|
208
|
+
return /* @__PURE__ */ React.createElement(
|
|
209
|
+
ClusterMarker,
|
|
210
|
+
{
|
|
211
|
+
key: `cluster-${cluster.id}`,
|
|
212
|
+
cluster,
|
|
213
|
+
coordinates,
|
|
214
|
+
onPinClick,
|
|
215
|
+
onPinHover,
|
|
216
|
+
zoomToLevel,
|
|
217
|
+
supercluster
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
const originalPoint = coordinates[cluster.properties.pointId];
|
|
222
|
+
return /* @__PURE__ */ React.createElement(
|
|
223
|
+
IndividualMarker,
|
|
224
|
+
{
|
|
225
|
+
key: `marker-${cluster.properties.pointId}`,
|
|
226
|
+
coordinate: originalPoint,
|
|
227
|
+
onPinClick,
|
|
228
|
+
onPinHover
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
}),
|
|
232
|
+
coordinates && clusters.length === 0 && coordinates.map((coord, index) => /* @__PURE__ */ React.createElement(
|
|
233
|
+
IndividualMarker,
|
|
234
|
+
{
|
|
235
|
+
key: `fallback-${index}`,
|
|
236
|
+
coordinate: coord,
|
|
237
|
+
onPinClick,
|
|
238
|
+
onPinHover
|
|
239
|
+
}
|
|
240
|
+
)),
|
|
241
|
+
focusPoint && radiusMiles && /* @__PURE__ */ React.createElement(
|
|
242
|
+
FocusCircle,
|
|
243
|
+
{
|
|
244
|
+
focusPoint,
|
|
245
|
+
radiusMiles,
|
|
246
|
+
map,
|
|
247
|
+
mapsLibrary
|
|
248
|
+
}
|
|
249
|
+
)
|
|
250
|
+
));
|
|
251
|
+
}
|
|
252
|
+
export {
|
|
253
|
+
MapContent
|
|
254
|
+
};
|
|
255
|
+
//# sourceMappingURL=MapContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ui/Map/MapContent.tsx","../../../../src/components/ui/Map/ClusterMarker.tsx","../../../../src/components/ui/Map/constants.ts","../../../../src/components/ui/Map/utils.ts","../../../../src/components/ui/Map/FocusCircle.tsx","../../../../src/components/ui/Map/IndividualMarker.tsx","../../../../src/lib/utils.ts"],"sourcesContent":["'use client'\n\nimport { AdvancedMarker, Map, Pin, useMap, useMapsLibrary } from '@vis.gl/react-google-maps'\nimport { useCallback } from 'react'\n\nimport { ClusterMarker } from '@/components/ui/Map/ClusterMarker'\nimport { PIN_COLORS } from '@/components/ui/Map/constants'\nimport { FocusCircle } from '@/components/ui/Map/FocusCircle'\nimport { IndividualMarker } from '@/components/ui/Map/IndividualMarker'\nimport type { MapContentProps, PinData } from '@/components/ui/Map/types'\nimport { cn } from '@/lib/utils'\n\nexport function MapContent<T = PinData>({\n mapId,\n mapCenter,\n mapZoom,\n position,\n coordinates,\n clusters,\n supercluster,\n onPinHover,\n onPinClick,\n focusPoint,\n radiusMiles,\n className,\n setBounds,\n setZoomLevel,\n}: MapContentProps<T>) {\n const map = useMap()\n const mapsLibrary = useMapsLibrary('maps')\n\n const zoomToLevel = useCallback(\n (newZoom: number) => {\n if (map) {\n map.setZoom(newZoom)\n }\n },\n [map]\n )\n\n const handleBoundsChanged = (e: {\n detail: { bounds: { south: number; west: number; north: number; east: number } }\n }) => {\n if (e.detail.bounds) {\n const bounds = e.detail.bounds\n setBounds([\n [bounds.south, bounds.west],\n [bounds.north, bounds.east],\n ])\n }\n }\n\n const handleZoomChanged = (e: { detail: { zoom: number } }) => {\n if (e.detail.zoom) {\n setZoomLevel(e.detail.zoom)\n }\n }\n\n const handleCameraChanged = (e: { detail: { zoom: number } }) => {\n if (e.detail.zoom) {\n setZoomLevel(e.detail.zoom)\n }\n }\n\n return (\n <div className={cn('relative h-screen max-w-full', className)}>\n <Map\n defaultZoom={mapZoom}\n defaultCenter={mapCenter}\n mapId={mapId}\n keyboardShortcuts={true}\n disableDefaultUI={true}\n zoomControl={true}\n onBoundsChanged={handleBoundsChanged}\n onZoomChanged={handleZoomChanged}\n onCameraChanged={handleCameraChanged}\n >\n {position && !coordinates && (\n <AdvancedMarker position={position}>\n <Pin {...PIN_COLORS} />\n </AdvancedMarker>\n )}\n\n {coordinates &&\n clusters.map((cluster) => {\n const { cluster: isCluster } = cluster.properties\n\n if (isCluster) {\n return (\n <ClusterMarker\n key={`cluster-${cluster.id}`}\n cluster={cluster}\n coordinates={coordinates}\n onPinClick={onPinClick}\n onPinHover={onPinHover}\n zoomToLevel={zoomToLevel}\n supercluster={supercluster}\n />\n )\n }\n\n const originalPoint = coordinates[cluster.properties.pointId!]\n return (\n <IndividualMarker\n key={`marker-${cluster.properties.pointId}`}\n coordinate={originalPoint}\n onPinClick={onPinClick}\n onPinHover={onPinHover}\n />\n )\n })}\n\n {coordinates &&\n clusters.length === 0 &&\n coordinates.map((coord, index) => (\n <IndividualMarker\n key={`fallback-${index}`}\n coordinate={coord}\n onPinClick={onPinClick}\n onPinHover={onPinHover}\n />\n ))}\n\n {focusPoint && radiusMiles && (\n <FocusCircle\n focusPoint={focusPoint}\n radiusMiles={radiusMiles}\n map={map}\n mapsLibrary={mapsLibrary}\n />\n )}\n </Map>\n </div>\n )\n}\n","'use client'\n\nimport { AdvancedMarker } from '@vis.gl/react-google-maps'\n\nimport type { ClusterMarkerProps, PinData } from '@/components/ui/Map/types'\nimport { filterClusterCoordinates } from '@/components/ui/Map/utils'\n\nexport function ClusterMarker<T = PinData>({\n cluster,\n coordinates,\n onPinClick,\n onPinHover,\n zoomToLevel,\n supercluster,\n}: ClusterMarkerProps<T>) {\n const [lng, lat] = cluster.geometry.coordinates\n const { point_count: pointCount } = cluster.properties\n\n const handleClick = () => {\n const clusterCoordinates = filterClusterCoordinates(coordinates, lat, lng)\n onPinClick?.(clusterCoordinates)\n\n const expansionZoom = supercluster.getClusterExpansionZoom(cluster.id)\n zoomToLevel(expansionZoom)\n }\n\n const handleMouseEnter = () => {\n const clusterCoordinates = filterClusterCoordinates(coordinates, lat, lng)\n onPinHover?.(clusterCoordinates)\n }\n\n const handleMouseLeave = () => onPinHover?.(null)\n\n return (\n <AdvancedMarker\n key={`cluster-${cluster.id}`}\n position={{ lat, lng }}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n >\n <div className=\"relative flex items-center justify-center\" id=\"CLUSTER_MARKER\">\n <div className=\"flex h-8 w-8 items-center justify-center rounded-full border-2 border-white bg-red-500 text-sm font-bold text-white shadow-lg\">\n {pointCount || '?'}\n </div>\n </div>\n </AdvancedMarker>\n )\n}\n","export const DEFAULT_POSITION = { lat: 40.715021, lng: -74.00459 }\nexport const DEFAULT_ZOOM = 10\nexport const CLUSTER_PIN_SCALE = 1.5\nexport const CLUSTER_DISTANCE_THRESHOLD = 0.001\n\nexport const PIN_COLORS = {\n background: '#0B5441',\n borderColor: '#EBFDF1',\n glyphColor: '#D4F500',\n} as const\n\nexport const FOCUS_CIRCLE_STYLES = {\n strokeColor: '#0B5441',\n strokeOpacity: 0.8,\n strokeWeight: 2,\n fillColor: '#0B5441',\n fillOpacity: 0.1,\n clickable: false,\n zIndex: 1,\n} as const\n\nexport const CLUSTERING_CONFIG = {\n radius: 60,\n maxZoom: 16,\n minPoints: 2,\n} as const\n","import { CLUSTER_DISTANCE_THRESHOLD, DEFAULT_POSITION } from '@/components/ui/Map/constants'\nimport type { Coordinate, PinData } from '@/components/ui/Map/types'\n\nexport function getCenterForCoordinates<T = PinData>(coords: Coordinate<T>[]): Coordinate<T> {\n if (coords.length === 0) return DEFAULT_POSITION as Coordinate<T>\n\n const avgLat = coords.reduce((sum, coord) => sum + coord.lat, 0) / coords.length\n const avgLng = coords.reduce((sum, coord) => sum + coord.lng, 0) / coords.length\n\n return { lat: avgLat, lng: avgLng }\n}\n\nexport function getZoomForCoordinates<T = PinData>(\n coords: Coordinate<T>[],\n defaultZoom: number\n): number {\n if (coords.length <= 1) return defaultZoom\n\n const lats = coords.map((coord) => coord.lat)\n const lngs = coords.map((coord) => coord.lng)\n\n const latDiff = Math.max(...lats) - Math.min(...lats)\n const lngDiff = Math.max(...lngs) - Math.min(...lngs)\n const maxDiff = Math.max(latDiff, lngDiff)\n\n if (maxDiff > 0.1) return 8\n if (maxDiff > 0.05) return 10\n if (maxDiff > 0.01) return 12\n return 14\n}\n\nexport function getClusteringRadius(zoom: number): number {\n if (zoom <= 8) return 200\n if (zoom <= 12) return 150\n return 100\n}\n\nexport function filterClusterCoordinates<T = PinData>(\n coordinates: Coordinate<T>[],\n clusterLat: number,\n clusterLng: number\n): Coordinate<T>[] {\n return coordinates.filter((coord) => {\n const latDiff = Math.abs(coord.lat - clusterLat)\n const lngDiff = Math.abs(coord.lng - clusterLng)\n const distance = Math.sqrt(latDiff * latDiff + lngDiff * lngDiff)\n return distance < CLUSTER_DISTANCE_THRESHOLD\n })\n}\n\nexport function calculateDistance<T = PinData>(\n coord1: Coordinate<T>,\n coord2: Coordinate<T>\n): number {\n const latDiff = Math.abs(coord1.lat - coord2.lat)\n const lngDiff = Math.abs(coord1.lng - coord2.lng)\n return Math.sqrt(latDiff * latDiff + lngDiff * lngDiff)\n}\n","'use client'\n\nimport { useEffect, useMemo, useRef } from 'react'\n\nimport { FOCUS_CIRCLE_STYLES } from '@/components/ui/Map/constants'\nimport type { FocusCircleProps, PinData } from '@/components/ui/Map/types'\n\nexport function FocusCircle<T = PinData>({\n focusPoint,\n radiusMiles,\n map,\n mapsLibrary,\n}: FocusCircleProps<T>) {\n const circleRef = useRef<google.maps.Circle | null>(null)\n\n const circleProps = useMemo(() => {\n if (!focusPoint || !radiusMiles) return null\n return {\n center: focusPoint,\n radius: radiusMiles * 1609.34,\n }\n }, [focusPoint, radiusMiles])\n\n useEffect(() => {\n if (!map || !mapsLibrary || !circleProps) {\n return\n }\n\n if (!circleRef.current) {\n const circle = new google.maps.Circle({\n center: circleProps.center,\n radius: circleProps.radius,\n ...FOCUS_CIRCLE_STYLES,\n map: map,\n })\n\n circleRef.current = circle\n } else {\n circleRef.current.setCenter(circleProps.center)\n circleRef.current.setRadius(circleProps.radius)\n }\n }, [map, mapsLibrary, circleProps])\n\n useEffect(() => {\n return () => {\n if (circleRef.current) {\n circleRef.current.setMap(null)\n circleRef.current = null\n }\n }\n }, [])\n\n return null\n}\n","'use client'\n\nimport { AdvancedMarker, Pin } from '@vis.gl/react-google-maps'\n\nimport { PIN_COLORS } from '@/components/ui/Map/constants'\nimport type { IndividualMarkerProps, PinData } from '@/components/ui/Map/types'\n\nexport function IndividualMarker<T = PinData>({\n coordinate,\n onPinClick,\n onPinHover,\n}: IndividualMarkerProps<T>) {\n const handleMouseEnter = () => onPinHover?.(coordinate)\n const handleMouseLeave = () => onPinHover?.(null)\n const handleClick = () => onPinClick?.(coordinate)\n\n return (\n <AdvancedMarker\n position={{ lat: coordinate.lat, lng: coordinate.lng }}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleClick}\n >\n <Pin {...PIN_COLORS} />\n </AdvancedMarker>\n )\n}\n","import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":"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","names":["AdvancedMarker","Pin","AdvancedMarker","AdvancedMarker","AdvancedMarker","Pin"]}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/components/ui/Map/clustering.ts
|
|
21
|
+
var clustering_exports = {};
|
|
22
|
+
__export(clustering_exports, {
|
|
23
|
+
convertCoordinatesToGeoJSON: () => convertCoordinatesToGeoJSON,
|
|
24
|
+
createManualClusters: () => createManualClusters
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(clustering_exports);
|
|
27
|
+
|
|
28
|
+
// src/components/ui/Map/constants.ts
|
|
29
|
+
var CLUSTER_DISTANCE_THRESHOLD = 1e-3;
|
|
30
|
+
|
|
31
|
+
// src/components/ui/Map/utils.ts
|
|
32
|
+
function calculateDistance(coord1, coord2) {
|
|
33
|
+
const latDiff = Math.abs(coord1.lat - coord2.lat);
|
|
34
|
+
const lngDiff = Math.abs(coord1.lng - coord2.lng);
|
|
35
|
+
return Math.sqrt(latDiff * latDiff + lngDiff * lngDiff);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/components/ui/Map/clustering.ts
|
|
39
|
+
function convertCoordinatesToGeoJSON(coordinates) {
|
|
40
|
+
return coordinates.map((coord, index) => ({
|
|
41
|
+
type: "Feature",
|
|
42
|
+
properties: {
|
|
43
|
+
cluster: false,
|
|
44
|
+
pointId: index,
|
|
45
|
+
data: coord.data
|
|
46
|
+
},
|
|
47
|
+
geometry: {
|
|
48
|
+
type: "Point",
|
|
49
|
+
coordinates: [coord.lng, coord.lat]
|
|
50
|
+
}
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
function createManualClusters(coordinates) {
|
|
54
|
+
if (!coordinates || coordinates.length === 0) return [];
|
|
55
|
+
const clusters = [];
|
|
56
|
+
const processed = /* @__PURE__ */ new Set();
|
|
57
|
+
coordinates.forEach((coord, index) => {
|
|
58
|
+
if (processed.has(index)) return;
|
|
59
|
+
const nearby = [index];
|
|
60
|
+
coordinates.forEach((otherCoord, otherIndex) => {
|
|
61
|
+
if (otherIndex === index || processed.has(otherIndex)) return;
|
|
62
|
+
const distance = calculateDistance(coord, otherCoord);
|
|
63
|
+
if (distance < CLUSTER_DISTANCE_THRESHOLD) {
|
|
64
|
+
nearby.push(otherIndex);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
if (nearby.length >= 2) {
|
|
68
|
+
clusters.push({
|
|
69
|
+
type: "Feature",
|
|
70
|
+
properties: {
|
|
71
|
+
cluster: true,
|
|
72
|
+
point_count: nearby.length
|
|
73
|
+
},
|
|
74
|
+
geometry: {
|
|
75
|
+
type: "Point",
|
|
76
|
+
coordinates: [coord.lng, coord.lat]
|
|
77
|
+
},
|
|
78
|
+
id: clusters.length
|
|
79
|
+
});
|
|
80
|
+
nearby.forEach((i) => processed.add(i));
|
|
81
|
+
} else {
|
|
82
|
+
clusters.push({
|
|
83
|
+
type: "Feature",
|
|
84
|
+
properties: {
|
|
85
|
+
cluster: false,
|
|
86
|
+
pointId: index,
|
|
87
|
+
data: coord.data
|
|
88
|
+
},
|
|
89
|
+
geometry: {
|
|
90
|
+
type: "Point",
|
|
91
|
+
coordinates: [coord.lng, coord.lat]
|
|
92
|
+
},
|
|
93
|
+
id: clusters.length
|
|
94
|
+
});
|
|
95
|
+
processed.add(index);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return clusters;
|
|
99
|
+
}
|
|
100
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
101
|
+
0 && (module.exports = {
|
|
102
|
+
convertCoordinatesToGeoJSON,
|
|
103
|
+
createManualClusters
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=clustering.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ui/Map/clustering.ts","../../../../src/components/ui/Map/constants.ts","../../../../src/components/ui/Map/utils.ts"],"sourcesContent":["import { CLUSTER_DISTANCE_THRESHOLD } from '@/components/ui/Map/constants'\nimport type { ClusterFeature, Coordinate, PinData } from '@/components/ui/Map/types'\nimport { calculateDistance } from '@/components/ui/Map/utils'\n\nexport function convertCoordinatesToGeoJSON<T = PinData>(coordinates: Coordinate<T>[]) {\n return coordinates.map((coord, index) => ({\n type: 'Feature' as const,\n properties: {\n cluster: false,\n pointId: index,\n data: coord.data,\n },\n geometry: {\n type: 'Point' as const,\n coordinates: [coord.lng, coord.lat],\n },\n }))\n}\n\nexport function createManualClusters<T = PinData>(\n coordinates: Coordinate<T>[]\n): ClusterFeature<T>[] {\n if (!coordinates || coordinates.length === 0) return []\n\n const clusters: ClusterFeature<T>[] = []\n const processed = new Set<number>()\n\n coordinates.forEach((coord, index) => {\n if (processed.has(index)) return\n\n const nearby: number[] = [index]\n coordinates.forEach((otherCoord, otherIndex) => {\n if (otherIndex === index || processed.has(otherIndex)) return\n\n const distance = calculateDistance(coord, otherCoord)\n\n if (distance < CLUSTER_DISTANCE_THRESHOLD) {\n nearby.push(otherIndex)\n }\n })\n\n if (nearby.length >= 2) {\n clusters.push({\n type: 'Feature' as const,\n properties: {\n cluster: true,\n point_count: nearby.length,\n },\n geometry: {\n type: 'Point' as const,\n coordinates: [coord.lng, coord.lat],\n },\n id: clusters.length,\n })\n\n nearby.forEach((i) => processed.add(i))\n } else {\n clusters.push({\n type: 'Feature' as const,\n properties: {\n cluster: false,\n pointId: index,\n data: coord.data,\n },\n geometry: {\n type: 'Point' as const,\n coordinates: [coord.lng, coord.lat],\n },\n id: clusters.length,\n })\n processed.add(index)\n }\n })\n\n return clusters\n}\n","export const DEFAULT_POSITION = { lat: 40.715021, lng: -74.00459 }\nexport const DEFAULT_ZOOM = 10\nexport const CLUSTER_PIN_SCALE = 1.5\nexport const CLUSTER_DISTANCE_THRESHOLD = 0.001\n\nexport const PIN_COLORS = {\n background: '#0B5441',\n borderColor: '#EBFDF1',\n glyphColor: '#D4F500',\n} as const\n\nexport const FOCUS_CIRCLE_STYLES = {\n strokeColor: '#0B5441',\n strokeOpacity: 0.8,\n strokeWeight: 2,\n fillColor: '#0B5441',\n fillOpacity: 0.1,\n clickable: false,\n zIndex: 1,\n} as const\n\nexport const CLUSTERING_CONFIG = {\n radius: 60,\n maxZoom: 16,\n minPoints: 2,\n} as const\n","import { CLUSTER_DISTANCE_THRESHOLD, DEFAULT_POSITION } from '@/components/ui/Map/constants'\nimport type { Coordinate, PinData } from '@/components/ui/Map/types'\n\nexport function getCenterForCoordinates<T = PinData>(coords: Coordinate<T>[]): Coordinate<T> {\n if (coords.length === 0) return DEFAULT_POSITION as Coordinate<T>\n\n const avgLat = coords.reduce((sum, coord) => sum + coord.lat, 0) / coords.length\n const avgLng = coords.reduce((sum, coord) => sum + coord.lng, 0) / coords.length\n\n return { lat: avgLat, lng: avgLng }\n}\n\nexport function getZoomForCoordinates<T = PinData>(\n coords: Coordinate<T>[],\n defaultZoom: number\n): number {\n if (coords.length <= 1) return defaultZoom\n\n const lats = coords.map((coord) => coord.lat)\n const lngs = coords.map((coord) => coord.lng)\n\n const latDiff = Math.max(...lats) - Math.min(...lats)\n const lngDiff = Math.max(...lngs) - Math.min(...lngs)\n const maxDiff = Math.max(latDiff, lngDiff)\n\n if (maxDiff > 0.1) return 8\n if (maxDiff > 0.05) return 10\n if (maxDiff > 0.01) return 12\n return 14\n}\n\nexport function getClusteringRadius(zoom: number): number {\n if (zoom <= 8) return 200\n if (zoom <= 12) return 150\n return 100\n}\n\nexport function filterClusterCoordinates<T = PinData>(\n coordinates: Coordinate<T>[],\n clusterLat: number,\n clusterLng: number\n): Coordinate<T>[] {\n return coordinates.filter((coord) => {\n const latDiff = Math.abs(coord.lat - clusterLat)\n const lngDiff = Math.abs(coord.lng - clusterLng)\n const distance = Math.sqrt(latDiff * latDiff + lngDiff * lngDiff)\n return distance < CLUSTER_DISTANCE_THRESHOLD\n })\n}\n\nexport function calculateDistance<T = PinData>(\n coord1: Coordinate<T>,\n coord2: Coordinate<T>\n): number {\n const latDiff = Math.abs(coord1.lat - coord2.lat)\n const lngDiff = Math.abs(coord1.lng - coord2.lng)\n return Math.sqrt(latDiff * latDiff + lngDiff * lngDiff)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGO,IAAM,6BAA6B;;;AC+CnC,SAAS,kBACd,QACA,QACQ;AACR,QAAM,UAAU,KAAK,IAAI,OAAO,MAAM,OAAO,GAAG;AAChD,QAAM,UAAU,KAAK,IAAI,OAAO,MAAM,OAAO,GAAG;AAChD,SAAO,KAAK,KAAK,UAAU,UAAU,UAAU,OAAO;AACxD;;;AFrDO,SAAS,4BAAyC,aAA8B;AACrF,SAAO,YAAY,IAAI,CAAC,OAAO,WAAW;AAAA,IACxC,MAAM;AAAA,IACN,YAAY;AAAA,MACV,SAAS;AAAA,MACT,SAAS;AAAA,MACT,MAAM,MAAM;AAAA,IACd;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,aAAa,CAAC,MAAM,KAAK,MAAM,GAAG;AAAA,IACpC;AAAA,EACF,EAAE;AACJ;AAEO,SAAS,qBACd,aACqB;AACrB,MAAI,CAAC,eAAe,YAAY,WAAW,EAAG,QAAO,CAAC;AAEtD,QAAM,WAAgC,CAAC;AACvC,QAAM,YAAY,oBAAI,IAAY;AAElC,cAAY,QAAQ,CAAC,OAAO,UAAU;AACpC,QAAI,UAAU,IAAI,KAAK,EAAG;AAE1B,UAAM,SAAmB,CAAC,KAAK;AAC/B,gBAAY,QAAQ,CAAC,YAAY,eAAe;AAC9C,UAAI,eAAe,SAAS,UAAU,IAAI,UAAU,EAAG;AAEvD,YAAM,WAAW,kBAAkB,OAAO,UAAU;AAEpD,UAAI,WAAW,4BAA4B;AACzC,eAAO,KAAK,UAAU;AAAA,MACxB;AAAA,IACF,CAAC;AAED,QAAI,OAAO,UAAU,GAAG;AACtB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS;AAAA,UACT,aAAa,OAAO;AAAA,QACtB;AAAA,QACA,UAAU;AAAA,UACR,MAAM;AAAA,UACN,aAAa,CAAC,MAAM,KAAK,MAAM,GAAG;AAAA,QACpC;AAAA,QACA,IAAI,SAAS;AAAA,MACf,CAAC;AAED,aAAO,QAAQ,CAAC,MAAM,UAAU,IAAI,CAAC,CAAC;AAAA,IACxC,OAAO;AACL,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS;AAAA,UACT,SAAS;AAAA,UACT,MAAM,MAAM;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,MAAM;AAAA,UACN,aAAa,CAAC,MAAM,KAAK,MAAM,GAAG;AAAA,QACpC;AAAA,QACA,IAAI,SAAS;AAAA,MACf,CAAC;AACD,gBAAU,IAAI,KAAK;AAAA,IACrB;AAAA,EACF,CAAC;AAED,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PinData, Coordinate, ClusterFeature } from './types.cjs';
|
|
2
|
+
|
|
3
|
+
declare function convertCoordinatesToGeoJSON<T = PinData>(coordinates: Coordinate<T>[]): {
|
|
4
|
+
type: "Feature";
|
|
5
|
+
properties: {
|
|
6
|
+
cluster: boolean;
|
|
7
|
+
pointId: number;
|
|
8
|
+
data: T | undefined;
|
|
9
|
+
};
|
|
10
|
+
geometry: {
|
|
11
|
+
type: "Point";
|
|
12
|
+
coordinates: number[];
|
|
13
|
+
};
|
|
14
|
+
}[];
|
|
15
|
+
declare function createManualClusters<T = PinData>(coordinates: Coordinate<T>[]): ClusterFeature<T>[];
|
|
16
|
+
|
|
17
|
+
export { convertCoordinatesToGeoJSON, createManualClusters };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PinData, Coordinate, ClusterFeature } from './types.js';
|
|
2
|
+
|
|
3
|
+
declare function convertCoordinatesToGeoJSON<T = PinData>(coordinates: Coordinate<T>[]): {
|
|
4
|
+
type: "Feature";
|
|
5
|
+
properties: {
|
|
6
|
+
cluster: boolean;
|
|
7
|
+
pointId: number;
|
|
8
|
+
data: T | undefined;
|
|
9
|
+
};
|
|
10
|
+
geometry: {
|
|
11
|
+
type: "Point";
|
|
12
|
+
coordinates: number[];
|
|
13
|
+
};
|
|
14
|
+
}[];
|
|
15
|
+
declare function createManualClusters<T = PinData>(coordinates: Coordinate<T>[]): ClusterFeature<T>[];
|
|
16
|
+
|
|
17
|
+
export { convertCoordinatesToGeoJSON, createManualClusters };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// src/components/ui/Map/constants.ts
|
|
2
|
+
var CLUSTER_DISTANCE_THRESHOLD = 1e-3;
|
|
3
|
+
|
|
4
|
+
// src/components/ui/Map/utils.ts
|
|
5
|
+
function calculateDistance(coord1, coord2) {
|
|
6
|
+
const latDiff = Math.abs(coord1.lat - coord2.lat);
|
|
7
|
+
const lngDiff = Math.abs(coord1.lng - coord2.lng);
|
|
8
|
+
return Math.sqrt(latDiff * latDiff + lngDiff * lngDiff);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/components/ui/Map/clustering.ts
|
|
12
|
+
function convertCoordinatesToGeoJSON(coordinates) {
|
|
13
|
+
return coordinates.map((coord, index) => ({
|
|
14
|
+
type: "Feature",
|
|
15
|
+
properties: {
|
|
16
|
+
cluster: false,
|
|
17
|
+
pointId: index,
|
|
18
|
+
data: coord.data
|
|
19
|
+
},
|
|
20
|
+
geometry: {
|
|
21
|
+
type: "Point",
|
|
22
|
+
coordinates: [coord.lng, coord.lat]
|
|
23
|
+
}
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
function createManualClusters(coordinates) {
|
|
27
|
+
if (!coordinates || coordinates.length === 0) return [];
|
|
28
|
+
const clusters = [];
|
|
29
|
+
const processed = /* @__PURE__ */ new Set();
|
|
30
|
+
coordinates.forEach((coord, index) => {
|
|
31
|
+
if (processed.has(index)) return;
|
|
32
|
+
const nearby = [index];
|
|
33
|
+
coordinates.forEach((otherCoord, otherIndex) => {
|
|
34
|
+
if (otherIndex === index || processed.has(otherIndex)) return;
|
|
35
|
+
const distance = calculateDistance(coord, otherCoord);
|
|
36
|
+
if (distance < CLUSTER_DISTANCE_THRESHOLD) {
|
|
37
|
+
nearby.push(otherIndex);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
if (nearby.length >= 2) {
|
|
41
|
+
clusters.push({
|
|
42
|
+
type: "Feature",
|
|
43
|
+
properties: {
|
|
44
|
+
cluster: true,
|
|
45
|
+
point_count: nearby.length
|
|
46
|
+
},
|
|
47
|
+
geometry: {
|
|
48
|
+
type: "Point",
|
|
49
|
+
coordinates: [coord.lng, coord.lat]
|
|
50
|
+
},
|
|
51
|
+
id: clusters.length
|
|
52
|
+
});
|
|
53
|
+
nearby.forEach((i) => processed.add(i));
|
|
54
|
+
} else {
|
|
55
|
+
clusters.push({
|
|
56
|
+
type: "Feature",
|
|
57
|
+
properties: {
|
|
58
|
+
cluster: false,
|
|
59
|
+
pointId: index,
|
|
60
|
+
data: coord.data
|
|
61
|
+
},
|
|
62
|
+
geometry: {
|
|
63
|
+
type: "Point",
|
|
64
|
+
coordinates: [coord.lng, coord.lat]
|
|
65
|
+
},
|
|
66
|
+
id: clusters.length
|
|
67
|
+
});
|
|
68
|
+
processed.add(index);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return clusters;
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
convertCoordinatesToGeoJSON,
|
|
75
|
+
createManualClusters
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=clustering.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ui/Map/constants.ts","../../../../src/components/ui/Map/utils.ts","../../../../src/components/ui/Map/clustering.ts"],"sourcesContent":["export const DEFAULT_POSITION = { lat: 40.715021, lng: -74.00459 }\nexport const DEFAULT_ZOOM = 10\nexport const CLUSTER_PIN_SCALE = 1.5\nexport const CLUSTER_DISTANCE_THRESHOLD = 0.001\n\nexport const PIN_COLORS = {\n background: '#0B5441',\n borderColor: '#EBFDF1',\n glyphColor: '#D4F500',\n} as const\n\nexport const FOCUS_CIRCLE_STYLES = {\n strokeColor: '#0B5441',\n strokeOpacity: 0.8,\n strokeWeight: 2,\n fillColor: '#0B5441',\n fillOpacity: 0.1,\n clickable: false,\n zIndex: 1,\n} as const\n\nexport const CLUSTERING_CONFIG = {\n radius: 60,\n maxZoom: 16,\n minPoints: 2,\n} as const\n","import { CLUSTER_DISTANCE_THRESHOLD, DEFAULT_POSITION } from '@/components/ui/Map/constants'\nimport type { Coordinate, PinData } from '@/components/ui/Map/types'\n\nexport function getCenterForCoordinates<T = PinData>(coords: Coordinate<T>[]): Coordinate<T> {\n if (coords.length === 0) return DEFAULT_POSITION as Coordinate<T>\n\n const avgLat = coords.reduce((sum, coord) => sum + coord.lat, 0) / coords.length\n const avgLng = coords.reduce((sum, coord) => sum + coord.lng, 0) / coords.length\n\n return { lat: avgLat, lng: avgLng }\n}\n\nexport function getZoomForCoordinates<T = PinData>(\n coords: Coordinate<T>[],\n defaultZoom: number\n): number {\n if (coords.length <= 1) return defaultZoom\n\n const lats = coords.map((coord) => coord.lat)\n const lngs = coords.map((coord) => coord.lng)\n\n const latDiff = Math.max(...lats) - Math.min(...lats)\n const lngDiff = Math.max(...lngs) - Math.min(...lngs)\n const maxDiff = Math.max(latDiff, lngDiff)\n\n if (maxDiff > 0.1) return 8\n if (maxDiff > 0.05) return 10\n if (maxDiff > 0.01) return 12\n return 14\n}\n\nexport function getClusteringRadius(zoom: number): number {\n if (zoom <= 8) return 200\n if (zoom <= 12) return 150\n return 100\n}\n\nexport function filterClusterCoordinates<T = PinData>(\n coordinates: Coordinate<T>[],\n clusterLat: number,\n clusterLng: number\n): Coordinate<T>[] {\n return coordinates.filter((coord) => {\n const latDiff = Math.abs(coord.lat - clusterLat)\n const lngDiff = Math.abs(coord.lng - clusterLng)\n const distance = Math.sqrt(latDiff * latDiff + lngDiff * lngDiff)\n return distance < CLUSTER_DISTANCE_THRESHOLD\n })\n}\n\nexport function calculateDistance<T = PinData>(\n coord1: Coordinate<T>,\n coord2: Coordinate<T>\n): number {\n const latDiff = Math.abs(coord1.lat - coord2.lat)\n const lngDiff = Math.abs(coord1.lng - coord2.lng)\n return Math.sqrt(latDiff * latDiff + lngDiff * lngDiff)\n}\n","import { CLUSTER_DISTANCE_THRESHOLD } from '@/components/ui/Map/constants'\nimport type { ClusterFeature, Coordinate, PinData } from '@/components/ui/Map/types'\nimport { calculateDistance } from '@/components/ui/Map/utils'\n\nexport function convertCoordinatesToGeoJSON<T = PinData>(coordinates: Coordinate<T>[]) {\n return coordinates.map((coord, index) => ({\n type: 'Feature' as const,\n properties: {\n cluster: false,\n pointId: index,\n data: coord.data,\n },\n geometry: {\n type: 'Point' as const,\n coordinates: [coord.lng, coord.lat],\n },\n }))\n}\n\nexport function createManualClusters<T = PinData>(\n coordinates: Coordinate<T>[]\n): ClusterFeature<T>[] {\n if (!coordinates || coordinates.length === 0) return []\n\n const clusters: ClusterFeature<T>[] = []\n const processed = new Set<number>()\n\n coordinates.forEach((coord, index) => {\n if (processed.has(index)) return\n\n const nearby: number[] = [index]\n coordinates.forEach((otherCoord, otherIndex) => {\n if (otherIndex === index || processed.has(otherIndex)) return\n\n const distance = calculateDistance(coord, otherCoord)\n\n if (distance < CLUSTER_DISTANCE_THRESHOLD) {\n nearby.push(otherIndex)\n }\n })\n\n if (nearby.length >= 2) {\n clusters.push({\n type: 'Feature' as const,\n properties: {\n cluster: true,\n point_count: nearby.length,\n },\n geometry: {\n type: 'Point' as const,\n coordinates: [coord.lng, coord.lat],\n },\n id: clusters.length,\n })\n\n nearby.forEach((i) => processed.add(i))\n } else {\n clusters.push({\n type: 'Feature' as const,\n properties: {\n cluster: false,\n pointId: index,\n data: coord.data,\n },\n geometry: {\n type: 'Point' as const,\n coordinates: [coord.lng, coord.lat],\n },\n id: clusters.length,\n })\n processed.add(index)\n }\n })\n\n return clusters\n}\n"],"mappings":";AAGO,IAAM,6BAA6B;;;AC+CnC,SAAS,kBACd,QACA,QACQ;AACR,QAAM,UAAU,KAAK,IAAI,OAAO,MAAM,OAAO,GAAG;AAChD,QAAM,UAAU,KAAK,IAAI,OAAO,MAAM,OAAO,GAAG;AAChD,SAAO,KAAK,KAAK,UAAU,UAAU,UAAU,OAAO;AACxD;;;ACrDO,SAAS,4BAAyC,aAA8B;AACrF,SAAO,YAAY,IAAI,CAAC,OAAO,WAAW;AAAA,IACxC,MAAM;AAAA,IACN,YAAY;AAAA,MACV,SAAS;AAAA,MACT,SAAS;AAAA,MACT,MAAM,MAAM;AAAA,IACd;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,aAAa,CAAC,MAAM,KAAK,MAAM,GAAG;AAAA,IACpC;AAAA,EACF,EAAE;AACJ;AAEO,SAAS,qBACd,aACqB;AACrB,MAAI,CAAC,eAAe,YAAY,WAAW,EAAG,QAAO,CAAC;AAEtD,QAAM,WAAgC,CAAC;AACvC,QAAM,YAAY,oBAAI,IAAY;AAElC,cAAY,QAAQ,CAAC,OAAO,UAAU;AACpC,QAAI,UAAU,IAAI,KAAK,EAAG;AAE1B,UAAM,SAAmB,CAAC,KAAK;AAC/B,gBAAY,QAAQ,CAAC,YAAY,eAAe;AAC9C,UAAI,eAAe,SAAS,UAAU,IAAI,UAAU,EAAG;AAEvD,YAAM,WAAW,kBAAkB,OAAO,UAAU;AAEpD,UAAI,WAAW,4BAA4B;AACzC,eAAO,KAAK,UAAU;AAAA,MACxB;AAAA,IACF,CAAC;AAED,QAAI,OAAO,UAAU,GAAG;AACtB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS;AAAA,UACT,aAAa,OAAO;AAAA,QACtB;AAAA,QACA,UAAU;AAAA,UACR,MAAM;AAAA,UACN,aAAa,CAAC,MAAM,KAAK,MAAM,GAAG;AAAA,QACpC;AAAA,QACA,IAAI,SAAS;AAAA,MACf,CAAC;AAED,aAAO,QAAQ,CAAC,MAAM,UAAU,IAAI,CAAC,CAAC;AAAA,IACxC,OAAO;AACL,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS;AAAA,UACT,SAAS;AAAA,UACT,MAAM,MAAM;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,MAAM;AAAA,UACN,aAAa,CAAC,MAAM,KAAK,MAAM,GAAG;AAAA,QACpC;AAAA,QACA,IAAI,SAAS;AAAA,MACf,CAAC;AACD,gBAAU,IAAI,KAAK;AAAA,IACrB;AAAA,EACF,CAAC;AAED,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/components/ui/Map/constants.ts
|
|
21
|
+
var constants_exports = {};
|
|
22
|
+
__export(constants_exports, {
|
|
23
|
+
CLUSTERING_CONFIG: () => CLUSTERING_CONFIG,
|
|
24
|
+
CLUSTER_DISTANCE_THRESHOLD: () => CLUSTER_DISTANCE_THRESHOLD,
|
|
25
|
+
CLUSTER_PIN_SCALE: () => CLUSTER_PIN_SCALE,
|
|
26
|
+
DEFAULT_POSITION: () => DEFAULT_POSITION,
|
|
27
|
+
DEFAULT_ZOOM: () => DEFAULT_ZOOM,
|
|
28
|
+
FOCUS_CIRCLE_STYLES: () => FOCUS_CIRCLE_STYLES,
|
|
29
|
+
PIN_COLORS: () => PIN_COLORS
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(constants_exports);
|
|
32
|
+
var DEFAULT_POSITION = { lat: 40.715021, lng: -74.00459 };
|
|
33
|
+
var DEFAULT_ZOOM = 10;
|
|
34
|
+
var CLUSTER_PIN_SCALE = 1.5;
|
|
35
|
+
var CLUSTER_DISTANCE_THRESHOLD = 1e-3;
|
|
36
|
+
var PIN_COLORS = {
|
|
37
|
+
background: "#0B5441",
|
|
38
|
+
borderColor: "#EBFDF1",
|
|
39
|
+
glyphColor: "#D4F500"
|
|
40
|
+
};
|
|
41
|
+
var FOCUS_CIRCLE_STYLES = {
|
|
42
|
+
strokeColor: "#0B5441",
|
|
43
|
+
strokeOpacity: 0.8,
|
|
44
|
+
strokeWeight: 2,
|
|
45
|
+
fillColor: "#0B5441",
|
|
46
|
+
fillOpacity: 0.1,
|
|
47
|
+
clickable: false,
|
|
48
|
+
zIndex: 1
|
|
49
|
+
};
|
|
50
|
+
var CLUSTERING_CONFIG = {
|
|
51
|
+
radius: 60,
|
|
52
|
+
maxZoom: 16,
|
|
53
|
+
minPoints: 2
|
|
54
|
+
};
|
|
55
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
56
|
+
0 && (module.exports = {
|
|
57
|
+
CLUSTERING_CONFIG,
|
|
58
|
+
CLUSTER_DISTANCE_THRESHOLD,
|
|
59
|
+
CLUSTER_PIN_SCALE,
|
|
60
|
+
DEFAULT_POSITION,
|
|
61
|
+
DEFAULT_ZOOM,
|
|
62
|
+
FOCUS_CIRCLE_STYLES,
|
|
63
|
+
PIN_COLORS
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=constants.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ui/Map/constants.ts"],"sourcesContent":["export const DEFAULT_POSITION = { lat: 40.715021, lng: -74.00459 }\nexport const DEFAULT_ZOOM = 10\nexport const CLUSTER_PIN_SCALE = 1.5\nexport const CLUSTER_DISTANCE_THRESHOLD = 0.001\n\nexport const PIN_COLORS = {\n background: '#0B5441',\n borderColor: '#EBFDF1',\n glyphColor: '#D4F500',\n} as const\n\nexport const FOCUS_CIRCLE_STYLES = {\n strokeColor: '#0B5441',\n strokeOpacity: 0.8,\n strokeWeight: 2,\n fillColor: '#0B5441',\n fillOpacity: 0.1,\n clickable: false,\n zIndex: 1,\n} as const\n\nexport const CLUSTERING_CONFIG = {\n radius: 60,\n maxZoom: 16,\n minPoints: 2,\n} as const\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,IAAM,mBAAmB,EAAE,KAAK,WAAW,KAAK,UAAU;AAC1D,IAAM,eAAe;AACrB,IAAM,oBAAoB;AAC1B,IAAM,6BAA6B;AAEnC,IAAM,aAAa;AAAA,EACxB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,YAAY;AACd;AAEO,IAAM,sBAAsB;AAAA,EACjC,aAAa;AAAA,EACb,eAAe;AAAA,EACf,cAAc;AAAA,EACd,WAAW;AAAA,EACX,aAAa;AAAA,EACb,WAAW;AAAA,EACX,QAAQ;AACV;AAEO,IAAM,oBAAoB;AAAA,EAC/B,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,WAAW;AACb;","names":[]}
|