@collabdt/core 0.0.43 → 0.0.45
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/core/components/viewers/Data/infrastructureDetails/FieldRenderer.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/infrastructureDetails/FieldRenderer.js.map +1 -1
- package/dist/core/components/viewers/bim/src/ClippingPlane.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/ClippingPlane.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddSensor.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddSensor.js.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.js +31 -8
- package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.js +19 -9
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.js.map +1 -1
- package/dist/core/components/viewers/map/utils/geocoder.d.ts +0 -5
- package/dist/core/components/viewers/map/utils/geocoder.d.ts.map +1 -1
- package/dist/core/components/viewers/map/utils/geocoder.js +1 -15
- package/dist/core/components/viewers/map/utils/geocoder.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldRenderer.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/Data/infrastructureDetails/FieldRenderer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"FieldRenderer.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/Data/infrastructureDetails/FieldRenderer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAmBzB,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,GAAG,CAAA;IACV,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAA;IACzD,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;IAC9C,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;IAC1C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;IAC3C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;IAC3C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;IACjD,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;IAC7C,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;CACjD;AAED,QAAA,MAAM,aAAa,GAAI,+IAWpB,kBAAkB,sBA+MpB,CAAA;AAED,eAAe,aAAa,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/core/components/viewers/Data/infrastructureDetails/FieldRenderer.tsx"],"sourcesContent":["// Dependencies\r\nimport React from 'react'\r\nimport { usePermissions } from '../../../../store'\r\n\r\n// import {\r\n// InfrastructureEnergySource,\r\n// InfrastructureAssessmentConditions,\r\n// InfrastructureProjectPhase,\r\n// InfrastructureProjectType,\r\n// InfrastructureLandUse,\r\n// } from '../../../../types/infrastructure'\r\n\r\n// Shadcn Components\r\nimport { Checkbox, Input, Textarea, Button, Badge, DatePicker } from '../../../../components/ui/'\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from '../../../../components/ui/Select'\r\n\r\n// Custom components\r\nimport FileUpload from '../details/FileUpload'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\ninterface FieldRendererProps {\r\n property: string\r\n value: any\r\n handleInputChange: (property: string, value: any) => void\r\n isTextAreaField: (property: string) => boolean\r\n isFileField: (property: string) => boolean\r\n isDateField?: (property: string) => boolean\r\n isEnumField?: (property: string) => boolean\r\n getEnumType?: (property: string) => string | null\r\n isNumberField?: (property: string) => boolean\r\n isFullWidthField?: (property: string) => boolean\r\n}\r\n\r\nconst FieldRenderer = ({\r\n property,\r\n value,\r\n handleInputChange,\r\n isTextAreaField,\r\n isFileField,\r\n isDateField = () => false,\r\n isEnumField = () => false,\r\n isNumberField = () => false,\r\n getEnumType = () => null,\r\n isFullWidthField = () => false,\r\n}: FieldRendererProps) => {\r\n\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n if (isFileField(property)) {\r\n return (\r\n <FileUpload\r\n value={Array.isArray(value) ? value : []}\r\n property={property}\r\n onChange={handleInputChange}\r\n editing={true}\r\n isFullWidthField={isFullWidthField(property)}\r\n />\r\n )\r\n }\r\n\r\n if (isDateField(property)) {\r\n return (\r\n <DatePicker\r\n date={value instanceof Date ? value : (value ? new Date(value) : undefined)}\r\n onSelect={date => handleInputChange(property, date)}\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n )\r\n }\r\n\r\n if (isEnumField(property)) {\r\n const enumType = getEnumType(property)\r\n\r\n // Return appropriate Select component based on enum type\r\n // if (enumType === 'InfrastructureEnergySource') {\r\n // return (\r\n // <Select\r\n // value={value || ''}\r\n // onValueChange={val => handleInputChange(property, val)}\r\n // >\r\n // <SelectTrigger>\r\n // <SelectValue placeholder=\"Select energy source\" />\r\n // </SelectTrigger>\r\n // <SelectContent>\r\n // {Object.values(InfrastructureEnergySource).map(source => (\r\n // <SelectItem key={source} value={source}>\r\n // {source}\r\n // </SelectItem>\r\n // ))}\r\n // </SelectContent>\r\n // </Select>\r\n // )\r\n // }\r\n\r\n // if (enumType === 'InfrastructureAssessmentConditions') {\r\n // return (\r\n // <Select\r\n // value={value || ''}\r\n // onValueChange={val => handleInputChange(property, val)}\r\n // >\r\n // <SelectTrigger>\r\n // <SelectValue placeholder=\"Select assessment condition\" />\r\n // </SelectTrigger>\r\n // <SelectContent>\r\n // {Object.values(InfrastructureAssessmentConditions).map(condition => (\r\n // <SelectItem key={condition} value={condition}>\r\n // {condition.replaceAll('_', ' ')}\r\n // </SelectItem>\r\n // ))}\r\n // </SelectContent>\r\n // </Select>\r\n // )\r\n // }\r\n\r\n // if (enumType === 'InfrastructureProjectPhase') {\r\n // return (\r\n // <Select\r\n // value={value || ''}\r\n // onValueChange={val => handleInputChange(property, val)}\r\n // >\r\n // <SelectTrigger>\r\n // <SelectValue placeholder=\"Select project phase\" />\r\n // </SelectTrigger>\r\n // <SelectContent>\r\n // {Object.values(InfrastructureProjectPhase).map(style => (\r\n // <SelectItem key={style} value={style}>\r\n // {style}\r\n // </SelectItem>\r\n // ))}\r\n // </SelectContent>\r\n // </Select>\r\n // )\r\n // }\r\n\r\n // if (enumType === 'InfrastructureProjectType') {\r\n // return (\r\n // <Select\r\n // value={value || ''}\r\n // onValueChange={val => handleInputChange(property, val)}\r\n // >\r\n // <SelectTrigger>\r\n // <SelectValue placeholder=\"Select project type\" />\r\n // </SelectTrigger>\r\n // <SelectContent>\r\n // {Object.values(InfrastructureProjectType).map(type => (\r\n // <SelectItem key={type} value={type}>\r\n // {type.replaceAll('_', ' ')}\r\n // </SelectItem>\r\n // ))}\r\n // </SelectContent>\r\n // </Select>\r\n // )\r\n // }\r\n\r\n // if (enumType === 'InfrastructureLandUse') {\r\n // return (\r\n // <Select\r\n // value={value || ''}\r\n // onValueChange={val => handleInputChange(property, val)}\r\n // >\r\n // <SelectTrigger>\r\n // <SelectValue placeholder=\"Select land use\" />\r\n // </SelectTrigger>\r\n // <SelectContent>\r\n // {Object.values(InfrastructureLandUse).map(use => (\r\n // <SelectItem key={use} value={use}>\r\n // {use.replaceAll('_', ' ')}\r\n // </SelectItem>\r\n // ))}\r\n // </SelectContent>\r\n // </Select>\r\n // )\r\n // }\r\n }\r\n\r\n if (isTextAreaField(property)) {\r\n return (\r\n <Textarea\r\n value={value || ''}\r\n onChange={e => handleInputChange(property, e.target.value)}\r\n rows={4}\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n )\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return (\r\n <>\r\n <div className=\"flex flex-row gap-2\">\r\n <Input\r\n type=\"text\"\r\n value=\"\"\r\n onChange={() => {}}\r\n placeholder=\"Add new item\"\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n <Button \r\n variant=\"outline\" \r\n size=\"icon\" \r\n disabled={!ability.can('update', 'Infrastructure')}\r\n ><LR.Plus /></Button>\r\n </div>\r\n {/* Render Existing values */}\r\n <div className=\"flex flex-row gap-2\">\r\n {(value || []).map((item: string, index: number) => (\r\n <Badge key={index} className=\"cursor-pointer inline-flex\" variant=\"secondary\">\r\n {item}\r\n </Badge>\r\n ))}\r\n </div>\r\n </>\r\n )\r\n }\r\n\r\n if (value === 'yes' || value === 'no') {\r\n const bool = value === 'yes'\r\n return (\r\n <Checkbox\r\n checked={bool}\r\n onCheckedChange={checked => handleInputChange(property, checked ? 'yes' : 'no')}\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n )\r\n }\r\n\r\n if (typeof value === 'number' || (value === null && isNumberField(property))) {\r\n return (\r\n <Input\r\n type=\"number\"\r\n value={value || ''}\r\n onChange={(e) => {\r\n const stringValue = e.target.value\r\n // If empty string, send null; otherwise convert to number\r\n const numValue = stringValue === '' ? null : Number(stringValue)\r\n handleInputChange(property, numValue)\r\n }}\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n )\r\n }\r\n\r\n // Default: text input\r\n return (\r\n <Input\r\n value={String(value || '')}\r\n onChange={e => handleInputChange(property, e.target.value)}\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n )\r\n}\r\n\r\nexport default FieldRenderer\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/core/components/viewers/Data/infrastructureDetails/FieldRenderer.tsx"],"sourcesContent":["// Dependencies\r\nimport React from 'react'\r\nimport { usePermissions } from '../../../../store'\r\n\r\n// Shadcn Components\r\nimport { Checkbox, Input, Textarea, Button, Badge, DatePicker } from '../../../../components/ui/'\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from '../../../../components/ui/Select'\r\n\r\n// Custom components\r\nimport FileUpload from '../details/FileUpload'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\ninterface FieldRendererProps {\r\n property: string\r\n value: any\r\n handleInputChange: (property: string, value: any) => void\r\n isTextAreaField: (property: string) => boolean\r\n isFileField: (property: string) => boolean\r\n isDateField?: (property: string) => boolean\r\n isEnumField?: (property: string) => boolean\r\n getEnumType?: (property: string) => string | null\r\n isNumberField?: (property: string) => boolean\r\n isFullWidthField?: (property: string) => boolean\r\n}\r\n\r\nconst FieldRenderer = ({\r\n property,\r\n value,\r\n handleInputChange,\r\n isTextAreaField,\r\n isFileField,\r\n isDateField = () => false,\r\n isEnumField = () => false,\r\n isNumberField = () => false,\r\n getEnumType = () => null,\r\n isFullWidthField = () => false,\r\n}: FieldRendererProps) => {\r\n\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n if (isFileField(property)) {\r\n return (\r\n <FileUpload\r\n value={Array.isArray(value) ? value : []}\r\n property={property}\r\n onChange={handleInputChange}\r\n editing={true}\r\n isFullWidthField={isFullWidthField(property)}\r\n />\r\n )\r\n }\r\n\r\n if (isDateField(property)) {\r\n return (\r\n <DatePicker\r\n date={value instanceof Date ? value : (value ? new Date(value) : undefined)}\r\n onSelect={date => handleInputChange(property, date)}\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n )\r\n }\r\n\r\n if (isEnumField(property)) {\r\n const enumType = getEnumType(property)\r\n\r\n // Return appropriate Select component based on enum type\r\n // if (enumType === 'InfrastructureEnergySource') {\r\n // return (\r\n // <Select\r\n // value={value || ''}\r\n // onValueChange={val => handleInputChange(property, val)}\r\n // >\r\n // <SelectTrigger>\r\n // <SelectValue placeholder=\"Select energy source\" />\r\n // </SelectTrigger>\r\n // <SelectContent>\r\n // {Object.values(InfrastructureEnergySource).map(source => (\r\n // <SelectItem key={source} value={source}>\r\n // {source}\r\n // </SelectItem>\r\n // ))}\r\n // </SelectContent>\r\n // </Select>\r\n // )\r\n // }\r\n\r\n // if (enumType === 'InfrastructureAssessmentConditions') {\r\n // return (\r\n // <Select\r\n // value={value || ''}\r\n // onValueChange={val => handleInputChange(property, val)}\r\n // >\r\n // <SelectTrigger>\r\n // <SelectValue placeholder=\"Select assessment condition\" />\r\n // </SelectTrigger>\r\n // <SelectContent>\r\n // {Object.values(InfrastructureAssessmentConditions).map(condition => (\r\n // <SelectItem key={condition} value={condition}>\r\n // {condition.replaceAll('_', ' ')}\r\n // </SelectItem>\r\n // ))}\r\n // </SelectContent>\r\n // </Select>\r\n // )\r\n // }\r\n\r\n // if (enumType === 'InfrastructureProjectPhase') {\r\n // return (\r\n // <Select\r\n // value={value || ''}\r\n // onValueChange={val => handleInputChange(property, val)}\r\n // >\r\n // <SelectTrigger>\r\n // <SelectValue placeholder=\"Select project phase\" />\r\n // </SelectTrigger>\r\n // <SelectContent>\r\n // {Object.values(InfrastructureProjectPhase).map(style => (\r\n // <SelectItem key={style} value={style}>\r\n // {style}\r\n // </SelectItem>\r\n // ))}\r\n // </SelectContent>\r\n // </Select>\r\n // )\r\n // }\r\n\r\n // if (enumType === 'InfrastructureProjectType') {\r\n // return (\r\n // <Select\r\n // value={value || ''}\r\n // onValueChange={val => handleInputChange(property, val)}\r\n // >\r\n // <SelectTrigger>\r\n // <SelectValue placeholder=\"Select project type\" />\r\n // </SelectTrigger>\r\n // <SelectContent>\r\n // {Object.values(InfrastructureProjectType).map(type => (\r\n // <SelectItem key={type} value={type}>\r\n // {type.replaceAll('_', ' ')}\r\n // </SelectItem>\r\n // ))}\r\n // </SelectContent>\r\n // </Select>\r\n // )\r\n // }\r\n\r\n // if (enumType === 'InfrastructureLandUse') {\r\n // return (\r\n // <Select\r\n // value={value || ''}\r\n // onValueChange={val => handleInputChange(property, val)}\r\n // >\r\n // <SelectTrigger>\r\n // <SelectValue placeholder=\"Select land use\" />\r\n // </SelectTrigger>\r\n // <SelectContent>\r\n // {Object.values(InfrastructureLandUse).map(use => (\r\n // <SelectItem key={use} value={use}>\r\n // {use.replaceAll('_', ' ')}\r\n // </SelectItem>\r\n // ))}\r\n // </SelectContent>\r\n // </Select>\r\n // )\r\n // }\r\n }\r\n\r\n if (isTextAreaField(property)) {\r\n return (\r\n <Textarea\r\n value={value || ''}\r\n onChange={e => handleInputChange(property, e.target.value)}\r\n rows={4}\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n )\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return (\r\n <>\r\n <div className=\"flex flex-row gap-2\">\r\n <Input\r\n type=\"text\"\r\n value=\"\"\r\n onChange={() => {}}\r\n placeholder=\"Add new item\"\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n <Button \r\n variant=\"outline\" \r\n size=\"icon\" \r\n disabled={!ability.can('update', 'Infrastructure')}\r\n ><LR.Plus /></Button>\r\n </div>\r\n {/* Render Existing values */}\r\n <div className=\"flex flex-row gap-2\">\r\n {(value || []).map((item: string, index: number) => (\r\n <Badge key={index} className=\"cursor-pointer inline-flex\" variant=\"secondary\">\r\n {item}\r\n </Badge>\r\n ))}\r\n </div>\r\n </>\r\n )\r\n }\r\n\r\n if (value === 'yes' || value === 'no') {\r\n const bool = value === 'yes'\r\n return (\r\n <Checkbox\r\n checked={bool}\r\n onCheckedChange={checked => handleInputChange(property, checked ? 'yes' : 'no')}\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n )\r\n }\r\n\r\n if (typeof value === 'number' || (value === null && isNumberField(property))) {\r\n return (\r\n <Input\r\n type=\"number\"\r\n value={value || ''}\r\n onChange={(e) => {\r\n const stringValue = e.target.value\r\n // If empty string, send null; otherwise convert to number\r\n const numValue = stringValue === '' ? null : Number(stringValue)\r\n handleInputChange(property, numValue)\r\n }}\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n )\r\n }\r\n\r\n // Default: text input\r\n return (\r\n <Input\r\n value={String(value || '')}\r\n onChange={e => handleInputChange(property, e.target.value)}\r\n disabled={!ability.can('update', 'Infrastructure')}\r\n />\r\n )\r\n}\r\n\r\nexport default FieldRenderer\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClippingPlane.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/bim/src/ClippingPlane.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"ClippingPlane.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/bim/src/ClippingPlane.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,sBAAsB,CAAA;AAE3C,qBAAa,aAAc,SAAQ,GAAG,CAAC,SAAS;IAE5C,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAG,sCAAsC,CAAS;IAEtE,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,SAAS,CAA2B;IAE5C,IAAI,OAAO,IAIQ,OAAO,CAFzB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EASzB;gBAEW,UAAU,EAAE,GAAG,CAAC,UAAU;IAoBtC,OAAO,CAAC,kBAAkB;IAuB1B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,aAAa,CAUpB;IAED,YAAY;IAMZ,YAAY;IAMZ,OAAO;CAMV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/core/components/viewers/bim/src/ClippingPlane.ts"],"sourcesContent":["import { CurrentWorld } from './CurrentWorld';\r\nimport * as OBC from '@thatopen/components'\r\n
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/core/components/viewers/bim/src/ClippingPlane.ts"],"sourcesContent":["import { CurrentWorld } from './CurrentWorld';\r\nimport * as OBC from '@thatopen/components'\r\n\r\nexport class ClippingPlane extends OBC.Component {\r\n\r\n static readonly uuid = '29b2eabd-36cd-4b42-a62c-d0509bd67d60' as const\r\n\r\n private _enabled = false\r\n private clipper: OBC.Clipper\r\n private casters: OBC.Raycasters\r\n private world: OBC.World | null = null\r\n private container: HTMLElement | null = null\r\n\r\n get enabled() {\r\n return this._enabled\r\n }\r\n\r\n set enabled(value: boolean) {\r\n this._enabled = value\r\n this.clipper.enabled = value\r\n \r\n if (value) {\r\n this.setupClippingPlane()\r\n } else {\r\n this.removeEventListeners()\r\n }\r\n }\r\n\r\n constructor(components: OBC.Components) {\r\n super(components)\r\n components.add(ClippingPlane.uuid, this)\r\n \r\n // Initialize clipper and raycasters\r\n this.clipper = components.get(OBC.Clipper)\r\n this.casters = components.get(OBC.Raycasters)\r\n this.world = components.get(CurrentWorld).world\r\n \r\n // Initialize the raycaster for the world\r\n if (this.world) {\r\n this.casters.get(this.world)\r\n }\r\n \r\n // Get the container from the world's renderer\r\n if (this.world?.renderer?.three.domElement.parentElement) {\r\n this.container = this.world.renderer.three.domElement.parentElement\r\n }\r\n }\r\n\r\n private setupClippingPlane() {\r\n if (!this.world || !this.container) {\r\n console.warn('World and container must be set before enabling clipping plane')\r\n return\r\n }\r\n\r\n // Add double-click event listener to create clipping planes\r\n this.container.ondblclick = () => {\r\n if (this.enabled && this.world) {\r\n this.clipper.create(this.world)\r\n }\r\n }\r\n\r\n // Make container focusable and focused for keyboard events\r\n this.container.tabIndex = -1\r\n this.container.focus()\r\n\r\n // Add keyboard event listener for deleting clipping planes\r\n this.container.addEventListener('keydown', this.handleKeyDown)\r\n // Also add to window as fallback\r\n window.addEventListener('keydown', this.handleKeyDown)\r\n }\r\n\r\n private removeEventListeners() {\r\n if (this.container) {\r\n this.container.ondblclick = null\r\n this.container.removeEventListener('keydown', this.handleKeyDown)\r\n }\r\n window.removeEventListener('keydown', this.handleKeyDown)\r\n }\r\n\r\n private handleKeyDown = (event: KeyboardEvent) => {\r\n console.log('Key pressed:', event.code, 'Enabled:', this.enabled); // Debug log\r\n \r\n if (event.code === \"Delete\" || event.code === \"Backspace\" || event.code === \"Escape\") {\r\n if (this.enabled && this.world) {\r\n event.preventDefault(); \r\n event.stopPropagation(); \r\n this.deletePlanes()\r\n }\r\n }\r\n }\r\n\r\n createPlanes() {\r\n if (this.enabled && this.world) {\r\n this.clipper.create(this.world)\r\n }\r\n }\r\n\r\n deletePlanes() {\r\n if (this.world) {\r\n this.clipper.deleteAll()\r\n }\r\n }\r\n\r\n dispose() {\r\n this.enabled = false\r\n this.removeEventListeners()\r\n this.world = null\r\n this.container = null\r\n }\r\n}"],"mappings":"AAAA,SAAS,oBAAoB;AAC7B,YAAY,SAAS;AAEd,MAAM,iBAAN,MAAM,uBAAsB,IAAI,UAAU;AAAA,EAyB7C,YAAY,YAA4B;AA5B5C;AA6BQ,UAAM,UAAU;AAtBpB,SAAQ,WAAW;AAGnB,SAAQ,QAA0B;AAClC,SAAQ,YAAgC;AAoExC,SAAQ,gBAAgB,CAAC,UAAyB;AAC9C,cAAQ,IAAI,gBAAgB,MAAM,MAAM,YAAY,KAAK,OAAO;AAEhE,UAAI,MAAM,SAAS,YAAY,MAAM,SAAS,eAAe,MAAM,SAAS,UAAU;AAClF,YAAI,KAAK,WAAW,KAAK,OAAO;AAC5B,gBAAM,eAAe;AACrB,gBAAM,gBAAgB;AACtB,eAAK,aAAa;AAAA,QACtB;AAAA,MACJ;AAAA,IACJ;AA3DI,eAAW,IAAI,eAAc,MAAM,IAAI;AAGvC,SAAK,UAAU,WAAW,IAAI,IAAI,OAAO;AACzC,SAAK,UAAU,WAAW,IAAI,IAAI,UAAU;AAC5C,SAAK,QAAQ,WAAW,IAAI,YAAY,EAAE;AAG1C,QAAI,KAAK,OAAO;AACZ,WAAK,QAAQ,IAAI,KAAK,KAAK;AAAA,IAC/B;AAGA,SAAI,gBAAK,UAAL,mBAAY,aAAZ,mBAAsB,MAAM,WAAW,eAAe;AACtD,WAAK,YAAY,KAAK,MAAM,SAAS,MAAM,WAAW;AAAA,IAC1D;AAAA,EACJ;AAAA,EAjCA,IAAI,UAAU;AACV,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAI,QAAQ,OAAgB;AACxB,SAAK,WAAW;AAChB,SAAK,QAAQ,UAAU;AAEvB,QAAI,OAAO;AACP,WAAK,mBAAmB;AAAA,IAC5B,OAAO;AACH,WAAK,qBAAqB;AAAA,IAC9B;AAAA,EACJ;AAAA,EAsBQ,qBAAqB;AACzB,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,WAAW;AAChC,cAAQ,KAAK,gEAAgE;AAC7E;AAAA,IACJ;AAGA,SAAK,UAAU,aAAa,MAAM;AAC9B,UAAI,KAAK,WAAW,KAAK,OAAO;AAC5B,aAAK,QAAQ,OAAO,KAAK,KAAK;AAAA,MAClC;AAAA,IACJ;AAGA,SAAK,UAAU,WAAW;AAC1B,SAAK,UAAU,MAAM;AAGrB,SAAK,UAAU,iBAAiB,WAAW,KAAK,aAAa;AAE7D,WAAO,iBAAiB,WAAW,KAAK,aAAa;AAAA,EACzD;AAAA,EAEQ,uBAAuB;AAC3B,QAAI,KAAK,WAAW;AAChB,WAAK,UAAU,aAAa;AAC5B,WAAK,UAAU,oBAAoB,WAAW,KAAK,aAAa;AAAA,IACpE;AACA,WAAO,oBAAoB,WAAW,KAAK,aAAa;AAAA,EAC5D;AAAA,EAcA,eAAe;AACX,QAAI,KAAK,WAAW,KAAK,OAAO;AAC5B,WAAK,QAAQ,OAAO,KAAK,KAAK;AAAA,IAClC;AAAA,EACJ;AAAA,EAEA,eAAe;AACX,QAAI,KAAK,OAAO;AACZ,WAAK,QAAQ,UAAU;AAAA,IAC3B;AAAA,EACJ;AAAA,EAEA,UAAU;AACN,SAAK,UAAU;AACf,SAAK,qBAAqB;AAC1B,SAAK,QAAQ;AACb,SAAK,YAAY;AAAA,EACrB;AACJ;AA1Ga,eAEO,OAAO;AAFpB,IAAM,gBAAN;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddSensor.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/AddSensor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,sBAAsB,CAAA;AAG3C,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"AddSensor.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/AddSensor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,sBAAsB,CAAA;AAG3C,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,UAAU,MAAM;IACd,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,qBAAa,SAAU,SAAQ,GAAG,CAAC,SAAS;IAC1C,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAG,sCAAsC,CAAS;IAEtE,OAAO,CAAC,QAAQ,CAAQ;IAExB,OAAO,CAAC,KAAK,CAAyB;IAEtC,OAAO,CAAC,SAAS,CAAoC;IAErD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAKzB;IAED,IAAI,OAAO,IAPQ,OAAO,CASzB;IAED,QAAQ,CAAC,aAAa,sBAA4B;gBAEtC,UAAU,EAAE,GAAG,CAAC,UAAU;IAYtC,OAAO,CAAC,eAAe,CAAwB;IAE/C,OAAO,CAAC,oBAAoB,CAY3B;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/AddSensor.ts"],"sourcesContent":["import * as OBC from '@thatopen/components'\r\nimport * as OBF from '@thatopen/components-front'\r\nimport { CurrentWorld } from '../../../CurrentWorld'\r\nimport * as THREE from 'three'\r\n
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/AddSensor.ts"],"sourcesContent":["import * as OBC from '@thatopen/components'\r\nimport * as OBF from '@thatopen/components-front'\r\nimport { CurrentWorld } from '../../../CurrentWorld'\r\nimport * as THREE from 'three'\r\n\r\ninterface Sensor {\r\n id: string\r\n position: THREE.Vector3\r\n modelId: string\r\n}\r\n\r\nexport class AddSensor extends OBC.Component {\r\n static readonly uuid = '93b460f1-cc7d-44cc-b1ee-55f0cd89acaf' as const\r\n\r\n private _enabled = false\r\n\r\n private world: OBC.World | null = null\r\n\r\n private fragments: OBC.FragmentsManager | null = null\r\n\r\n set enabled(value: boolean) {\r\n this._enabled = value\r\n if (!value && this._previewElement) {\r\n this._previewElement.visible = false\r\n }\r\n }\r\n\r\n get enabled() {\r\n return this._enabled\r\n }\r\n\r\n readonly onSensorAdded = new OBC.Event<Sensor[]>()\r\n\r\n constructor(components: OBC.Components) {\r\n super(components)\r\n components.add(AddSensor.uuid, this)\r\n this.world = components.get(CurrentWorld).world\r\n if (this.world) {\r\n this.createPreviewElement(this.world)\r\n // this.setEvents(this.world, true);\r\n }\r\n\r\n this.fragments = components.get(OBC.FragmentsManager)\r\n }\r\n\r\n private _previewElement: OBF.Mark | null = null\r\n\r\n private createPreviewElement = (world: OBC.World) => {\r\n const icon = document.createElement('a')\r\n\r\n icon.className = 'bg-white text-black rounded-full w-10 h-10 flex items-center justify-center shadow-md cursor-pointer'\r\n icon.id = 'sensor-preview'\r\n\r\n icon.innerHTML = '<i data-lucide=\"radio\"></i>'\r\n\r\n if (world) return\r\n const preview = new OBF.Mark(world as any, icon)\r\n preview.visible = false\r\n this._previewElement = preview\r\n }\r\n}\r\n"],"mappings":"AAAA,YAAY,SAAS;AACrB,YAAY,SAAS;AACrB,SAAS,oBAAoB;AAStB,MAAM,aAAN,MAAM,mBAAkB,IAAI,UAAU;AAAA,EAsB3C,YAAY,YAA4B;AACtC,UAAM,UAAU;AApBlB,SAAQ,WAAW;AAEnB,SAAQ,QAA0B;AAElC,SAAQ,YAAyC;AAajD,SAAS,gBAAgB,IAAI,IAAI,MAAgB;AAcjD,SAAQ,kBAAmC;AAE3C,SAAQ,uBAAuB,CAAC,UAAqB;AACnD,YAAM,OAAO,SAAS,cAAc,GAAG;AAEvC,WAAK,YAAY;AACjB,WAAK,KAAK;AAEV,WAAK,YAAY;AAEjB,UAAI,MAAO;AACX,YAAM,UAAU,IAAI,IAAI,KAAK,OAAc,IAAI;AAC/C,cAAQ,UAAU;AAClB,WAAK,kBAAkB;AAAA,IACzB;AAxBE,eAAW,IAAI,WAAU,MAAM,IAAI;AACnC,SAAK,QAAQ,WAAW,IAAI,YAAY,EAAE;AAC1C,QAAI,KAAK,OAAO;AACd,WAAK,qBAAqB,KAAK,KAAK;AAAA,IAEtC;AAEA,SAAK,YAAY,WAAW,IAAI,IAAI,gBAAgB;AAAA,EACtD;AAAA,EAvBA,IAAI,QAAQ,OAAgB;AAC1B,SAAK,WAAW;AAChB,QAAI,CAAC,SAAS,KAAK,iBAAiB;AAClC,WAAK,gBAAgB,UAAU;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,IAAI,UAAU;AACZ,WAAO,KAAK;AAAA,EACd;AA+BF;AAjDa,WACK,OAAO;AADlB,IAAM,YAAN;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapViewer.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/map/MapViewer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAA;AAazB,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"MapViewer.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/map/MapViewer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAA;AAazB,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAerD,UAAU,KAAK;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,YAAY,CAAA;CAC3B;AAED,wBAAgB,SAAS,CAAC,EAAE,KAAc,EAAE,MAAe,EAAE,YAAY,EAAE,EAAE,KAAK,qBAsLjF"}
|
|
@@ -20,16 +20,17 @@ const CANADA_DEFAULTS = {
|
|
|
20
20
|
long: -98.74
|
|
21
21
|
};
|
|
22
22
|
const DEFAULT_MAP_STYLE = { name: "Satellite", url: "mapStyles/satellite.json" };
|
|
23
|
+
const MAX_GLOBE_ZOOM = 5;
|
|
23
24
|
function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
24
|
-
var _a, _b;
|
|
25
|
+
var _a, _b, _c;
|
|
25
26
|
const searchParams = useSearchParams();
|
|
26
27
|
const [isMapLoaded, setIsMapLoaded] = React.useState(false);
|
|
27
28
|
const viewState = React.useMemo(() => {
|
|
28
|
-
var _a2, _b2,
|
|
29
|
+
var _a2, _b2, _c2, _d, _e, _f, _g, _h, _i, _j;
|
|
29
30
|
return searchParams.size === 0 ? {
|
|
30
31
|
zoom: (_a2 = organization.zoom) != null ? _a2 : CANADA_DEFAULTS.zoom,
|
|
31
32
|
bearing: (_b2 = organization.bearing) != null ? _b2 : 0,
|
|
32
|
-
pitch: (
|
|
33
|
+
pitch: (_c2 = organization.pitch) != null ? _c2 : 0,
|
|
33
34
|
longitude: (_d = organization.long) != null ? _d : CANADA_DEFAULTS.long,
|
|
34
35
|
latitude: (_e = organization.lat) != null ? _e : CANADA_DEFAULTS.lat
|
|
35
36
|
} : {
|
|
@@ -40,6 +41,7 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
|
40
41
|
zoom: searchParams.has("zoom") ? Number.parseFloat(searchParams.get("zoom")) : (_j = organization.zoom) != null ? _j : CANADA_DEFAULTS.zoom
|
|
41
42
|
};
|
|
42
43
|
}, [searchParams, organization]);
|
|
44
|
+
const initialProjection = viewState.zoom > MAX_GLOBE_ZOOM ? "mercator" : "globe";
|
|
43
45
|
const mapContainerStyle = React.useMemo(
|
|
44
46
|
() => ({ width, height, backgroundColor: "black" }),
|
|
45
47
|
[width, height]
|
|
@@ -50,9 +52,30 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
|
50
52
|
);
|
|
51
53
|
const mapRef = React.useRef(null);
|
|
52
54
|
const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext);
|
|
55
|
+
const activeMap = (_a = mapState == null ? void 0 : mapState.map) == null ? void 0 : _a.map;
|
|
56
|
+
React.useEffect(() => {
|
|
57
|
+
if (!activeMap) return;
|
|
58
|
+
const enforceProjectionForZoom = () => {
|
|
59
|
+
var _a2;
|
|
60
|
+
if (activeMap.getZoom() <= MAX_GLOBE_ZOOM) return;
|
|
61
|
+
const projection = activeMap.getProjection();
|
|
62
|
+
const currentType = typeof projection === "string" ? projection : (_a2 = projection == null ? void 0 : projection.type) != null ? _a2 : projection == null ? void 0 : projection.name;
|
|
63
|
+
if (currentType !== "mercator") {
|
|
64
|
+
activeMap.setProjection({ type: "mercator" });
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
enforceProjectionForZoom();
|
|
68
|
+
activeMap.on("zoom", enforceProjectionForZoom);
|
|
69
|
+
return () => {
|
|
70
|
+
activeMap.off("zoom", enforceProjectionForZoom);
|
|
71
|
+
};
|
|
72
|
+
}, [activeMap]);
|
|
53
73
|
const handleMapLoad = () => {
|
|
54
|
-
var _a2, _b2,
|
|
74
|
+
var _a2, _b2, _c2, _d, _e, _f, _g, _h;
|
|
55
75
|
const map = mapRef.current.getMap();
|
|
76
|
+
if (map.getZoom() > MAX_GLOBE_ZOOM) {
|
|
77
|
+
map.setProjection({ type: "mercator" });
|
|
78
|
+
}
|
|
56
79
|
if (mapRef.current) {
|
|
57
80
|
mapDispatch({
|
|
58
81
|
type: "SET_MAP",
|
|
@@ -73,7 +96,7 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
|
73
96
|
// Then override with URL params (this ensures URL params take precedence)
|
|
74
97
|
lat: searchParams.has("lat") ? Number.parseFloat(searchParams.get("lat")) : (_a2 = organization.lat) != null ? _a2 : CANADA_DEFAULTS.lat,
|
|
75
98
|
lng: searchParams.has("lng") ? Number.parseFloat(searchParams.get("lng")) : (_b2 = organization.long) != null ? _b2 : CANADA_DEFAULTS.long,
|
|
76
|
-
bearing: searchParams.has("bearing") ? Number.parseFloat(searchParams.get("bearing")) : (
|
|
99
|
+
bearing: searchParams.has("bearing") ? Number.parseFloat(searchParams.get("bearing")) : (_c2 = organization.bearing) != null ? _c2 : 0,
|
|
77
100
|
pitch: searchParams.has("pitch") ? Number.parseFloat(searchParams.get("pitch")) : (_d = organization.pitch) != null ? _d : 0,
|
|
78
101
|
zoom: searchParams.has("zoom") ? Number.parseFloat(searchParams.get("zoom")) : (_e = organization.zoom) != null ? _e : CANADA_DEFAULTS.zoom,
|
|
79
102
|
// Add location details from URL params if available
|
|
@@ -99,7 +122,7 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
|
99
122
|
const coordinates = { lng, lat, elevation, zoom: (_b2 = mapRef.current) == null ? void 0 : _b2.getZoom() };
|
|
100
123
|
console.log("\u{1F4CD} Map coordinates:", coordinates);
|
|
101
124
|
}, []);
|
|
102
|
-
const mapStyle = (
|
|
125
|
+
const mapStyle = (_b = mapState == null ? void 0 : mapState.map.mapStyle) != null ? _b : DEFAULT_MAP_STYLE;
|
|
103
126
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
104
127
|
/* @__PURE__ */ jsxs(
|
|
105
128
|
Map,
|
|
@@ -112,9 +135,9 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
|
|
|
112
135
|
style: mapContainerStyle,
|
|
113
136
|
initialViewState: viewState,
|
|
114
137
|
maxPitch: 60,
|
|
115
|
-
minZoom: (
|
|
138
|
+
minZoom: (_c = organization == null ? void 0 : organization.minZoom) != null ? _c : CANADA_DEFAULTS.zoom,
|
|
116
139
|
maxBounds: resolveBounds(organization == null ? void 0 : organization.maxBounds, CANADA_DEFAULTS.maxBounds),
|
|
117
|
-
projection:
|
|
140
|
+
projection: initialProjection,
|
|
118
141
|
doubleClickZoom: false,
|
|
119
142
|
onDblClick,
|
|
120
143
|
pixelRatio,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/core/components/viewers/map/MapViewer.tsx"],"sourcesContent":["'use client'\r\n\r\nimport Map, { MapRef, NavigationControl } from 'react-map-gl/maplibre'\r\nimport React from 'react'\r\n\r\nimport maplibregl, { LngLatBoundsLike } from 'maplibre-gl'\r\nimport { useSearchParams } from 'next/navigation'\r\n\r\nimport { MapContext } from '../../../store'\r\nimport { resolveBounds } from './utils/validateBounds'\r\n\r\nimport { MapClickManager } from './utils/MapEventManager/MapClickManager'\r\nimport DatasetManagerMenu from './datasets/DatasetManager'\r\nimport { MapLegendHost } from './legends/MapLegendHost'\r\nimport { StatsOverlay } from '../../ui/stats'\r\nimport { MapHoverManager } from './utils/MapEventManager/MapHoverManager'\r\nimport { Organization } from '../../../types/dbTypes'\r\nimport { CurrentLocation } from '../../../types/map'\r\nimport { MapLayers } from './src/MapLayers'\r\nimport SettingsButton from '../../ui/SettingsButton'\r\n\r\nconst CANADA_DEFAULTS = {\r\n maxBounds: [-141.0, 41.6751050889, -52.6480987209, 83.23324] as LngLatBoundsLike,\r\n zoom: 3,\r\n lat: 56.415,\r\n long: -98.74,\r\n} as const\r\n\r\nconst DEFAULT_MAP_STYLE = { name: 'Satellite', url: 'mapStyles/satellite.json' } as const\r\n\r\ninterface Props {\r\n width?: string\r\n height?: string\r\n organization: Organization\r\n}\r\n\r\nexport function MapViewer({ width = '100%', height = '100%', organization }: Props) {\r\n\r\n const searchParams = useSearchParams()\r\n\r\n // Add state to track if map is loaded\r\n const [isMapLoaded, setIsMapLoaded] = React.useState(false)\r\n\r\n const viewState = React.useMemo(() => {\r\n return searchParams.size === 0\r\n ? {\r\n zoom: organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n bearing: organization.bearing ?? 0,\r\n pitch: organization.pitch ?? 0,\r\n longitude: organization.long ?? CANADA_DEFAULTS.long,\r\n latitude: organization.lat ?? CANADA_DEFAULTS.lat,\r\n }\r\n : {\r\n latitude: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n longitude: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n }\r\n }, [searchParams, organization])\r\n\r\n // Memoize the inline style object that gets passed to <Map> for a stable prop identity.\r\n const mapContainerStyle = React.useMemo(\r\n () => ({ width, height, backgroundColor: 'black' }),\r\n [width, height],\r\n )\r\n\r\n // Adaptive pixel ratio. A hardcoded 2 doubled fragment-shader cost on 1× DPR\r\n // desktops for zero visual gain; capping at 2 keeps phones (DPR 3-4) effective.\r\n const pixelRatio = React.useMemo(\r\n () => Math.min(typeof window !== 'undefined' ? window.devicePixelRatio : 1, 2),\r\n [],\r\n )\r\n\r\n const mapRef = React.useRef<MapRef>(null)\r\n const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext)\r\n\r\n const handleMapLoad = () => {\r\n const map = mapRef.current.getMap()\r\n\r\n // Only dispatch SET_MAP after map is fully loaded\r\n if (mapRef.current) {\r\n mapDispatch({\r\n type: 'SET_MAP',\r\n payload: { map },\r\n })\r\n }\r\n // initilize a new click manager\r\n const mapClickManager = new MapClickManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_CLICK_MANAGER',\r\n payload: { mapClickManager },\r\n })\r\n\r\n const mapHoverManager = new MapHoverManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_HOVER_MANAGER',\r\n payload: { mapHoverManager },\r\n })\r\n\r\n // update current Location with URL params or fallback to theme location\r\n const updatedLocation: CurrentLocation = {\r\n // Then override with URL params (this ensures URL params take precedence)\r\n lat: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n lng: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n // Add location details from URL params if available\r\n countrySubdivision: searchParams.has('countrySubdivision') ? searchParams.get('countrySubdivision') : (organization.countrySubdivision ?? ''),\r\n municipality: searchParams.has('municipality') ? searchParams.get('municipality') : (organization.municipality ?? ''),\r\n address: searchParams.has('address') ? searchParams.get('address') : '', // organization.address,\r\n site: searchParams.has('site') ? searchParams.get('site') : String(organization.locationSiteId ?? ''),\r\n id: String(organization.id),\r\n }\r\n\r\n mapDispatch({\r\n type: 'UPDATE_LOCATION',\r\n payload: { currentLocation: updatedLocation },\r\n })\r\n\r\n // Set map as loaded after all dispatches are complete\r\n setIsMapLoaded(true)\r\n }\r\n\r\n // Enable the perf HUD by appending ?debug=1 to the URL. Never reaches\r\n // production users unless they explicitly opt in.\r\n const isDebug = searchParams.get('debug') === '1'\r\n\r\n // useCallback so the onDblClick prop identity is stable across renders of\r\n // MapViewer; a new function each render caused react-map-gl to detach/re-attach\r\n // the listener. The console.log is gated behind a dev-mode check.\r\n const onDblClick = React.useCallback((e) => {\r\n if (process.env.NODE_ENV === 'production') return\r\n const { lng, lat } = e.lngLat\r\n const elevation = mapRef.current?.queryTerrainElevation([lng, lat]) || 0\r\n const coordinates = { lng, lat, elevation, zoom: mapRef.current?.getZoom() }\r\n console.log('📍 Map coordinates:', coordinates)\r\n }, [])\r\n\r\n const mapStyle = mapState?.map.mapStyle ?? DEFAULT_MAP_STYLE;\r\n\r\n return (\r\n <>\r\n <Map\r\n id=\"map-component\"\r\n mapStyle={ mapStyle.url}\r\n mapLib={maplibregl}\r\n onLoad={handleMapLoad}\r\n ref={mapRef}\r\n style={mapContainerStyle}\r\n initialViewState={viewState}\r\n maxPitch={60}\r\n minZoom={organization?.minZoom ?? CANADA_DEFAULTS.zoom}\r\n maxBounds={resolveBounds(organization?.maxBounds, CANADA_DEFAULTS.maxBounds)}\r\n projection=\"globe\"\r\n doubleClickZoom={false}\r\n onDblClick={onDblClick}\r\n pixelRatio={pixelRatio}\r\n >\r\n <NavigationControl visualizePitch />\r\n <SettingsButton /> \r\n {isMapLoaded\r\n && (\r\n <>\r\n <MapLayers />\r\n {/* Bottom-left stack: legend above the layers/styling card, gap auto-managed by flex. */}\r\n <div className=\"absolute bottom-[10px] left-3 z-10 flex flex-col gap-2 pointer-events-none\">\r\n {/* Portal slot for on-map WMS time controls; display:contents so an\r\n empty slot adds no flex item / gap, but a mounted control stacks\r\n above the legend + dataset-manager cards. */}\r\n <div id=\"wms-time-slot\" style={{ display: 'contents' }} />\r\n <MapLegendHost />\r\n <DatasetManagerMenu />\r\n </div>\r\n </>\r\n )}\r\n </Map>\r\n <StatsOverlay mapRef={mapRef} enabled={isDebug} />\r\n </>\r\n\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/core/components/viewers/map/MapViewer.tsx"],"sourcesContent":["'use client'\r\n\r\nimport Map, { MapRef, NavigationControl } from 'react-map-gl/maplibre'\r\nimport React from 'react'\r\n\r\nimport maplibregl, { LngLatBoundsLike } from 'maplibre-gl'\r\nimport { useSearchParams } from 'next/navigation'\r\n\r\nimport { MapContext } from '../../../store'\r\nimport { resolveBounds } from './utils/validateBounds'\r\n\r\nimport { MapClickManager } from './utils/MapEventManager/MapClickManager'\r\nimport DatasetManagerMenu from './datasets/DatasetManager'\r\nimport { MapLegendHost } from './legends/MapLegendHost'\r\nimport { StatsOverlay } from '../../ui/stats'\r\nimport { MapHoverManager } from './utils/MapEventManager/MapHoverManager'\r\nimport { Organization } from '../../../types/dbTypes'\r\nimport { CurrentLocation } from '../../../types/map'\r\nimport { MapLayers } from './src/MapLayers'\r\nimport SettingsButton from '../../ui/SettingsButton'\r\n\r\nconst CANADA_DEFAULTS = {\r\n maxBounds: [-141.0, 41.6751050889, -52.6480987209, 83.23324] as LngLatBoundsLike,\r\n zoom: 3,\r\n lat: 56.415,\r\n long: -98.74,\r\n} as const\r\n\r\nconst DEFAULT_MAP_STYLE = { name: 'Satellite', url: 'mapStyles/satellite.json' } as const\r\nconst MAX_GLOBE_ZOOM = 5\r\n\r\ninterface Props {\r\n width?: string\r\n height?: string\r\n organization: Organization\r\n}\r\n\r\nexport function MapViewer({ width = '100%', height = '100%', organization }: Props) {\r\n\r\n const searchParams = useSearchParams()\r\n\r\n // Add state to track if map is loaded\r\n const [isMapLoaded, setIsMapLoaded] = React.useState(false)\r\n\r\n const viewState = React.useMemo(() => {\r\n return searchParams.size === 0\r\n ? {\r\n zoom: organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n bearing: organization.bearing ?? 0,\r\n pitch: organization.pitch ?? 0,\r\n longitude: organization.long ?? CANADA_DEFAULTS.long,\r\n latitude: organization.lat ?? CANADA_DEFAULTS.lat,\r\n }\r\n : {\r\n latitude: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n longitude: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n }\r\n }, [searchParams, organization])\r\n\r\n const initialProjection = viewState.zoom > MAX_GLOBE_ZOOM ? 'mercator' : 'globe'\r\n\r\n // Memoize the inline style object that gets passed to <Map> for a stable prop identity.\r\n const mapContainerStyle = React.useMemo(\r\n () => ({ width, height, backgroundColor: 'black' }),\r\n [width, height],\r\n )\r\n\r\n // Adaptive pixel ratio. A hardcoded 2 doubled fragment-shader cost on 1× DPR\r\n // desktops for zero visual gain; capping at 2 keeps phones (DPR 3-4) effective.\r\n const pixelRatio = React.useMemo(\r\n () => Math.min(typeof window !== 'undefined' ? window.devicePixelRatio : 1, 2),\r\n [],\r\n )\r\n\r\n const mapRef = React.useRef<MapRef>(null)\r\n const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext)\r\n\r\n // Keep the projection in sync with zoom at all times — not only while the\r\n // map-settings sidebar is mounted. The globe projection degrades past\r\n // MAX_GLOBE_ZOOM, so we force mercator regardless of which panels are open.\r\n const activeMap = mapState?.map?.map\r\n\r\n React.useEffect(() => {\r\n if (!activeMap) return\r\n\r\n const enforceProjectionForZoom = () => {\r\n if (activeMap.getZoom() <= MAX_GLOBE_ZOOM) return\r\n\r\n const projection = activeMap.getProjection()\r\n const currentType =\r\n typeof projection === 'string'\r\n ? projection\r\n : (projection as { type?: string; name?: string })?.type ?? (projection as { type?: string; name?: string })?.name\r\n\r\n if (currentType !== 'mercator') {\r\n activeMap.setProjection({ type: 'mercator' })\r\n }\r\n }\r\n\r\n enforceProjectionForZoom()\r\n activeMap.on('zoom', enforceProjectionForZoom)\r\n\r\n return () => {\r\n activeMap.off('zoom', enforceProjectionForZoom)\r\n }\r\n }, [activeMap])\r\n\r\n const handleMapLoad = () => {\r\n const map = mapRef.current.getMap()\r\n\r\n if (map.getZoom() > MAX_GLOBE_ZOOM) {\r\n map.setProjection({ type: 'mercator' })\r\n }\r\n\r\n // Only dispatch SET_MAP after map is fully loaded\r\n if (mapRef.current) {\r\n mapDispatch({\r\n type: 'SET_MAP',\r\n payload: { map },\r\n })\r\n }\r\n // initilize a new click manager\r\n const mapClickManager = new MapClickManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_CLICK_MANAGER',\r\n payload: { mapClickManager },\r\n })\r\n\r\n const mapHoverManager = new MapHoverManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_HOVER_MANAGER',\r\n payload: { mapHoverManager },\r\n })\r\n\r\n // update current Location with URL params or fallback to theme location\r\n const updatedLocation: CurrentLocation = {\r\n // Then override with URL params (this ensures URL params take precedence)\r\n lat: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n lng: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n // Add location details from URL params if available\r\n countrySubdivision: searchParams.has('countrySubdivision') ? searchParams.get('countrySubdivision') : (organization.countrySubdivision ?? ''),\r\n municipality: searchParams.has('municipality') ? searchParams.get('municipality') : (organization.municipality ?? ''),\r\n address: searchParams.has('address') ? searchParams.get('address') : '', // organization.address,\r\n site: searchParams.has('site') ? searchParams.get('site') : String(organization.locationSiteId ?? ''),\r\n id: String(organization.id),\r\n }\r\n\r\n mapDispatch({\r\n type: 'UPDATE_LOCATION',\r\n payload: { currentLocation: updatedLocation },\r\n })\r\n\r\n // Set map as loaded after all dispatches are complete\r\n setIsMapLoaded(true)\r\n }\r\n\r\n // Enable the perf HUD by appending ?debug=1 to the URL. Never reaches\r\n // production users unless they explicitly opt in.\r\n const isDebug = searchParams.get('debug') === '1'\r\n\r\n // useCallback so the onDblClick prop identity is stable across renders of\r\n // MapViewer; a new function each render caused react-map-gl to detach/re-attach\r\n // the listener. The console.log is gated behind a dev-mode check.\r\n const onDblClick = React.useCallback((e) => {\r\n if (process.env.NODE_ENV === 'production') return\r\n const { lng, lat } = e.lngLat\r\n const elevation = mapRef.current?.queryTerrainElevation([lng, lat]) || 0\r\n const coordinates = { lng, lat, elevation, zoom: mapRef.current?.getZoom() }\r\n console.log('📍 Map coordinates:', coordinates)\r\n }, [])\r\n\r\n const mapStyle = mapState?.map.mapStyle ?? DEFAULT_MAP_STYLE;\r\n\r\n return (\r\n <>\r\n <Map\r\n id=\"map-component\"\r\n mapStyle={mapStyle.url}\r\n mapLib={maplibregl}\r\n onLoad={handleMapLoad}\r\n ref={mapRef}\r\n style={mapContainerStyle}\r\n initialViewState={viewState}\r\n maxPitch={60}\r\n minZoom={organization?.minZoom ?? CANADA_DEFAULTS.zoom}\r\n maxBounds={resolveBounds(organization?.maxBounds, CANADA_DEFAULTS.maxBounds)}\r\n projection={initialProjection}\r\n doubleClickZoom={false}\r\n onDblClick={onDblClick}\r\n pixelRatio={pixelRatio}\r\n >\r\n <NavigationControl visualizePitch />\r\n <SettingsButton />\r\n {isMapLoaded\r\n && (\r\n <>\r\n <MapLayers />\r\n {/* Bottom-left stack: legend above the layers/styling card, gap auto-managed by flex. */}\r\n <div className=\"absolute bottom-[10px] left-3 z-10 flex flex-col gap-2 pointer-events-none\">\r\n {/* Portal slot for on-map WMS time controls; display:contents so an\r\n empty slot adds no flex item / gap, but a mounted control stacks\r\n above the legend + dataset-manager cards. */}\r\n <div id=\"wms-time-slot\" style={{ display: 'contents' }} />\r\n <MapLegendHost />\r\n <DatasetManagerMenu />\r\n </div>\r\n </>\r\n )}\r\n </Map>\r\n <StatsOverlay mapRef={mapRef} enabled={isDebug} />\r\n </>\r\n\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b","_c"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/src/MapSidebar/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/src/MapSidebar/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAY9B,wBAAgB,UAAU,sBA2BzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../src/core/components/viewers/map/src/MapSidebar/index.tsx"],"sourcesContent":["'use client'\r\nimport * as React from 'react'\r\nimport { TabSelector } from './TabSelector'\r\nimport { MenusContext, usePermissions } from '../../../../../store'\r\nimport { SidebarTabType } from '../../../../../store/Menus/reducer'\r\nimport { FileTab } from './src/FileTab'\r\nimport { LayersTab } from './src/LayersTab'\r\n
|
|
1
|
+
{"version":3,"sources":["../../../../../../../src/core/components/viewers/map/src/MapSidebar/index.tsx"],"sourcesContent":["'use client'\r\nimport * as React from 'react'\r\nimport { TabSelector } from './TabSelector'\r\nimport { MenusContext, usePermissions } from '../../../../../store'\r\nimport { SidebarTabType } from '../../../../../store/Menus/reducer'\r\nimport { FileTab } from './src/FileTab'\r\nimport { LayersTab } from './src/LayersTab'\r\n\r\nimport { SettingsTab } from './src/SettingsTab'\r\nimport { InfoSidebarContainer } from '../../../../../components/ui/InfoSidebar/Container'\r\nimport { CommunicationTab } from './src/CommunicationTab'\r\nimport { SensorsTab } from './src/SensorsTab'\r\n\r\nexport function MapSidebar() {\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const { state: menusState, dispatch: menusDispatch } = React.useContext(MenusContext)\r\n const { selectedTab } = menusState.menus\r\n\r\n const handleTabChange = (selectedTab: SidebarTabType) => {\r\n menusDispatch({ type: 'SET_SIDEBAR_SELECTED_TAB', payload: { selectedTab } })\r\n }\r\n\r\n return (\r\n <InfoSidebarContainer\r\n tabSelector={\r\n <TabSelector\r\n activeTab={selectedTab}\r\n onTabChangeAction={handleTabChange}\r\n />\r\n }\r\n >\r\n {selectedTab === 'file' && ability.can('read', 'File') && <FileTab />}\r\n {selectedTab === 'layers' && ability.can('read', 'File') && <LayersTab />}\r\n {selectedTab === 'communication' && ability.can('read', 'Comment') && <CommunicationTab />}\r\n {selectedTab === 'sensors' && ability.can('read', 'Sensor') && <SensorsTab />}\r\n {selectedTab === 'settings' && <SettingsTab />} \r\n </InfoSidebarContainer>\r\n )\r\n}"],"mappings":";AAyBI,SAEI,KAFJ;AAxBJ,YAAY,WAAW;AACvB,SAAS,mBAAmB;AAC5B,SAAS,cAAc,sBAAsB;AAE7C,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAE1B,SAAS,mBAAmB;AAC5B,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AACjC,SAAS,kBAAkB;AAEpB,SAAS,aAAa;AAE3B,QAAM,EAAE,QAAQ,IAAI,eAAe;AAEnC,QAAM,EAAE,OAAO,YAAY,UAAU,cAAc,IAAI,MAAM,WAAW,YAAY;AACpF,QAAM,EAAE,YAAY,IAAI,WAAW;AAEnC,QAAM,kBAAkB,CAACA,iBAAgC;AACvD,kBAAc,EAAE,MAAM,4BAA4B,SAAS,EAAE,aAAAA,aAAY,EAAE,CAAC;AAAA,EAC9E;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aACE;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,UACX,mBAAmB;AAAA;AAAA,MACrB;AAAA,MAGD;AAAA,wBAAgB,UAAU,QAAQ,IAAI,QAAQ,MAAM,KAAK,oBAAC,WAAQ;AAAA,QAClE,gBAAgB,YAAY,QAAQ,IAAI,QAAQ,MAAM,KAAK,oBAAC,aAAU;AAAA,QACtE,gBAAgB,mBAAmB,QAAQ,IAAI,QAAQ,SAAS,KAAK,oBAAC,oBAAiB;AAAA,QACvF,gBAAgB,aAAa,QAAQ,IAAI,QAAQ,QAAQ,KAAK,oBAAC,cAAW;AAAA,QAC1E,gBAAgB,cAAc,oBAAC,eAAY;AAAA;AAAA;AAAA,EAC9C;AAEJ;","names":["selectedTab"]}
|
package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapProjection.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"MapProjection.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,wBAAgB,aAAa,sBAyE5B"}
|
package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.js
CHANGED
|
@@ -5,6 +5,7 @@ import { useTranslations } from "next-intl";
|
|
|
5
5
|
import * as LR from "lucide-react";
|
|
6
6
|
import { Tabs, TabsList, TabsTrigger } from "../../../../../../../ui/Tabs";
|
|
7
7
|
import { MapContext } from "../../../../../../../../store";
|
|
8
|
+
const MAX_GLOBE_ZOOM = 5;
|
|
8
9
|
function MapProjection() {
|
|
9
10
|
const tMap = useTranslations("MapCustomization");
|
|
10
11
|
const { state: mapState } = React.useContext(MapContext);
|
|
@@ -20,20 +21,29 @@ function MapProjection() {
|
|
|
20
21
|
const projectionType = (_a = projection == null ? void 0 : projection.type) != null ? _a : projection == null ? void 0 : projection.name;
|
|
21
22
|
return projectionType === "globe" ? "globe" : "mercator";
|
|
22
23
|
}, [map]);
|
|
23
|
-
React.
|
|
24
|
-
if (!map
|
|
24
|
+
const syncProjectionDisplay = React.useCallback(() => {
|
|
25
|
+
if (!map) return;
|
|
25
26
|
setMapProjection(getCurrentProjection());
|
|
26
|
-
}, [
|
|
27
|
-
|
|
27
|
+
}, [getCurrentProjection, map]);
|
|
28
|
+
React.useEffect(() => {
|
|
28
29
|
if (!map) return;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
syncProjectionDisplay();
|
|
31
|
+
map.on("zoom", syncProjectionDisplay);
|
|
32
|
+
return () => {
|
|
33
|
+
map.off("zoom", syncProjectionDisplay);
|
|
34
|
+
};
|
|
35
|
+
}, [map, syncProjectionDisplay]);
|
|
36
|
+
const handleMapProjection = (value) => {
|
|
37
|
+
if (!map) return;
|
|
38
|
+
const forcedProjection = map.getZoom() > MAX_GLOBE_ZOOM ? "mercator" : value;
|
|
39
|
+
if (getCurrentProjection() !== forcedProjection) {
|
|
40
|
+
map.setProjection({ type: forcedProjection });
|
|
41
|
+
}
|
|
42
|
+
setMapProjection(forcedProjection);
|
|
33
43
|
};
|
|
34
44
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
35
45
|
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: tMap("mapProjection") }),
|
|
36
|
-
/* @__PURE__ */ jsx(Tabs, { value: mapProjection, onValueChange: handleMapProjection, variant: "switch", children: /* @__PURE__ */ jsxs(TabsList, { className: "grid w-full grid-cols-2", children: [
|
|
46
|
+
/* @__PURE__ */ jsx(Tabs, { value: mapProjection, onValueChange: (value) => handleMapProjection(value), variant: "switch", children: /* @__PURE__ */ jsxs(TabsList, { className: "grid w-full grid-cols-2", children: [
|
|
37
47
|
/* @__PURE__ */ jsxs(TabsTrigger, { value: "globe", children: [
|
|
38
48
|
/* @__PURE__ */ jsx(LR.Globe, { className: "w-4 h-4 mr-2" }),
|
|
39
49
|
tMap("globe")
|
package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.tsx"],"sourcesContent":["'use client'\r\n\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\nimport * as LR from 'lucide-react'\r\nimport { Tabs, TabsList, TabsTrigger } from '../../../../../../../ui/Tabs'\r\nimport { MapContext } from '../../../../../../../../store'\r\n\r\ntype MapProjectionType = 'globe' | 'mercator'\r\n\r\nexport function MapProjection() {\r\n const tMap = useTranslations('MapCustomization')\r\n const { state: mapState } = React.useContext(MapContext)\r\n const { map } = mapState.map\r\n const [mapProjection, setMapProjection] = React.useState<MapProjectionType>('globe')\r\n\r\n const getCurrentProjection = React.useCallback((): MapProjectionType => {\r\n if (!map) return 'globe'\r\n\r\n const projection = map.getProjection()\r\n\r\n if (typeof projection === 'string') {\r\n return projection === 'globe' ? 'globe' : 'mercator'\r\n }\r\n\r\n const projectionType =\r\n (projection as { type?: string; name?: string })?.type ??\r\n (projection as { type?: string; name?: string })?.name\r\n\r\n return projectionType === 'globe' ? 'globe' : 'mercator'\r\n }, [map])\r\n\r\n React.
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../../src/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.tsx"],"sourcesContent":["'use client'\r\n\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\nimport * as LR from 'lucide-react'\r\nimport { Tabs, TabsList, TabsTrigger } from '../../../../../../../ui/Tabs'\r\nimport { MapContext } from '../../../../../../../../store'\r\n\r\ntype MapProjectionType = 'globe' | 'mercator'\r\n\r\nconst MAX_GLOBE_ZOOM = 5\r\n\r\nexport function MapProjection() {\r\n const tMap = useTranslations('MapCustomization')\r\n const { state: mapState } = React.useContext(MapContext)\r\n const { map } = mapState.map\r\n const [mapProjection, setMapProjection] = React.useState<MapProjectionType>('globe')\r\n\r\n const getCurrentProjection = React.useCallback((): MapProjectionType => {\r\n if (!map) return 'globe'\r\n\r\n const projection = map.getProjection()\r\n\r\n if (typeof projection === 'string') {\r\n return projection === 'globe' ? 'globe' : 'mercator'\r\n }\r\n\r\n const projectionType =\r\n (projection as { type?: string; name?: string })?.type ??\r\n (projection as { type?: string; name?: string })?.name\r\n\r\n return projectionType === 'globe' ? 'globe' : 'mercator'\r\n }, [map])\r\n\r\n // Display-only sync. The zoom-based enforcement (forcing mercator past\r\n // MAX_GLOBE_ZOOM) now lives in MapViewer so it runs whether or not this\r\n // settings panel is mounted; here we just mirror the map's current projection\r\n // into the toggle UI.\r\n const syncProjectionDisplay = React.useCallback(() => {\r\n if (!map) return\r\n\r\n setMapProjection(getCurrentProjection())\r\n }, [getCurrentProjection, map])\r\n\r\n React.useEffect(() => {\r\n if (!map) return\r\n\r\n syncProjectionDisplay()\r\n\r\n map.on('zoom', syncProjectionDisplay)\r\n\r\n return () => {\r\n map.off('zoom', syncProjectionDisplay)\r\n }\r\n }, [map, syncProjectionDisplay])\r\n\r\n const handleMapProjection = (value: MapProjectionType) => {\r\n if (!map) return\r\n\r\n const forcedProjection = map.getZoom() > MAX_GLOBE_ZOOM ? 'mercator' : value\r\n\r\n if (getCurrentProjection() !== forcedProjection) {\r\n map.setProjection({ type: forcedProjection })\r\n }\r\n\r\n setMapProjection(forcedProjection)\r\n }\r\n\r\n return (\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium\">{tMap('mapProjection')}</label>\r\n <Tabs value={mapProjection} onValueChange={value => handleMapProjection(value as MapProjectionType)} variant=\"switch\">\r\n <TabsList className=\"grid w-full grid-cols-2\">\r\n <TabsTrigger value=\"globe\">\r\n <LR.Globe className=\"w-4 h-4 mr-2\" />\r\n {tMap('globe')}\r\n </TabsTrigger>\r\n <TabsTrigger value=\"mercator\">\r\n <LR.Map className=\"w-4 h-4 mr-2\" />\r\n {tMap('mercator')}\r\n </TabsTrigger>\r\n </TabsList>\r\n </Tabs>\r\n </div>\r\n )\r\n}\r\n"],"mappings":";AAsEM,cAGI,YAHJ;AApEN,YAAY,WAAW;AACvB,SAAS,uBAAuB;AAChC,YAAY,QAAQ;AACpB,SAAS,MAAM,UAAU,mBAAmB;AAC5C,SAAS,kBAAkB;AAI3B,MAAM,iBAAiB;AAEhB,SAAS,gBAAgB;AAC9B,QAAM,OAAO,gBAAgB,kBAAkB;AAC/C,QAAM,EAAE,OAAO,SAAS,IAAI,MAAM,WAAW,UAAU;AACvD,QAAM,EAAE,IAAI,IAAI,SAAS;AACzB,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAA4B,OAAO;AAEnF,QAAM,uBAAuB,MAAM,YAAY,MAAyB;AAlB1E;AAmBI,QAAI,CAAC,IAAK,QAAO;AAEjB,UAAM,aAAa,IAAI,cAAc;AAErC,QAAI,OAAO,eAAe,UAAU;AAClC,aAAO,eAAe,UAAU,UAAU;AAAA,IAC5C;AAEA,UAAM,kBACH,8CAAiD,SAAjD,YACA,yCAAiD;AAEpD,WAAO,mBAAmB,UAAU,UAAU;AAAA,EAChD,GAAG,CAAC,GAAG,CAAC;AAMR,QAAM,wBAAwB,MAAM,YAAY,MAAM;AACpD,QAAI,CAAC,IAAK;AAEV,qBAAiB,qBAAqB,CAAC;AAAA,EACzC,GAAG,CAAC,sBAAsB,GAAG,CAAC;AAE9B,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,IAAK;AAEV,0BAAsB;AAEtB,QAAI,GAAG,QAAQ,qBAAqB;AAEpC,WAAO,MAAM;AACX,UAAI,IAAI,QAAQ,qBAAqB;AAAA,IACvC;AAAA,EACF,GAAG,CAAC,KAAK,qBAAqB,CAAC;AAE/B,QAAM,sBAAsB,CAAC,UAA6B;AACxD,QAAI,CAAC,IAAK;AAEV,UAAM,mBAAmB,IAAI,QAAQ,IAAI,iBAAiB,aAAa;AAEvE,QAAI,qBAAqB,MAAM,kBAAkB;AAC/C,UAAI,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAAA,IAC9C;AAEA,qBAAiB,gBAAgB;AAAA,EACnC;AAEA,SACE,qBAAC,SAAI,WAAU,aACb;AAAA,wBAAC,WAAM,WAAU,uBAAuB,eAAK,eAAe,GAAE;AAAA,IAC9D,oBAAC,QAAK,OAAO,eAAe,eAAe,WAAS,oBAAoB,KAA0B,GAAG,SAAQ,UAC3G,+BAAC,YAAS,WAAU,2BAClB;AAAA,2BAAC,eAAY,OAAM,SACjB;AAAA,4BAAC,GAAG,OAAH,EAAS,WAAU,gBAAe;AAAA,QAClC,KAAK,OAAO;AAAA,SACf;AAAA,MACA,qBAAC,eAAY,OAAM,YACjB;AAAA,4BAAC,GAAG,KAAH,EAAO,WAAU,gBAAe;AAAA,QAChC,KAAK,UAAU;AAAA,SAClB;AAAA,OACF,GACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Feature } from 'geojson';
|
|
2
|
-
import { MarkerManager } from './MarkerManager';
|
|
3
2
|
export declare const getMunicipalityAndProvince: (latitude: string, longitude: string, countryCode?: string) => Promise<{
|
|
4
3
|
municipality: any;
|
|
5
4
|
countrySubdivision: any;
|
|
@@ -65,8 +64,4 @@ export declare const buildingToFeature: (building: any) => {
|
|
|
65
64
|
};
|
|
66
65
|
is_database_building: boolean;
|
|
67
66
|
};
|
|
68
|
-
export declare const createGeocoderMarker: (coordinates: [number, number], map: any, options?: {
|
|
69
|
-
editing?: boolean;
|
|
70
|
-
}) => MarkerManager;
|
|
71
|
-
export declare const removeGeocoderMarker: () => void;
|
|
72
67
|
//# sourceMappingURL=geocoder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geocoder.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/map/utils/geocoder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAS,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"geocoder.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/map/utils/geocoder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAS,MAAM,SAAS,CAAA;AAgBxC,eAAO,MAAM,0BAA0B,GAAU,UAAU,MAAM,EAAE,WAAW,MAAM,EAAE,cAAc,MAAM;;;EAmBzG,CAAA;AAGD,eAAO,MAAM,gBAAgB,GAAU,OAAO,MAAM,EAAE,cAAc,MAAM;;KAYzE,CAAA;AAGD,eAAO,MAAM,aAAa,GAAI,SAAS,OAAO;;;;CAoC7C,CAAA;AAGD,eAAO,MAAM,oBAAoB,GAAI,SAAS,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,EAAE,UAAU;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqF7G,CAAA;AAGD,eAAO,MAAM,kBAAkB,GAAU,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,MAAM;;GAc3F,CAAA;AAGD,eAAO,MAAM,iBAAiB,GAAI,aAAQ;;;;;;;;;;;;;;;CAgCzC,CAAA"}
|
|
@@ -77,7 +77,6 @@ const handleLocationSelect = (feature, map, type, options) => {
|
|
|
77
77
|
is_database_building: true
|
|
78
78
|
};
|
|
79
79
|
if (map && center2) {
|
|
80
|
-
markerManager.create(center2, map);
|
|
81
80
|
map.flyTo({
|
|
82
81
|
center: addressData2.coordinates,
|
|
83
82
|
zoom: 18,
|
|
@@ -122,7 +121,6 @@ const handleLocationSelect = (feature, map, type, options) => {
|
|
|
122
121
|
// How well the result matches the query
|
|
123
122
|
};
|
|
124
123
|
if (map && center) {
|
|
125
|
-
markerManager.create(center, map, { editing });
|
|
126
124
|
if (feature.bbox) {
|
|
127
125
|
map.fitBounds(feature.bbox, { speed: 2 });
|
|
128
126
|
} else {
|
|
@@ -175,24 +173,12 @@ const buildingToFeature = (building) => {
|
|
|
175
173
|
is_database_building: true
|
|
176
174
|
};
|
|
177
175
|
};
|
|
178
|
-
const createGeocoderMarker = (coordinates, map, options) => {
|
|
179
|
-
const editing = (options == null ? void 0 : options.editing) || false;
|
|
180
|
-
const markerManager = getGeocoderMarkerManager();
|
|
181
|
-
markerManager.create(coordinates, map, { editing });
|
|
182
|
-
return markerManager;
|
|
183
|
-
};
|
|
184
|
-
const removeGeocoderMarker = () => {
|
|
185
|
-
const markerManager = getGeocoderMarkerManager();
|
|
186
|
-
markerManager.remove();
|
|
187
|
-
};
|
|
188
176
|
export {
|
|
189
177
|
buildingToFeature,
|
|
190
|
-
createGeocoderMarker,
|
|
191
178
|
fetchSuggestions,
|
|
192
179
|
getDetailedAddress,
|
|
193
180
|
getMunicipalityAndProvince,
|
|
194
181
|
handleLocationSelect,
|
|
195
|
-
parseLocation
|
|
196
|
-
removeGeocoderMarker
|
|
182
|
+
parseLocation
|
|
197
183
|
};
|
|
198
184
|
//# sourceMappingURL=geocoder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/core/components/viewers/map/utils/geocoder.ts"],"sourcesContent":["import { Feature, Point } from 'geojson'\r\nimport { MarkerManager } from './MarkerManager'\r\nimport { autocompleteGeocode, reverseGeocode } from './geocoding'\r\n\r\n// Global marker manager instance for geocoder\r\nlet geocoderMarkerManager: MarkerManager | null = null\r\n\r\n// Helper function to get or create the marker manager\r\nconst getGeocoderMarkerManager = (): MarkerManager => {\r\n if (!geocoderMarkerManager) {\r\n geocoderMarkerManager = new MarkerManager()\r\n }\r\n return geocoderMarkerManager\r\n}\r\n\r\n// Convert longitude and latitude into Municipality and Country Subdivision\r\nexport const getMunicipalityAndProvince = async (latitude: string, longitude: string, countryCode?: string) => {\r\n try {\r\n const features = await reverseGeocode(latitude, longitude, countryCode, { size: 1, coarse: true })\r\n\r\n if (features.length > 0) {\r\n const properties = features[0].properties as any\r\n\r\n const municipality = properties.locality || properties.neighbourhood || properties.county || ''\r\n const countrySubdivision = properties.region_a || properties.region || '' // region_a gives abbreviation like \"ON\", \"BC\"\r\n\r\n return { municipality, countrySubdivision }\r\n }\r\n\r\n return { municipality: '', countrySubdivision: '' }\r\n }\r\n catch (error) {\r\n console.error('Error fetching municipality and country subdivision:', error)\r\n return { municipality: '', countrySubdivision: '' }\r\n }\r\n}\r\n\r\n// Fetch address suggestions from the active autocomplete provider\r\nexport const fetchSuggestions = async (input: string, countryCode?: string) => {\r\n if (!input || input.length < 3) {\r\n return []\r\n }\r\n\r\n try {\r\n return await autocompleteGeocode(input, countryCode, 5)\r\n }\r\n catch (error) {\r\n console.error('Error fetching address suggestions:', error)\r\n return []\r\n }\r\n}\r\n\r\n// Parse location details for better display\r\nexport const parseLocation = (feature: Feature) => {\r\n const locationName = feature.properties?.name || ''\r\n const fullLabel = feature.properties?.label || ''\r\n\r\n // Try to extract location details from properties\r\n const properties = feature.properties\r\n let regionDetails = ''\r\n\r\n if (properties) {\r\n const locality = properties.locality\r\n const region = properties.region // Full countrySubdivision name\r\n const region_a = properties.region_a // CountrySubdivision abbreviation (ON, BC, etc.)\r\n const country = properties.country\r\n const country_a = properties.country_a // Country abbreviation (CA)\r\n\r\n // Build region details similar to your original format\r\n if (locality && region_a && country_a) {\r\n regionDetails = `${locality}, ${region_a}, ${country_a}`\r\n }\r\n else if (locality && region && country) {\r\n regionDetails = `${locality}, ${region}, ${country}`\r\n }\r\n else {\r\n // Fallback: try to extract from the full label\r\n const parts = fullLabel.split(', ')\r\n if (parts.length > 1) {\r\n regionDetails = parts.slice(1, 3).join(', ')\r\n }\r\n }\r\n }\r\n\r\n return {\r\n name: locationName,\r\n region: regionDetails,\r\n fullLabel: fullLabel,\r\n }\r\n}\r\n\r\n// Handle suggestion selection and map movement\r\nexport const handleLocationSelect = (feature: Feature, map: any, type: string, options?: { editing?: boolean }) => {\r\n const editing = options?.editing || false\r\n const markerManager = getGeocoderMarkerManager()\r\n\r\n // Handle feature with is_database_building flag\r\n if (type === 'dbBuilding') {\r\n const geometry = feature.geometry as Point\r\n const center = geometry.coordinates\r\n const addressData = {\r\n formatted_address: feature.properties?.label || '',\r\n coordinates: center,\r\n properties: feature.properties,\r\n building_id: feature.properties.gid?.replace('building-', ''),\r\n is_database_building: true,\r\n }\r\n\r\n if (map && center) {\r\n // Add marker to the center with editing capability\r\n markerManager.create(center as [number, number], map)\r\n\r\n map.flyTo({\r\n center: addressData.coordinates,\r\n zoom: 18,\r\n speed: 1.5,\r\n })\r\n }\r\n\r\n return addressData\r\n }\r\n\r\n // Calculate center coordinates\r\n let center\r\n\r\n // Use bbox if available (more precise for areas)\r\n if (feature.bbox) {\r\n center = [\r\n feature.bbox[0] + (feature.bbox[2] - feature.bbox[0]) / 2,\r\n feature.bbox[1] + (feature.bbox[3] - feature.bbox[1]) / 2,\r\n ]\r\n }\r\n // Otherwise extract coordinates based on geometry type\r\n else if (feature.geometry?.type === 'Point') {\r\n center = (feature.geometry as any).coordinates\r\n }\r\n\r\n const addressData = {\r\n formatted_address: feature.properties?.label || feature.properties?.name || '',\r\n coordinates: center,\r\n properties: feature.properties,\r\n address_details: {\r\n name: feature.properties?.name,\r\n label: feature.properties?.label,\r\n locality: feature.properties?.locality,\r\n neighbourhood: feature.properties?.neighbourhood,\r\n region: feature.properties?.region,\r\n region_a: feature.properties?.region_a,\r\n country: feature.properties?.country,\r\n country_a: feature.properties?.country_a,\r\n postalcode: feature.properties?.postalcode,\r\n housenumber: feature.properties?.housenumber,\r\n street: feature.properties?.street,\r\n },\r\n geocode_earth_id: feature.properties?.gid, // Geocode Earth's unique id\r\n layer: feature.properties?.layer, // Type of place (address, venue, locality, etc.)\r\n confidence: feature.properties?.confidence, // Geocode Earth's confidence score\r\n match_type: feature.properties?.match_type, // How well the result matches the query\r\n }\r\n\r\n if (map && center) {\r\n // Add marker to the center with editing capability\r\n markerManager.create(center as [number, number], map, { editing })\r\n\r\n if (feature.bbox) {\r\n map.fitBounds(feature.bbox, { speed: 2 })\r\n }\r\n else {\r\n map.flyTo({\r\n center: addressData.coordinates,\r\n zoom: 14, // Might be good idea to set zoom level depending on layer / type of place\r\n speed: 2,\r\n })\r\n }\r\n }\r\n\r\n return addressData\r\n}\r\n\r\n// Util function to get detailed address information\r\nexport const getDetailedAddress = async (coordinates: [number, number], countryCode?: string) => {\r\n const [longitude, latitude] = coordinates\r\n\r\n try {\r\n // Restrict to address-layer results (the original popover used layers=address) so\r\n // callers get a street address rather than the nearest venue/POI. Nominatim's zoom-18\r\n // reverse is already building-level, so this only refines the Pelias path.\r\n const features = await reverseGeocode(latitude.toString(), longitude.toString(), countryCode, { size: 1, layers: 'address' })\r\n return features.length > 0 ? features[0] : null\r\n }\r\n catch (error) {\r\n console.error('Error fetching detailed address:', error)\r\n return null\r\n }\r\n}\r\n\r\n// Convert a building object to a GeoJSON feature format compatible with handleLocationSelect\r\nexport const buildingToFeature = (building) => {\r\n const name = building.buildingName || ''\r\n\r\n // Validate coordinates - use the correct property names\r\n const longitude = Number.parseFloat(building.buildingLongitude)\r\n const latitude = Number.parseFloat(building.buildingLatitude)\r\n\r\n if (isNaN(longitude) || isNaN(latitude)) {\r\n console.error('Invalid building coordinates:', {\r\n longitude: building.buildingLongitude,\r\n latitude: building.buildingLatitude,\r\n buildingId: building.id,\r\n })\r\n return null\r\n }\r\n\r\n return {\r\n properties: {\r\n name: name,\r\n label: `${name}, ${[building.buildingAddress, building.buildingMunicipality, building.buildingCountrySubdivision].filter(Boolean).join(', ')}`,\r\n address: building.buildingAddress,\r\n municipality: building.buildingMunicipality,\r\n countrySubdivision: building.buildingCountrySubdivision,\r\n postalCode: building.buildingPostalCode,\r\n gid: `building-${building.id}`,\r\n },\r\n geometry: {\r\n type: 'Point',\r\n coordinates: [longitude, latitude],\r\n },\r\n is_database_building: true,\r\n }\r\n}\r\n\r\n// Enhanced marker creation with editing capabilities\r\nexport const createGeocoderMarker = (coordinates: [number, number], map: any, options?: { editing?: boolean }) => {\r\n const editing = options?.editing || false\r\n const markerManager = getGeocoderMarkerManager()\r\n markerManager.create(coordinates, map, { editing })\r\n return markerManager\r\n}\r\n\r\n// Helper function to remove the current marker\r\nexport const removeGeocoderMarker = (): void => {\r\n const markerManager = getGeocoderMarkerManager()\r\n markerManager.remove()\r\n}\r\n"],"mappings":"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","names":["center","addressData"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/core/components/viewers/map/utils/geocoder.ts"],"sourcesContent":["import { Feature, Point } from 'geojson'\r\nimport { MarkerManager } from './MarkerManager'\r\nimport { autocompleteGeocode, reverseGeocode } from './geocoding'\r\n\r\n// Global marker manager instance for geocoder\r\nlet geocoderMarkerManager: MarkerManager | null = null\r\n\r\n// Helper function to get or create the marker manager\r\nconst getGeocoderMarkerManager = (): MarkerManager => {\r\n if (!geocoderMarkerManager) {\r\n geocoderMarkerManager = new MarkerManager()\r\n }\r\n return geocoderMarkerManager\r\n}\r\n\r\n// Convert longitude and latitude into Municipality and Country Subdivision\r\nexport const getMunicipalityAndProvince = async (latitude: string, longitude: string, countryCode?: string) => {\r\n try {\r\n const features = await reverseGeocode(latitude, longitude, countryCode, { size: 1, coarse: true })\r\n\r\n if (features.length > 0) {\r\n const properties = features[0].properties as any\r\n\r\n const municipality = properties.locality || properties.neighbourhood || properties.county || ''\r\n const countrySubdivision = properties.region_a || properties.region || '' // region_a gives abbreviation like \"ON\", \"BC\"\r\n\r\n return { municipality, countrySubdivision }\r\n }\r\n\r\n return { municipality: '', countrySubdivision: '' }\r\n }\r\n catch (error) {\r\n console.error('Error fetching municipality and country subdivision:', error)\r\n return { municipality: '', countrySubdivision: '' }\r\n }\r\n}\r\n\r\n// Fetch address suggestions from the active autocomplete provider\r\nexport const fetchSuggestions = async (input: string, countryCode?: string) => {\r\n if (!input || input.length < 3) {\r\n return []\r\n }\r\n\r\n try {\r\n return await autocompleteGeocode(input, countryCode, 5)\r\n }\r\n catch (error) {\r\n console.error('Error fetching address suggestions:', error)\r\n return []\r\n }\r\n}\r\n\r\n// Parse location details for better display\r\nexport const parseLocation = (feature: Feature) => {\r\n const locationName = feature.properties?.name || ''\r\n const fullLabel = feature.properties?.label || ''\r\n\r\n // Try to extract location details from properties\r\n const properties = feature.properties\r\n let regionDetails = ''\r\n\r\n if (properties) {\r\n const locality = properties.locality\r\n const region = properties.region // Full countrySubdivision name\r\n const region_a = properties.region_a // CountrySubdivision abbreviation (ON, BC, etc.)\r\n const country = properties.country\r\n const country_a = properties.country_a // Country abbreviation (CA)\r\n\r\n // Build region details similar to your original format\r\n if (locality && region_a && country_a) {\r\n regionDetails = `${locality}, ${region_a}, ${country_a}`\r\n }\r\n else if (locality && region && country) {\r\n regionDetails = `${locality}, ${region}, ${country}`\r\n }\r\n else {\r\n // Fallback: try to extract from the full label\r\n const parts = fullLabel.split(', ')\r\n if (parts.length > 1) {\r\n regionDetails = parts.slice(1, 3).join(', ')\r\n }\r\n }\r\n }\r\n\r\n return {\r\n name: locationName,\r\n region: regionDetails,\r\n fullLabel: fullLabel,\r\n }\r\n}\r\n\r\n// Handle suggestion selection and map movement\r\nexport const handleLocationSelect = (feature: Feature, map: any, type: string, options?: { editing?: boolean }) => {\r\n const editing = options?.editing || false\r\n const markerManager = getGeocoderMarkerManager()\r\n\r\n // Handle feature with is_database_building flag\r\n if (type === 'dbBuilding') {\r\n const geometry = feature.geometry as Point\r\n const center = geometry.coordinates\r\n const addressData = {\r\n formatted_address: feature.properties?.label || '',\r\n coordinates: center,\r\n properties: feature.properties,\r\n building_id: feature.properties.gid?.replace('building-', ''),\r\n is_database_building: true,\r\n }\r\n\r\n if (map && center) {\r\n // Add marker to the center with editing capability\r\n // markerManager.create(center as [number, number], map)\r\n\r\n map.flyTo({\r\n center: addressData.coordinates,\r\n zoom: 18,\r\n speed: 1.5,\r\n })\r\n }\r\n\r\n return addressData\r\n }\r\n\r\n // Calculate center coordinates\r\n let center\r\n\r\n // Use bbox if available (more precise for areas)\r\n if (feature.bbox) {\r\n center = [\r\n feature.bbox[0] + (feature.bbox[2] - feature.bbox[0]) / 2,\r\n feature.bbox[1] + (feature.bbox[3] - feature.bbox[1]) / 2,\r\n ]\r\n }\r\n // Otherwise extract coordinates based on geometry type\r\n else if (feature.geometry?.type === 'Point') {\r\n center = (feature.geometry as any).coordinates\r\n }\r\n\r\n const addressData = {\r\n formatted_address: feature.properties?.label || feature.properties?.name || '',\r\n coordinates: center,\r\n properties: feature.properties,\r\n address_details: {\r\n name: feature.properties?.name,\r\n label: feature.properties?.label,\r\n locality: feature.properties?.locality,\r\n neighbourhood: feature.properties?.neighbourhood,\r\n region: feature.properties?.region,\r\n region_a: feature.properties?.region_a,\r\n country: feature.properties?.country,\r\n country_a: feature.properties?.country_a,\r\n postalcode: feature.properties?.postalcode,\r\n housenumber: feature.properties?.housenumber,\r\n street: feature.properties?.street,\r\n },\r\n geocode_earth_id: feature.properties?.gid, // Geocode Earth's unique id\r\n layer: feature.properties?.layer, // Type of place (address, venue, locality, etc.)\r\n confidence: feature.properties?.confidence, // Geocode Earth's confidence score\r\n match_type: feature.properties?.match_type, // How well the result matches the query\r\n }\r\n\r\n if (map && center) {\r\n // Add marker to the center with editing capability\r\n // markerManager.create(center as [number, number], map, { editing })\r\n\r\n if (feature.bbox) {\r\n map.fitBounds(feature.bbox, { speed: 2 })\r\n }\r\n else {\r\n map.flyTo({\r\n center: addressData.coordinates,\r\n zoom: 14, // Might be good idea to set zoom level depending on layer / type of place\r\n speed: 2,\r\n })\r\n }\r\n }\r\n\r\n return addressData\r\n}\r\n\r\n// Util function to get detailed address information\r\nexport const getDetailedAddress = async (coordinates: [number, number], countryCode?: string) => {\r\n const [longitude, latitude] = coordinates\r\n\r\n try {\r\n // Restrict to address-layer results (the original popover used layers=address) so\r\n // callers get a street address rather than the nearest venue/POI. Nominatim's zoom-18\r\n // reverse is already building-level, so this only refines the Pelias path.\r\n const features = await reverseGeocode(latitude.toString(), longitude.toString(), countryCode, { size: 1, layers: 'address' })\r\n return features.length > 0 ? features[0] : null\r\n }\r\n catch (error) {\r\n console.error('Error fetching detailed address:', error)\r\n return null\r\n }\r\n}\r\n\r\n// Convert a building object to a GeoJSON feature format compatible with handleLocationSelect\r\nexport const buildingToFeature = (building) => {\r\n const name = building.buildingName || ''\r\n\r\n // Validate coordinates - use the correct property names\r\n const longitude = Number.parseFloat(building.buildingLongitude)\r\n const latitude = Number.parseFloat(building.buildingLatitude)\r\n\r\n if (isNaN(longitude) || isNaN(latitude)) {\r\n console.error('Invalid building coordinates:', {\r\n longitude: building.buildingLongitude,\r\n latitude: building.buildingLatitude,\r\n buildingId: building.id,\r\n })\r\n return null\r\n }\r\n\r\n return {\r\n properties: {\r\n name: name,\r\n label: `${name}, ${[building.buildingAddress, building.buildingMunicipality, building.buildingCountrySubdivision].filter(Boolean).join(', ')}`,\r\n address: building.buildingAddress,\r\n municipality: building.buildingMunicipality,\r\n countrySubdivision: building.buildingCountrySubdivision,\r\n postalCode: building.buildingPostalCode,\r\n gid: `building-${building.id}`,\r\n },\r\n geometry: {\r\n type: 'Point',\r\n coordinates: [longitude, latitude],\r\n },\r\n is_database_building: true,\r\n }\r\n}\r\n\r\n// // Enhanced marker creation with editing capabilities\r\n// export const createGeocoderMarker = (coordinates: [number, number], map: any, options?: { editing?: boolean }) => {\r\n// const editing = options?.editing || false\r\n// const markerManager = getGeocoderMarkerManager()\r\n// markerManager.create(coordinates, map, { editing })\r\n// return markerManager\r\n// }\r\n\r\n// Helper function to remove the current marker\r\n// export const removeGeocoderMarker = (): void => {\r\n// const markerManager = getGeocoderMarkerManager()\r\n// markerManager.remove()\r\n// }\r\n"],"mappings":"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","names":["center","addressData"]}
|