@collabdt/core 0.0.43 → 0.0.44

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.
@@ -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;AA2BzB,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
+ {"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;AAI3C,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
+ {"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// import * as FRAGS from '@thatopen/fragments'\r\n// import * as THREE from 'three'\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;AAId,MAAM,iBAAN,MAAM,uBAAsB,IAAI,UAAU;AAAA,EAyB7C,YAAY,YAA4B;AA9B5C;AA+BQ,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
+ {"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;AAI9B,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
+ {"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// import * as WEBIFC from 'web-ifc'\r\n// import * as BIM from '..'\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;AAWtB,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
+ {"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;AAcrD,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,EAAG,EAAE,KAAK,qBAkJlF"}
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, _c, _d, _e, _f, _g, _h, _i, _j;
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: (_c = organization.pitch) != null ? _c : 0,
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, _c, _d, _e, _f, _g, _h;
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")) : (_c = organization.bearing) != null ? _c : 0,
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 = (_a = mapState == null ? void 0 : mapState.map.mapStyle) != null ? _a : DEFAULT_MAP_STYLE;
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: (_b = organization == null ? void 0 : organization.minZoom) != null ? _b : CANADA_DEFAULTS.zoom,
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: "globe",
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;AAa9B,wBAAgB,UAAU,sBA2BzB"}
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// import { DatasetsTab } from './src/DatasetsTab'\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":";AA0BI,SAEI,KAFJ;AAzBJ,YAAY,WAAW;AACvB,SAAS,mBAAmB;AAC5B,SAAS,cAAc,sBAAsB;AAE7C,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAG1B,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"]}
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"]}
@@ -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;AAQ9B,wBAAgB,aAAa,sBAuD5B"}
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"}
@@ -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.useEffect(() => {
24
- if (!map || !map.loaded()) return;
24
+ const syncProjectionDisplay = React.useCallback(() => {
25
+ if (!map) return;
25
26
  setMapProjection(getCurrentProjection());
26
- }, [map, getCurrentProjection]);
27
- const handleMapProjection = () => {
27
+ }, [getCurrentProjection, map]);
28
+ React.useEffect(() => {
28
29
  if (!map) return;
29
- const currentProjection = getCurrentProjection();
30
- const nextProjection = currentProjection !== "globe" ? "globe" : "mercator";
31
- map.setProjection({ type: nextProjection });
32
- setMapProjection(nextProjection);
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")
@@ -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.useEffect(() => {\r\n if (!map || !map.loaded()) return\r\n\r\n setMapProjection(getCurrentProjection())\r\n }, [map, getCurrentProjection])\r\n\r\n const handleMapProjection = () => {\r\n if (!map) return\r\n\r\n const currentProjection = getCurrentProjection()\r\n const nextProjection = currentProjection !== 'globe' ? 'globe' : 'mercator'\r\n\r\n map.setProjection({ type: nextProjection })\r\n setMapProjection(nextProjection)\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={handleMapProjection} 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":";AAkDM,cAGI,YAHJ;AAhDN,YAAY,WAAW;AACvB,SAAS,uBAAuB;AAChC,YAAY,QAAQ;AACpB,SAAS,MAAM,UAAU,mBAAmB;AAC5C,SAAS,kBAAkB;AAIpB,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;AAhB1E;AAiBI,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;AAER,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,OAAO,CAAC,IAAI,OAAO,EAAG;AAE3B,qBAAiB,qBAAqB,CAAC;AAAA,EACzC,GAAG,CAAC,KAAK,oBAAoB,CAAC;AAE9B,QAAM,sBAAsB,MAAM;AAChC,QAAI,CAAC,IAAK;AAEV,UAAM,oBAAoB,qBAAqB;AAC/C,UAAM,iBAAiB,sBAAsB,UAAU,UAAU;AAEjE,QAAI,cAAc,EAAE,MAAM,eAAe,CAAC;AAC1C,qBAAiB,cAAc;AAAA,EACjC;AAEA,SACE,qBAAC,SAAI,WAAU,aACb;AAAA,wBAAC,WAAM,WAAU,uBAAuB,eAAK,eAAe,GAAE;AAAA,IAC9D,oBAAC,QAAK,OAAO,eAAe,eAAe,qBAAqB,SAAQ,UACtE,+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
+ {"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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@collabdt/core",
3
- "version": "0.0.43",
3
+ "version": "0.0.44",
4
4
  "description": "CDT Core contains all the core technology for your CDT platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",