@object-ui/plugin-map 6.0.3 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/index.umd.cjs +1 -1
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @object-ui/plugin-map
|
|
2
2
|
|
|
3
|
+
## 6.1.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [991b62d]
|
|
8
|
+
- @object-ui/core@6.1.0
|
|
9
|
+
- @object-ui/types@6.1.0
|
|
10
|
+
- @object-ui/components@6.1.0
|
|
11
|
+
- @object-ui/react@6.1.0
|
|
12
|
+
|
|
13
|
+
## 6.0.4
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- @object-ui/types@6.0.4
|
|
18
|
+
- @object-ui/core@6.0.4
|
|
19
|
+
- @object-ui/react@6.0.4
|
|
20
|
+
- @object-ui/components@6.0.4
|
|
21
|
+
|
|
3
22
|
## 6.0.3
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`),require(`@object-ui/core`),require(`@object-ui/react`),require(`@object-ui/components`),require(`zod`),require(`react-map-gl/maplibre`),require(`maplibre-gl/dist/maplibre-gl.css`),require(`react/jsx-runtime`)):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/core`,`@object-ui/react`,`@object-ui/components`,`zod`,`react-map-gl/maplibre`,`maplibre-gl/dist/maplibre-gl.css`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginMap={},e.React,e.ObjectUICore,e.ObjectUIReact,e.ObjectUIComponents,e.zod,e.react_map_gl_maplibre,e.maplibre_gl_dist_maplibre_gl_css,e.react_jsx_runtime))})(this,function(e,t,n,r,i,a,o,s,c){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var l=Object.create,u=Object.defineProperty,d=Object.getOwnPropertyDescriptor,f=Object.getOwnPropertyNames,p=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty,h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=f(t),a=0,o=i.length,s;a<o;a++)s=i[a],!m.call(e,s)&&s!==n&&u(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=d(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:l(p(e)),h(t||!e||!e.__esModule?u(n,`default`,{value:e,enumerable:!0}):n,e));t=g(t,1),o=g(o,1);var _=a.z.object({latitudeField:a.z.string().optional(),longitudeField:a.z.string().optional(),locationField:a.z.string().optional(),titleField:a.z.string().optional(),descriptionField:a.z.string().optional(),zoom:a.z.number().optional(),center:a.z.tuple([a.z.number(),a.z.number()]).optional()});function v(e){return e.data?e.data:e.staticData?{provider:`value`,items:e.staticData}:e.objectName?{provider:`object`,object:e.objectName}:null}function y(e){if(e){if(typeof e==`string`){let t=e.split(` `),n=t[0],r=t[1]?.toLowerCase()===`desc`?`desc`:`asc`;return{[n]:r}}if(Array.isArray(e))return e.reduce((e,t)=>(t.field&&t.order&&(e[t.field]=t.order),e),{})}}function b(e){if(e.locationField||e.latitudeField)return{locationField:e.locationField,latitudeField:e.latitudeField,longitudeField:e.longitudeField,titleField:e.titleField||`name`,descriptionField:e.descriptionField,zoom:e.zoom,center:e.center};let t=null;if(e.filter&&typeof e.filter==`object`&&`map`in e.filter?t=e.filter.map:e.map&&(t=e.map),t){let e=_.safeParse(t);return e.success||console.warn(`[ObjectMap] Invalid map configuration:`,e.error.format()),t}return{latitudeField:`latitude`,longitudeField:`longitude`,locationField:`location`,titleField:`name`,descriptionField:`description`,zoom:10,center:[0,0]}}function x(e,t){if(t.latitudeField&&t.longitudeField){let n=e[t.latitudeField],r=e[t.longitudeField];if(typeof n==`number`&&typeof r==`number`)return[n,r]}if(t.locationField){let n=e[t.locationField];if(typeof n==`object`&&n){let e=n.lat||n.latitude,t=n.lng||n.lon||n.longitude;if(typeof e==`number`&&typeof t==`number`)return[e,t]}if(typeof n==`string`){let e=n.split(`,`).map(e=>parseFloat(e.trim()));if(e.length===2&&!isNaN(e[0])&&!isNaN(e[1]))return[e[0],e[1]]}if(Array.isArray(n)&&n.length===2){let e=parseFloat(n[0]),t=parseFloat(n[1]);if(!isNaN(e)&&!isNaN(t))return[e,t]}}return null}function S(e,t,n=50){if(e.length<=1||t>=15)return e.map(e=>({id:e.id,coordinates:e.coordinates,markers:[e],isCluster:!1}));let r=n/2**t,i=new Map;e.forEach(e=>{let t=`${Math.floor(e.coordinates[0]/r)}:${Math.floor(e.coordinates[1]/r)}`;i.has(t)||i.set(t,[]),i.get(t).push(e)});let a=[];return i.forEach((e,t)=>{if(e.length===1)a.push({id:e[0].id,coordinates:e[0].coordinates,markers:e,isCluster:!1});else{let n=e.reduce((e,t)=>e+t.coordinates[0],0)/e.length,r=e.reduce((e,t)=>e+t.coordinates[1],0)/e.length;a.push({id:`cluster-${t}`,coordinates:[n,r],markers:e,isCluster:!0})}}),a}var C=({schema:e,dataSource:a,className:s,onMarkerClick:l,onRowClick:u,onEdit:d,onDelete:f,enableClustering:p,clusterRadius:m=50,...h})=>{let[g,_]=(0,t.useState)([]),[C,w]=(0,t.useState)(!0),[T,E]=(0,t.useState)(null),[D,O]=(0,t.useState)(null),[k,A]=(0,t.useState)(null),[j,M]=(0,t.useState)(``),N=(0,i.useIsMobile)(),P=(0,t.useRef)(null),[F,I]=(0,t.useState)(null),[L,R]=(0,t.useState)(null),[z,B]=(0,t.useState)(!1),V=(0,t.useCallback)(()=>{if(typeof navigator>`u`||!navigator.geolocation){R(`Geolocation is not available in this browser.`);return}B(!0),R(null),navigator.geolocation.getCurrentPosition(e=>{let{longitude:t,latitude:n}=e.coords;I({lng:t,lat:n}),B(!1);try{P.current?.flyTo({center:[t,n],zoom:12,duration:800})}catch{}},e=>{B(!1),R(e.message||`Unable to retrieve location.`)},{enableHighAccuracy:!1,timeout:8e3,maximumAge:6e4})},[]),H=v(e),U=(0,t.useMemo)(()=>H,[JSON.stringify(H)]),W=b(e),G=U?.provider===`value`;(0,t.useEffect)(()=>{(async()=>{try{if(w(!0),h.data){let e=h.data;if(Array.isArray(e)){_(e),w(!1);return}}if(e.data){let t=e.data;if(Array.isArray(t)){_(t),w(!1);return}}if(G&&U?.provider===`value`){_(U.items),w(!1);return}if(!a||typeof a.find!=`function`)throw Error(`DataSource required for object/api providers`);if(U?.provider===`object`){let t=U.object,r=(0,n.buildExpandFields)(D?.fields);_((0,n.extractRecords)(await a.find(t,{$filter:e.filter,$orderby:y(e.sort),...r.length>0?{$expand:r}:{}})))}else U?.provider===`api`&&(console.warn(`API provider not yet implemented for ObjectMap`),_([]));w(!1)}catch(e){E(e),w(!1)}})()},[U,a,G,e.filter,e.sort,D]),(0,t.useEffect)(()=>{!G&&a&&(async()=>{try{if(!a)return;let t=U?.provider===`object`?U.object:e.objectName;if(!t)return;O(await a.getObjectSchema(t))}catch(e){console.error(`Failed to fetch object schema:`,e)}})()},[e.objectName,a,G,U]);let{markers:K,invalidCount:q}=(0,t.useMemo)(()=>{let e=0;return{markers:g.map((t,n)=>{let r=x(t,W);if(!r)return e++,null;let i=W.titleField?t[W.titleField]:`Marker`,a=W.descriptionField?t[W.descriptionField]:void 0,[o,s]=r;return!isFinite(o)||!isFinite(s)||o<-90||o>90||s<-180||s>180?(e++,null):{id:t.id||t._id||`marker-${n}`,title:i,description:a,coordinates:[s,o],data:t}}).filter(e=>e!==null),invalidCount:e}},[g,W]),J=(0,t.useMemo)(()=>K.find(e=>e.id===k),[K,k]),[Y,X]=(0,t.useState)(W.zoom||3),Z=(0,r.useNavigationOverlay)({navigation:e.navigation,objectName:e.objectName,onRowClick:u}),Q=(0,t.useMemo)(()=>{if(!j.trim())return K;let e=j.toLowerCase();return K.filter(t=>t.title?.toLowerCase().includes(e)||t.description?.toLowerCase().includes(e))},[K,j]),$=(0,t.useMemo)(()=>p??(e.enableClustering||Q.length>100)?S(Q,Y,m):Q.map(e=>({id:e.id,coordinates:e.coordinates,markers:[e],isCluster:!1})),[Q,Y,p,m,e]),ee=(0,t.useMemo)(()=>{if(!Q.length)return{longitude:W.center?.[1]||0,latitude:W.center?.[0]||0,zoom:W.zoom||2};let e=Q.map(e=>e.coordinates[0]),t=Q.map(e=>e.coordinates[1]),n=Math.min(...e),r=Math.max(...e),i=Math.min(...t),a=Math.max(...t);return{longitude:(n+r)/2,latitude:(i+a)/2,zoom:W.zoom||3}},[Q,W]);return C?(0,c.jsx)(`div`,{className:(0,i.cn)(`min-w-0 overflow-hidden`,s),children:(0,c.jsx)(`div`,{className:`flex items-center justify-center h-96 bg-muted rounded-lg border`,children:(0,c.jsx)(`div`,{className:`text-muted-foreground`,children:`Loading map...`})})}):T?(0,c.jsx)(`div`,{className:(0,i.cn)(`min-w-0 overflow-hidden`,s),children:(0,c.jsx)(`div`,{className:`flex items-center justify-center h-96 bg-muted rounded-lg border`,children:(0,c.jsxs)(`div`,{className:`text-destructive`,children:[`Error: `,T.message]})})}):(0,c.jsxs)(`div`,{className:(0,i.cn)(`min-w-0 overflow-hidden`,s),children:[q>0&&(0,c.jsx)(`div`,{className:`mb-2 p-2 text-sm text-yellow-800 bg-yellow-50 border border-yellow-200 rounded`,children:`${q} record${q===1?``:`s`} with missing or invalid coordinates excluded from the map.`}),K.length>0&&(0,c.jsx)(`div`,{className:`mb-2`,children:(0,c.jsx)(`input`,{type:`text`,value:j,onChange:e=>M(e.target.value),placeholder:`Search locations…`,className:`w-full px-3 py-2 text-sm border rounded-md bg-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring`})}),(0,c.jsxs)(`div`,{className:`relative border rounded-lg overflow-hidden bg-muted h-[300px] sm:h-[400px] md:h-[500px] lg:h-[600px] w-full`,children:[(0,c.jsxs)(o.default,{ref:e=>{P.current=e},initialViewState:ee,style:{width:`100%`,height:`100%`},mapStyle:`https://demotiles.maplibre.org/style.json`,touchZoomRotate:!0,dragRotate:!0,touchPitch:!0,onZoom:e=>X(Math.round(e.viewState.zoom)),children:[(0,c.jsx)(o.NavigationControl,{position:`top-right`,showCompass:!0,showZoom:!0}),(0,c.jsx)(`button`,{type:`button`,onClick:V,disabled:z,className:`absolute top-2 left-2 z-10 inline-flex items-center justify-center size-9 rounded-md bg-background/95 border shadow-sm hover:bg-background disabled:opacity-50`,"aria-label":`Show my location`,"data-testid":`map-geolocate`,children:(0,c.jsx)(`span`,{"aria-hidden":`true`,children:z?`⏳`:`🧭`})}),F&&(0,c.jsx)(o.Marker,{longitude:F.lng,latitude:F.lat,anchor:`center`,children:(0,c.jsx)(`div`,{className:`size-3 rounded-full bg-blue-500 ring-4 ring-blue-500/30 shadow`,"aria-label":`Your location`,"data-testid":`map-user-location`})}),$.map(e=>e.isCluster?(0,c.jsx)(o.Marker,{longitude:e.coordinates[0],latitude:e.coordinates[1],anchor:`center`,onClick:t=>{t.originalEvent.stopPropagation();try{let t=Math.min(20,Math.max(Y+2,8));P.current?.flyTo({center:[e.coordinates[0],e.coordinates[1]],zoom:t,duration:600})}catch{}},children:(0,c.jsx)(`div`,{className:`flex items-center justify-center rounded-full bg-primary text-primary-foreground font-bold text-xs cursor-pointer hover:scale-110 transition-transform shadow-md`,style:{width:Math.min(48,24+e.markers.length*2),height:Math.min(48,24+e.markers.length*2)},title:`${e.markers.length} markers`,"data-testid":`map-cluster`,children:e.markers.length})},e.id):(0,c.jsx)(o.Marker,{longitude:e.coordinates[0],latitude:e.coordinates[1],anchor:`bottom`,onClick:t=>{t.originalEvent.stopPropagation();let n=e.markers[0];A(n.id),Z.handleClick(n.data),l?.(n.data)},children:(0,c.jsx)(`div`,{className:`text-2xl cursor-pointer hover:scale-110 transition-transform`,children:`📍`})},e.id)),J&&!N&&(0,c.jsx)(o.Popup,{longitude:J.coordinates[0],latitude:J.coordinates[1],anchor:`top`,onClose:()=>A(null),closeOnClick:!1,children:(0,c.jsxs)(`div`,{className:`p-2 min-w-[150px] sm:min-w-[200px]`,children:[(0,c.jsx)(`h3`,{className:`font-bold text-sm mb-1`,children:J.title}),J.description&&(0,c.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:J.description}),(0,c.jsxs)(`div`,{className:`mt-2 text-xs flex gap-2`,children:[d&&(0,c.jsx)(`button`,{className:`text-blue-500 hover:underline`,onClick:()=>d(J.data),children:`Edit`}),f&&(0,c.jsx)(`button`,{className:`text-red-500 hover:underline`,onClick:()=>f(J.data),children:`Delete`})]})]})})]}),J&&N&&(0,c.jsxs)(`div`,{className:`absolute inset-x-0 bottom-0 z-30 bg-background border-t shadow-lg rounded-t-2xl p-4 pb-[max(env(safe-area-inset-bottom),1rem)]`,role:`dialog`,"aria-label":`Location details`,"data-testid":`map-mobile-record-sheet`,children:[(0,c.jsx)(`div`,{className:`mx-auto mb-2 h-1 w-10 rounded-full bg-muted`,"aria-hidden":`true`}),(0,c.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,c.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,c.jsx)(`h3`,{className:`text-sm font-semibold truncate`,children:J.title}),J.description&&(0,c.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground line-clamp-3`,children:J.description})]}),(0,c.jsx)(`button`,{type:`button`,onClick:()=>A(null),className:`text-muted-foreground hover:text-foreground text-lg leading-none px-2`,"aria-label":`Close details`,"data-testid":`map-mobile-record-close`,children:`×`})]}),(0,c.jsxs)(`div`,{className:`mt-3 flex flex-wrap gap-2 text-xs`,children:[d&&(0,c.jsx)(`button`,{className:`px-3 py-1.5 rounded-md border bg-card hover:bg-accent`,onClick:()=>d(J.data),children:`Edit`}),f&&(0,c.jsx)(`button`,{className:`px-3 py-1.5 rounded-md border border-destructive/30 text-destructive hover:bg-destructive/10`,onClick:()=>f(J.data),children:`Delete`})]})]}),L&&(0,c.jsx)(`div`,{className:`absolute top-2 left-14 right-2 z-10 text-xs px-3 py-1.5 rounded-md bg-destructive/10 text-destructive border border-destructive/30`,children:L})]}),Z.isOverlay&&(0,c.jsx)(i.NavigationOverlay,{...Z,title:`Location Details`,children:e=>(0,c.jsx)(`div`,{className:`space-y-3`,children:Object.entries(e).map(([e,t])=>(0,c.jsxs)(`div`,{className:`flex flex-col`,children:[(0,c.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground uppercase tracking-wide`,children:e.replace(/_/g,` `)}),(0,c.jsx)(`span`,{className:`text-sm`,children:String(t??`—`)})]},e))})})]})},w=({schema:e,...t})=>{let{dataSource:n}=(0,r.useSchemaContext)()||{};return(0,c.jsx)(C,{schema:e,dataSource:n,...t})};console.log(`Registering object-map...`),n.ComponentRegistry.register(`object-map`,w,{namespace:`plugin-map`,label:`Object Map`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`map`,type:`object`,label:`Map Config`,description:`latitudeField, longitudeField, titleField`}]}),n.ComponentRegistry.register(`map`,w,{namespace:`view`,label:`Map View`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`map`,type:`object`,label:`Map Config`,description:`latitudeField, longitudeField, titleField`}]}),e.ObjectMap=C,e.ObjectMapRenderer=w});
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react"),require("@object-ui/core"),require("@object-ui/react"),require("@object-ui/components"),require("zod"),require("react-map-gl/maplibre"),require("maplibre-gl/dist/maplibre-gl.css"),require("react/jsx-runtime")):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/core`,`@object-ui/react`,`@object-ui/components`,`zod`,`react-map-gl/maplibre`,`maplibre-gl/dist/maplibre-gl.css`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginMap={},e.React,e.ObjectUICore,e.ObjectUIReact,e.ObjectUIComponents,e.zod,e.react_map_gl_maplibre,e.maplibre_gl_dist_maplibre_gl_css,e.react_jsx_runtime))})(this,function(e,t,n,r,i,a,o,s,c){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var l=Object.create,u=Object.defineProperty,d=Object.getOwnPropertyDescriptor,f=Object.getOwnPropertyNames,p=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty,h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=f(t),a=0,o=i.length,s;a<o;a++)s=i[a],!m.call(e,s)&&s!==n&&u(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=d(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:l(p(e)),h(t||!e||!e.__esModule?u(n,`default`,{value:e,enumerable:!0}):n,e));t=g(t,1),o=g(o,1);var _=a.z.object({latitudeField:a.z.string().optional(),longitudeField:a.z.string().optional(),locationField:a.z.string().optional(),titleField:a.z.string().optional(),descriptionField:a.z.string().optional(),zoom:a.z.number().optional(),center:a.z.tuple([a.z.number(),a.z.number()]).optional()});function v(e){return e.data?e.data:e.staticData?{provider:`value`,items:e.staticData}:e.objectName?{provider:`object`,object:e.objectName}:null}function y(e){if(e){if(typeof e==`string`){let t=e.split(` `),n=t[0],r=t[1]?.toLowerCase()===`desc`?`desc`:`asc`;return{[n]:r}}if(Array.isArray(e))return e.reduce((e,t)=>(t.field&&t.order&&(e[t.field]=t.order),e),{})}}function b(e){if(e.locationField||e.latitudeField)return{locationField:e.locationField,latitudeField:e.latitudeField,longitudeField:e.longitudeField,titleField:e.titleField||`name`,descriptionField:e.descriptionField,zoom:e.zoom,center:e.center};let t=null;if(e.filter&&typeof e.filter==`object`&&`map`in e.filter?t=e.filter.map:e.map&&(t=e.map),t){let e=_.safeParse(t);return e.success||console.warn(`[ObjectMap] Invalid map configuration:`,e.error.format()),t}return{latitudeField:`latitude`,longitudeField:`longitude`,locationField:`location`,titleField:`name`,descriptionField:`description`,zoom:10,center:[0,0]}}function x(e,t){if(t.latitudeField&&t.longitudeField){let n=e[t.latitudeField],r=e[t.longitudeField];if(typeof n==`number`&&typeof r==`number`)return[n,r]}if(t.locationField){let n=e[t.locationField];if(typeof n==`object`&&n){let e=n.lat||n.latitude,t=n.lng||n.lon||n.longitude;if(typeof e==`number`&&typeof t==`number`)return[e,t]}if(typeof n==`string`){let e=n.split(`,`).map(e=>parseFloat(e.trim()));if(e.length===2&&!isNaN(e[0])&&!isNaN(e[1]))return[e[0],e[1]]}if(Array.isArray(n)&&n.length===2){let e=parseFloat(n[0]),t=parseFloat(n[1]);if(!isNaN(e)&&!isNaN(t))return[e,t]}}return null}function S(e,t,n=50){if(e.length<=1||t>=15)return e.map(e=>({id:e.id,coordinates:e.coordinates,markers:[e],isCluster:!1}));let r=n/2**t,i=new Map;e.forEach(e=>{let t=`${Math.floor(e.coordinates[0]/r)}:${Math.floor(e.coordinates[1]/r)}`;i.has(t)||i.set(t,[]),i.get(t).push(e)});let a=[];return i.forEach((e,t)=>{if(e.length===1)a.push({id:e[0].id,coordinates:e[0].coordinates,markers:e,isCluster:!1});else{let n=e.reduce((e,t)=>e+t.coordinates[0],0)/e.length,r=e.reduce((e,t)=>e+t.coordinates[1],0)/e.length;a.push({id:`cluster-${t}`,coordinates:[n,r],markers:e,isCluster:!0})}}),a}var C=({schema:e,dataSource:a,className:s,onMarkerClick:l,onRowClick:u,onEdit:d,onDelete:f,enableClustering:p,clusterRadius:m=50,...h})=>{let[g,_]=(0,t.useState)([]),[C,w]=(0,t.useState)(!0),[T,E]=(0,t.useState)(null),[D,O]=(0,t.useState)(null),[k,A]=(0,t.useState)(null),[j,M]=(0,t.useState)(``),N=(0,i.useIsMobile)(),P=(0,t.useRef)(null),[F,I]=(0,t.useState)(null),[L,R]=(0,t.useState)(null),[z,B]=(0,t.useState)(!1),V=(0,t.useCallback)(()=>{if(typeof navigator>`u`||!navigator.geolocation){R(`Geolocation is not available in this browser.`);return}B(!0),R(null),navigator.geolocation.getCurrentPosition(e=>{let{longitude:t,latitude:n}=e.coords;I({lng:t,lat:n}),B(!1);try{P.current?.flyTo({center:[t,n],zoom:12,duration:800})}catch{}},e=>{B(!1),R(e.message||`Unable to retrieve location.`)},{enableHighAccuracy:!1,timeout:8e3,maximumAge:6e4})},[]),H=v(e),U=(0,t.useMemo)(()=>H,[JSON.stringify(H)]),W=b(e),G=U?.provider===`value`;(0,t.useEffect)(()=>{(async()=>{try{if(w(!0),h.data){let e=h.data;if(Array.isArray(e)){_(e),w(!1);return}}if(e.data){let t=e.data;if(Array.isArray(t)){_(t),w(!1);return}}if(G&&U?.provider===`value`){_(U.items),w(!1);return}if(!a||typeof a.find!=`function`)throw Error(`DataSource required for object/api providers`);if(U?.provider===`object`){let t=U.object,r=(0,n.buildExpandFields)(D?.fields);_((0,n.extractRecords)(await a.find(t,{$filter:e.filter,$orderby:y(e.sort),...r.length>0?{$expand:r}:{}})))}else U?.provider===`api`&&(console.warn(`API provider not yet implemented for ObjectMap`),_([]));w(!1)}catch(e){E(e),w(!1)}})()},[U,a,G,e.filter,e.sort,D]),(0,t.useEffect)(()=>{!G&&a&&(async()=>{try{if(!a)return;let t=U?.provider===`object`?U.object:e.objectName;if(!t)return;O(await a.getObjectSchema(t))}catch(e){console.error(`Failed to fetch object schema:`,e)}})()},[e.objectName,a,G,U]);let{markers:K,invalidCount:q}=(0,t.useMemo)(()=>{let e=0;return{markers:g.map((t,n)=>{let r=x(t,W);if(!r)return e++,null;let i=W.titleField?t[W.titleField]:`Marker`,a=W.descriptionField?t[W.descriptionField]:void 0,[o,s]=r;return!isFinite(o)||!isFinite(s)||o<-90||o>90||s<-180||s>180?(e++,null):{id:t.id||t._id||`marker-${n}`,title:i,description:a,coordinates:[s,o],data:t}}).filter(e=>e!==null),invalidCount:e}},[g,W]),J=(0,t.useMemo)(()=>K.find(e=>e.id===k),[K,k]),[Y,X]=(0,t.useState)(W.zoom||3),Z=(0,r.useNavigationOverlay)({navigation:e.navigation,objectName:e.objectName,onRowClick:u}),Q=(0,t.useMemo)(()=>{if(!j.trim())return K;let e=j.toLowerCase();return K.filter(t=>t.title?.toLowerCase().includes(e)||t.description?.toLowerCase().includes(e))},[K,j]),$=(0,t.useMemo)(()=>p??(e.enableClustering||Q.length>100)?S(Q,Y,m):Q.map(e=>({id:e.id,coordinates:e.coordinates,markers:[e],isCluster:!1})),[Q,Y,p,m,e]),ee=(0,t.useMemo)(()=>{if(!Q.length)return{longitude:W.center?.[1]||0,latitude:W.center?.[0]||0,zoom:W.zoom||2};let e=Q.map(e=>e.coordinates[0]),t=Q.map(e=>e.coordinates[1]),n=Math.min(...e),r=Math.max(...e),i=Math.min(...t),a=Math.max(...t);return{longitude:(n+r)/2,latitude:(i+a)/2,zoom:W.zoom||3}},[Q,W]);return C?(0,c.jsx)(`div`,{className:(0,i.cn)(`min-w-0 overflow-hidden`,s),children:(0,c.jsx)(`div`,{className:`flex items-center justify-center h-96 bg-muted rounded-lg border`,children:(0,c.jsx)(`div`,{className:`text-muted-foreground`,children:`Loading map...`})})}):T?(0,c.jsx)(`div`,{className:(0,i.cn)(`min-w-0 overflow-hidden`,s),children:(0,c.jsx)(`div`,{className:`flex items-center justify-center h-96 bg-muted rounded-lg border`,children:(0,c.jsxs)(`div`,{className:`text-destructive`,children:[`Error: `,T.message]})})}):(0,c.jsxs)(`div`,{className:(0,i.cn)(`min-w-0 overflow-hidden`,s),children:[q>0&&(0,c.jsx)(`div`,{className:`mb-2 p-2 text-sm text-yellow-800 bg-yellow-50 border border-yellow-200 rounded`,children:`${q} record${q===1?``:`s`} with missing or invalid coordinates excluded from the map.`}),K.length>0&&(0,c.jsx)(`div`,{className:`mb-2`,children:(0,c.jsx)(`input`,{type:`text`,value:j,onChange:e=>M(e.target.value),placeholder:`Search locations…`,className:`w-full px-3 py-2 text-sm border rounded-md bg-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring`})}),(0,c.jsxs)(`div`,{className:`relative border rounded-lg overflow-hidden bg-muted h-[300px] sm:h-[400px] md:h-[500px] lg:h-[600px] w-full`,children:[(0,c.jsxs)(o.default,{ref:e=>{P.current=e},initialViewState:ee,style:{width:`100%`,height:`100%`},mapStyle:`https://demotiles.maplibre.org/style.json`,touchZoomRotate:!0,dragRotate:!0,touchPitch:!0,onZoom:e=>X(Math.round(e.viewState.zoom)),children:[(0,c.jsx)(o.NavigationControl,{position:`top-right`,showCompass:!0,showZoom:!0}),(0,c.jsx)(`button`,{type:`button`,onClick:V,disabled:z,className:`absolute top-2 left-2 z-10 inline-flex items-center justify-center size-9 rounded-md bg-background/95 border shadow-sm hover:bg-background disabled:opacity-50`,"aria-label":`Show my location`,"data-testid":`map-geolocate`,children:(0,c.jsx)(`span`,{"aria-hidden":`true`,children:z?`⏳`:`🧭`})}),F&&(0,c.jsx)(o.Marker,{longitude:F.lng,latitude:F.lat,anchor:`center`,children:(0,c.jsx)(`div`,{className:`size-3 rounded-full bg-blue-500 ring-4 ring-blue-500/30 shadow`,"aria-label":`Your location`,"data-testid":`map-user-location`})}),$.map(e=>e.isCluster?(0,c.jsx)(o.Marker,{longitude:e.coordinates[0],latitude:e.coordinates[1],anchor:`center`,onClick:t=>{t.originalEvent.stopPropagation();try{let t=Math.min(20,Math.max(Y+2,8));P.current?.flyTo({center:[e.coordinates[0],e.coordinates[1]],zoom:t,duration:600})}catch{}},children:(0,c.jsx)(`div`,{className:`flex items-center justify-center rounded-full bg-primary text-primary-foreground font-bold text-xs cursor-pointer hover:scale-110 transition-transform shadow-md`,style:{width:Math.min(48,24+e.markers.length*2),height:Math.min(48,24+e.markers.length*2)},title:`${e.markers.length} markers`,"data-testid":`map-cluster`,children:e.markers.length})},e.id):(0,c.jsx)(o.Marker,{longitude:e.coordinates[0],latitude:e.coordinates[1],anchor:`bottom`,onClick:t=>{t.originalEvent.stopPropagation();let n=e.markers[0];A(n.id),Z.handleClick(n.data),l?.(n.data)},children:(0,c.jsx)(`div`,{className:`text-2xl cursor-pointer hover:scale-110 transition-transform`,children:`📍`})},e.id)),J&&!N&&(0,c.jsx)(o.Popup,{longitude:J.coordinates[0],latitude:J.coordinates[1],anchor:`top`,onClose:()=>A(null),closeOnClick:!1,children:(0,c.jsxs)(`div`,{className:`p-2 min-w-[150px] sm:min-w-[200px]`,children:[(0,c.jsx)(`h3`,{className:`font-bold text-sm mb-1`,children:J.title}),J.description&&(0,c.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:J.description}),(0,c.jsxs)(`div`,{className:`mt-2 text-xs flex gap-2`,children:[d&&(0,c.jsx)(`button`,{className:`text-blue-500 hover:underline`,onClick:()=>d(J.data),children:`Edit`}),f&&(0,c.jsx)(`button`,{className:`text-red-500 hover:underline`,onClick:()=>f(J.data),children:`Delete`})]})]})})]}),J&&N&&(0,c.jsxs)(`div`,{className:`absolute inset-x-0 bottom-0 z-30 bg-background border-t shadow-lg rounded-t-2xl p-4 pb-[max(env(safe-area-inset-bottom),1rem)]`,role:`dialog`,"aria-label":`Location details`,"data-testid":`map-mobile-record-sheet`,children:[(0,c.jsx)(`div`,{className:`mx-auto mb-2 h-1 w-10 rounded-full bg-muted`,"aria-hidden":`true`}),(0,c.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,c.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,c.jsx)(`h3`,{className:`text-sm font-semibold truncate`,children:J.title}),J.description&&(0,c.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground line-clamp-3`,children:J.description})]}),(0,c.jsx)(`button`,{type:`button`,onClick:()=>A(null),className:`text-muted-foreground hover:text-foreground text-lg leading-none px-2`,"aria-label":`Close details`,"data-testid":`map-mobile-record-close`,children:`×`})]}),(0,c.jsxs)(`div`,{className:`mt-3 flex flex-wrap gap-2 text-xs`,children:[d&&(0,c.jsx)(`button`,{className:`px-3 py-1.5 rounded-md border bg-card hover:bg-accent`,onClick:()=>d(J.data),children:`Edit`}),f&&(0,c.jsx)(`button`,{className:`px-3 py-1.5 rounded-md border border-destructive/30 text-destructive hover:bg-destructive/10`,onClick:()=>f(J.data),children:`Delete`})]})]}),L&&(0,c.jsx)(`div`,{className:`absolute top-2 left-14 right-2 z-10 text-xs px-3 py-1.5 rounded-md bg-destructive/10 text-destructive border border-destructive/30`,children:L})]}),Z.isOverlay&&(0,c.jsx)(i.NavigationOverlay,{...Z,title:`Location Details`,children:e=>(0,c.jsx)(`div`,{className:`space-y-3`,children:Object.entries(e).map(([e,t])=>(0,c.jsxs)(`div`,{className:`flex flex-col`,children:[(0,c.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground uppercase tracking-wide`,children:e.replace(/_/g,` `)}),(0,c.jsx)(`span`,{className:`text-sm`,children:String(t??`—`)})]},e))})})]})},w=({schema:e,...t})=>{let{dataSource:n}=(0,r.useSchemaContext)()||{};return(0,c.jsx)(C,{schema:e,dataSource:n,...t})};console.log(`Registering object-map...`),n.ComponentRegistry.register(`object-map`,w,{namespace:`plugin-map`,label:`Object Map`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`map`,type:`object`,label:`Map Config`,description:`latitudeField, longitudeField, titleField`}]}),n.ComponentRegistry.register(`map`,w,{namespace:`view`,label:`Map View`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`map`,type:`object`,label:`Map Config`,description:`latitudeField, longitudeField, titleField`}]}),e.ObjectMap=C,e.ObjectMapRenderer=w});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/plugin-map",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Map visualization plugin for Object UI",
|
|
@@ -29,22 +29,22 @@
|
|
|
29
29
|
"maplibre-gl": "^5.24.0",
|
|
30
30
|
"react-map-gl": "^8.1.1",
|
|
31
31
|
"zod": "^4.4.3",
|
|
32
|
-
"@object-ui/components": "6.0
|
|
33
|
-
"@object-ui/core": "6.0
|
|
34
|
-
"@object-ui/react": "6.0
|
|
35
|
-
"@object-ui/types": "6.0
|
|
32
|
+
"@object-ui/components": "6.1.0",
|
|
33
|
+
"@object-ui/core": "6.1.0",
|
|
34
|
+
"@object-ui/react": "6.1.0",
|
|
35
|
+
"@object-ui/types": "6.1.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"react": "^18.0.0 || ^19.0.0",
|
|
39
39
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@types/react": "19.2.
|
|
42
|
+
"@types/react": "19.2.15",
|
|
43
43
|
"@types/react-dom": "19.2.3",
|
|
44
44
|
"@vitejs/plugin-react": "^6.0.2",
|
|
45
45
|
"typescript": "^6.0.3",
|
|
46
|
-
"vite": "^8.0.
|
|
47
|
-
"vite-plugin-dts": "^5.0.
|
|
46
|
+
"vite": "^8.0.14",
|
|
47
|
+
"vite-plugin-dts": "^5.0.1"
|
|
48
48
|
},
|
|
49
49
|
"keywords": [
|
|
50
50
|
"objectui",
|