utopia-ui 3.0.90 → 3.0.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -7,7 +7,7 @@ import { DomEvent, divIcon, Point, control, marker, LatLng, LatLngBounds } from
7
7
  import { useMap, useMapEvents, TileLayer, GeoJSON, MapContainer, Popup, Marker, Tooltip } from 'react-leaflet';
8
8
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
9
9
  import * as React from 'react';
10
- import { createContext, useContext, useState, useCallback, useReducer, useEffect, createRef, useRef, memo, Children, cloneElement, isValidElement, forwardRef } from 'react';
10
+ import { createContext, useContext, useState, useCallback, useReducer, useEffect, createRef, useRef, memo, cloneElement, forwardRef, useMemo } from 'react';
11
11
  import { useNavigate, useInRouterContext, BrowserRouter, useLocation, Outlet, Link, NavLink } from 'react-router-dom';
12
12
  import { toast, ToastContainer } from 'react-toastify';
13
13
  import MarkerClusterGroup from 'react-leaflet-cluster';
@@ -120,7 +120,7 @@ const useSetClusterRef = () => {
120
120
  return setClusterRef;
121
121
  };
122
122
 
123
- const LayerContext = createContext({
123
+ const LayerContext$1 = createContext({
124
124
  layers: [],
125
125
  // eslint-disable-next-line @typescript-eslint/no-empty-function
126
126
  addLayer: () => { },
@@ -148,13 +148,13 @@ function useLayerManager(initialLayers) {
148
148
  }, []);
149
149
  return { layers, addLayer };
150
150
  }
151
- const LayersProvider = ({ initialLayers, children }) => (jsx(LayerContext.Provider, { value: useLayerManager(initialLayers), children: children }));
151
+ const LayersProvider = ({ initialLayers, children }) => (jsx(LayerContext$1.Provider, { value: useLayerManager(initialLayers), children: children }));
152
152
  const useLayers = () => {
153
- const { layers } = useContext(LayerContext);
153
+ const { layers } = useContext(LayerContext$1);
154
154
  return layers;
155
155
  };
156
156
  const useAddLayer = () => {
157
- const { addLayer } = useContext(LayerContext);
157
+ const { addLayer } = useContext(LayerContext$1);
158
158
  return addLayer;
159
159
  };
160
160
 
@@ -409,7 +409,7 @@ const useVisibleGroupType = () => {
409
409
  return visibleGroupTypes;
410
410
  };
411
411
 
412
- const ItemContext = createContext({
412
+ const ItemContext$1 = createContext({
413
413
  items: [],
414
414
  addItem: () => { },
415
415
  updateItem: () => { },
@@ -509,33 +509,33 @@ function useItemsManager(initialItems) {
509
509
  allItemsLoaded,
510
510
  };
511
511
  }
512
- const ItemsProvider = ({ initialItems, children }) => (jsx(ItemContext.Provider, { value: useItemsManager(initialItems), children: children }));
512
+ const ItemsProvider = ({ initialItems, children }) => (jsx(ItemContext$1.Provider, { value: useItemsManager(initialItems), children: children }));
513
513
  const useItems = () => {
514
- const { items } = useContext(ItemContext);
514
+ const { items } = useContext(ItemContext$1);
515
515
  return items;
516
516
  };
517
517
  const useAddItem = () => {
518
- const { addItem } = useContext(ItemContext);
518
+ const { addItem } = useContext(ItemContext$1);
519
519
  return addItem;
520
520
  };
521
521
  const useUpdateItem = () => {
522
- const { updateItem } = useContext(ItemContext);
522
+ const { updateItem } = useContext(ItemContext$1);
523
523
  return updateItem;
524
524
  };
525
525
  const useRemoveItem = () => {
526
- const { removeItem } = useContext(ItemContext);
526
+ const { removeItem } = useContext(ItemContext$1);
527
527
  return removeItem;
528
528
  };
529
529
  const useSetItemsApi = () => {
530
- const { setItemsApi } = useContext(ItemContext);
530
+ const { setItemsApi } = useContext(ItemContext$1);
531
531
  return setItemsApi;
532
532
  };
533
533
  const useSetItemsData = () => {
534
- const { setItemsData } = useContext(ItemContext);
534
+ const { setItemsData } = useContext(ItemContext$1);
535
535
  return setItemsData;
536
536
  };
537
537
  const useAllItemsLoaded = () => {
538
- const { allItemsLoaded } = useContext(ItemContext);
538
+ const { allItemsLoaded } = useContext(ItemContext$1);
539
539
  return allItemsLoaded;
540
540
  };
541
541
 
@@ -819,6 +819,22 @@ const useSetAdminRole = () => {
819
819
  return setAdminRole;
820
820
  };
821
821
 
822
+ const PoupFormContext = createContext({
823
+ popupForm: {},
824
+ setPopupForm: () => {
825
+ /* empty function */
826
+ },
827
+ });
828
+ function usePopupFormManager() {
829
+ const [popupForm, setPopupForm] = useState(null);
830
+ return { popupForm, setPopupForm };
831
+ }
832
+ const PopupFormProvider = ({ children }) => (jsx(PoupFormContext.Provider, { value: usePopupFormManager(), children: children }));
833
+ const usePopupForm = () => {
834
+ const { popupForm, setPopupForm } = useContext(PoupFormContext);
835
+ return { popupForm, setPopupForm };
836
+ };
837
+
822
838
  const SelectPositionContext = createContext({
823
839
  selectPosition: null,
824
840
  setSelectPosition: () => { },
@@ -842,7 +858,9 @@ function useSelectPositionManager() {
842
858
  }, [markerClicked]);
843
859
  useEffect(() => {
844
860
  if (selectPosition != null) {
861
+ // selectPosition can be null, Layer or Item
845
862
  if ('menuIcon' in selectPosition) {
863
+ // if selectPosition is a Layer
846
864
  mapClicked &&
847
865
  mapClicked.setItemFormPopup({
848
866
  layer: selectPosition,
@@ -851,6 +869,7 @@ function useSelectPositionManager() {
851
869
  setSelectPosition(null);
852
870
  }
853
871
  if ('text' in selectPosition) {
872
+ // if selectPosition is an Item
854
873
  const position = mapClicked?.position.lng &&
855
874
  {
856
875
  type: 'Point',
@@ -1115,7 +1134,7 @@ const ContextWrapper = ({ children }) => {
1115
1134
  // eslint-disable-next-line react/prop-types
1116
1135
  const Wrappers = ({ children }) => {
1117
1136
  const queryClient = new QueryClient();
1118
- return (jsx(PermissionsProvider, { initialPermissions: [], children: jsx(TagsProvider, { initialTags: [], children: jsx(LayersProvider, { initialLayers: [], children: jsx(FilterProvider, { initialTags: [], children: jsx(ItemsProvider, { initialItems: [], children: jsx(SelectPositionProvider, { children: jsx(LeafletRefsProvider, { initialLeafletRefs: {}, children: jsx(QueryClientProvider, { client: queryClient, children: jsx(AppStateProvider, { children: jsx(ClusterRefProvider, { children: jsxs(QuestsProvider, { initialOpen: true, children: [jsx(ToastContainer, { position: 'top-right', autoClose: 2000, hideProgressBar: true, newestOnTop: false, closeOnClick: true, rtl: false, pauseOnFocusLoss: true, draggable: true, pauseOnHover: true, theme: 'light', closeButton: CloseButton }), children] }) }) }) }) }) }) }) }) }) }) }));
1137
+ return (jsx(PermissionsProvider, { initialPermissions: [], children: jsx(TagsProvider, { initialTags: [], children: jsx(LayersProvider, { initialLayers: [], children: jsx(FilterProvider, { initialTags: [], children: jsx(ItemsProvider, { initialItems: [], children: jsx(SelectPositionProvider, { children: jsx(LeafletRefsProvider, { initialLeafletRefs: {}, children: jsx(QueryClientProvider, { client: queryClient, children: jsx(AppStateProvider, { children: jsx(ClusterRefProvider, { children: jsx(PopupFormProvider, { children: jsxs(QuestsProvider, { initialOpen: true, children: [jsx(ToastContainer, { position: 'top-right', autoClose: 2000, hideProgressBar: true, newestOnTop: false, closeOnClick: true, rtl: false, pauseOnFocusLoss: true, draggable: true, pauseOnHover: true, theme: 'light', closeButton: CloseButton }), children] }) }) }) }) }) }) }) }) }) }) }) }));
1119
1138
  };
1120
1139
 
1121
1140
  const useTheme = (defaultTheme = 'default') => {
@@ -2584,7 +2603,7 @@ function fixUrls(message) {
2584
2603
  /**
2585
2604
  * @category Map
2586
2605
  */
2587
- const TextView = ({ item, itemId, text, truncate = false, rawText, itemTextField, }) => {
2606
+ const TextView$1 = ({ item, itemId, text, truncate = false, rawText, itemTextField, }) => {
2588
2607
  if (item) {
2589
2608
  text = item.text;
2590
2609
  itemId = item.id;
@@ -2660,8 +2679,6 @@ const TextView = ({ item, itemId, text, truncate = false, rawText, itemTextField
2660
2679
  return jsx(MemoizedVideoEmbed, { url: href });
2661
2680
  }
2662
2681
  if (href?.startsWith('#')) {
2663
- console.log(href.slice(1).toLowerCase());
2664
- console.log(tags);
2665
2682
  const tag = tags.find((t) => t.name.toLowerCase() === decodeURI(href).slice(1).toLowerCase());
2666
2683
  if (tag)
2667
2684
  return (jsx(CustomHashTagLink, { tag: tag, itemId: itemId, children: children }));
@@ -2729,13 +2746,13 @@ function UtopiaMapInner({ children, geo, showFilterControl = false, showGratitud
2729
2746
  const setClusterRef = useSetClusterRef();
2730
2747
  const clusterRef = useClusterRef();
2731
2748
  const setMapClicked = useSetMapClicked();
2732
- const [itemFormPopup, setItemFormPopup] = useState(null);
2733
- useTheme(defaultTheme);
2749
+ const { setPopupForm } = usePopupForm();
2734
2750
  const layers = useLayers();
2735
2751
  const addVisibleLayer = useAddVisibleLayer();
2736
2752
  const leafletRefs = useLeafletRefs();
2737
2753
  const location = useLocation();
2738
2754
  const map = useMap();
2755
+ useTheme(defaultTheme);
2739
2756
  useEffect(() => {
2740
2757
  layers.forEach((layer) => addVisibleLayer(layer));
2741
2758
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -2749,7 +2766,7 @@ function UtopiaMapInner({ children, geo, showFilterControl = false, showGratitud
2749
2766
  if (!init.current) {
2750
2767
  donationWidget &&
2751
2768
  setTimeout(() => {
2752
- toast(jsxs(Fragment, { children: [jsx(TextView, { itemId: '', rawText: '## Do you like this Map?' }), jsxs("div", { children: [jsx(TextView, { itemId: '', rawText: 'Support us building free opensource maps for communities and help us grow 🌱☀️' }), jsx("a", { href: 'https://opencollective.com/utopia-project', children: jsx("div", { className: 'tw:btn tw:btn-sm tw:float-right tw:btn-primary', children: "Donate" }) })] })] }), { autoClose: false });
2769
+ toast(jsxs(Fragment, { children: [jsx(TextView$1, { itemId: '', rawText: '## Do you like this Map?' }), jsxs("div", { children: [jsx(TextView$1, { itemId: '', rawText: 'Support us building free opensource maps for communities and help us grow 🌱☀️' }), jsx("a", { href: 'https://opencollective.com/utopia-project', children: jsx("div", { className: 'tw:btn tw:btn-sm tw:float-right tw:btn-primary', children: "Donate" }) })] })] }), { autoClose: false });
2753
2770
  }, 600000);
2754
2771
  init.current = true;
2755
2772
  }
@@ -2762,7 +2779,7 @@ function UtopiaMapInner({ children, geo, showFilterControl = false, showGratitud
2762
2779
  // eslint-disable-next-line no-console
2763
2780
  console.log(e.latlng.lat + ',' + e.latlng.lng);
2764
2781
  if (selectNewItemPosition) {
2765
- setMapClicked({ position: e.latlng, setItemFormPopup });
2782
+ setMapClicked({ position: e.latlng, setItemFormPopup: setPopupForm });
2766
2783
  }
2767
2784
  },
2768
2785
  moveend: () => { },
@@ -2833,13 +2850,11 @@ function UtopiaMapInner({ children, geo, showFilterControl = false, showGratitud
2833
2850
  layer.bindPopup(feature.properties.name);
2834
2851
  }
2835
2852
  };
2836
- return (jsxs("div", { className: `tw:h-full ${selectNewItemPosition != null ? 'crosshair-cursor-enabled' : ''}`, children: [jsx(Outlet, {}), jsxs(Control, { position: 'topLeft', zIndex: '1000', absolute: true, children: [jsx(SearchControl, {}), jsx(TagsControl, {})] }), jsxs(Control, { position: 'bottomLeft', zIndex: '999', absolute: true, children: [showFilterControl && jsx(FilterControl, {}), showLayerControl && jsx(LayerControl, {}), showGratitudeControl && jsx(GratitudeControl, {})] }), jsx(TileLayer, { maxZoom: 19, attribution: '\u00A9 <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', url: 'https://tile.osmand.net/hd/{z}/{x}/{y}.png' }), jsx(MarkerClusterGroup, { ref: (r) => setClusterRef(r), showCoverageOnHover: true, chunkedLoading: true, maxClusterRadius: 50, removeOutsideVisibleBounds: false, children: Children.toArray(children).map((child) => isValidElement(child)
2837
- ? cloneElement(child, { setItemFormPopup, itemFormPopup, clusterRef })
2838
- : child) }), geo && (jsx(GeoJSON, { data: geo, onEachFeature: onEachFeature, eventHandlers: {
2853
+ return (jsxs("div", { className: `tw:h-full ${selectNewItemPosition != null ? 'crosshair-cursor-enabled' : ''}`, children: [jsx(Outlet, {}), jsxs(Control, { position: 'topLeft', zIndex: '1000', absolute: true, children: [jsx(SearchControl, {}), jsx(TagsControl, {})] }), jsxs(Control, { position: 'bottomLeft', zIndex: '999', absolute: true, children: [showFilterControl && jsx(FilterControl, {}), showLayerControl && jsx(LayerControl, {}), showGratitudeControl && jsx(GratitudeControl, {})] }), jsx(TileLayer, { maxZoom: 19, attribution: '\u00A9 <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', url: 'https://tile.osmand.net/hd/{z}/{x}/{y}.png' }), jsx(MarkerClusterGroup, { ref: (r) => setClusterRef(r), showCoverageOnHover: true, chunkedLoading: true, maxClusterRadius: 50, removeOutsideVisibleBounds: false, children: children }), geo && (jsx(GeoJSON, { data: geo, onEachFeature: onEachFeature, eventHandlers: {
2839
2854
  click: (e) => {
2840
2855
  if (selectNewItemPosition) {
2841
2856
  e.layer.closePopup();
2842
- setMapClicked({ position: e.latlng, setItemFormPopup });
2857
+ setMapClicked({ position: e.latlng, setItemFormPopup: setPopupForm });
2843
2858
  }
2844
2859
  },
2845
2860
  } })), jsx(MapEventListener, {}), jsx(AddButton, { triggerAction: setSelectNewItemPosition }), selectNewItemPosition != null && (jsx(SelectPosition, { setSelectNewItemPosition: setSelectNewItemPosition }))] }));
@@ -2883,653 +2898,143 @@ function UtopiaMap({ height = '500px', width = '100%', center = [50.6, 9.5], zoo
2883
2898
  return (jsx(ContextWrapper, { children: jsx(MapContainer, { style: { height, width }, center: new LatLng(center[0], center[1]), zoom: zoom, zoomControl: showZoomControl, maxZoom: 19, children: jsx(UtopiaMapInner, { geo: geo, showFilterControl: showFilterControl, showGratitudeControl: showGratitudeControl, showLayerControl: showLayerControl, donationWidget: donationWidget, showThemeControl: showThemeControl, defaultTheme: defaultTheme, children: children }) }) }));
2884
2899
  }
2885
2900
 
2886
- const goldenRatioConjugate = 0.618033988749895;
2887
- const randomColor = () => {
2888
- return hsvToHex((Math.random() + goldenRatioConjugate) % 1, 0.8, 0.7);
2889
- };
2890
- function hsvToHex(h, s, v) {
2891
- let r, g, b;
2892
- const i = Math.floor(h * 6);
2893
- const f = h * 6 - i;
2894
- const p = v * (1 - s);
2895
- const q = v * (1 - f * s);
2896
- const t = v * (1 - (1 - f) * s);
2897
- switch (i % 6) {
2898
- case 0:
2899
- r = v;
2900
- g = t;
2901
- b = p;
2902
- break;
2903
- case 1:
2904
- r = q;
2905
- g = v;
2906
- b = p;
2907
- break;
2908
- case 2:
2909
- r = p;
2910
- g = v;
2911
- b = t;
2912
- break;
2913
- case 3:
2914
- r = p;
2915
- g = q;
2916
- b = v;
2917
- break;
2918
- case 4:
2919
- r = t;
2920
- g = p;
2921
- b = v;
2922
- break;
2923
- case 5:
2924
- r = v;
2925
- g = p;
2926
- b = q;
2927
- break;
2928
- }
2929
- return rgbToHex(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
2930
- }
2931
- const rgbToHex = (r, g, b) => '#' +
2932
- [r, g, b]
2933
- .map((x) => {
2934
- const hex = x.toString(16);
2935
- return hex.length === 1 ? `0${hex}` : hex;
2936
- })
2937
- .join('');
2901
+ const LayerContext = createContext({
2902
+ name: '',
2903
+ markerDefaultColor: '',
2904
+ markerDefaultColor2: '',
2905
+ markerShape: '',
2906
+ menuText: '',
2907
+ });
2938
2908
 
2939
2909
  /**
2940
- * @category Input
2910
+ * @category Map
2941
2911
  */
2942
- function TextAreaInput({ labelTitle, dataField, labelStyle, containerStyle, inputStyle, defaultValue, placeholder, required = true, updateFormValue, }) {
2943
- const ref = useRef(null);
2944
- const [inputValue, setInputValue] = useState(defaultValue);
2912
+ const Layer = ({ data, children, name = 'places', menuIcon = 'MapPinIcon', menuText = 'add new place', menuColor = '#2E7D32', markerIcon, markerShape = 'circle', markerDefaultColor = '#777', markerDefaultColor2 = 'RGBA(35, 31, 32, 0.2)', api, itemType, userProfileLayer = false, customEditLink, customEditParameter,
2913
+ // eslint-disable-next-line camelcase
2914
+ public_edit_items, listed = true, }) => {
2915
+ const setItemsApi = useSetItemsApi();
2916
+ const setItemsData = useSetItemsData();
2917
+ const addTag = useAddTag();
2918
+ const [newTagsToAdd] = useState([]);
2919
+ const [tagsReady] = useState(false);
2945
2920
  useEffect(() => {
2946
- setInputValue(defaultValue);
2947
- }, [defaultValue]);
2948
- const handleChange = (e) => {
2949
- const newValue = e.target.value;
2950
- setInputValue(newValue);
2951
- if (updateFormValue) {
2952
- updateFormValue(newValue);
2921
+ data &&
2922
+ setItemsData({
2923
+ data,
2924
+ children,
2925
+ name,
2926
+ menuIcon,
2927
+ menuText,
2928
+ menuColor,
2929
+ markerIcon,
2930
+ markerShape,
2931
+ markerDefaultColor,
2932
+ markerDefaultColor2,
2933
+ api,
2934
+ itemType,
2935
+ userProfileLayer,
2936
+ // Can we just use editCallback for all cases?
2937
+ customEditLink,
2938
+ customEditParameter,
2939
+ // eslint-disable-next-line camelcase
2940
+ public_edit_items,
2941
+ listed,
2942
+ });
2943
+ api &&
2944
+ setItemsApi({
2945
+ data,
2946
+ children,
2947
+ name,
2948
+ menuIcon,
2949
+ menuText,
2950
+ menuColor,
2951
+ markerIcon,
2952
+ markerShape,
2953
+ markerDefaultColor,
2954
+ markerDefaultColor2,
2955
+ api,
2956
+ itemType,
2957
+ userProfileLayer,
2958
+ customEditLink,
2959
+ customEditParameter,
2960
+ // eslint-disable-next-line camelcase
2961
+ public_edit_items,
2962
+ listed,
2963
+ });
2964
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2965
+ }, [data, api]);
2966
+ useEffect(() => {
2967
+ if (tagsReady) {
2968
+ const processedTags = {};
2969
+ newTagsToAdd.map((newtag) => {
2970
+ if (!processedTags[newtag.name]) {
2971
+ processedTags[newtag.name] = true;
2972
+ addTag(newtag);
2973
+ }
2974
+ return null;
2975
+ });
2953
2976
  }
2954
- };
2955
- return (jsxs("div", { className: `tw:form-control tw:w-full ${containerStyle ?? ''}`, children: [labelTitle ? (jsx("label", { className: 'tw:label', children: jsx("span", { className: `tw:label-text tw:text-base-content ${labelStyle ?? ''}`, children: labelTitle }) })) : null, jsx("textarea", { required: required, ref: ref, value: inputValue, name: dataField, className: `tw:textarea tw:textarea-bordered tw:w-full tw:leading-5 ${inputStyle ?? ''}`, placeholder: placeholder ?? '', onChange: handleChange })] }));
2956
- }
2977
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2978
+ }, [tagsReady]);
2979
+ return (jsx(LayerContext.Provider, { value: {
2980
+ name,
2981
+ markerDefaultColor,
2982
+ markerDefaultColor2,
2983
+ markerShape,
2984
+ markerIcon,
2985
+ menuText,
2986
+ }, children: children }));
2987
+ };
2957
2988
 
2958
2989
  /**
2959
- * @category Input
2990
+ * This Components injects Tags comming from an {@link ItemsApi | `API`}
2991
+ * ```tsx
2992
+ * <Tags api={tagsApi} />
2993
+ * ```
2994
+ * or from on {@link Tag| `Array`}
2995
+ * ```tsx
2996
+ * <Tags data={tags} />
2997
+ * ```
2998
+ * Can be child of {@link AppShell | `AppShell`}
2999
+ * ```tsx
3000
+ * <AppShell>
3001
+ * ...
3002
+ * <Tags api={tagsApi} />
3003
+ * </AppShell>
3004
+ * ```
3005
+ * Or child of {@link UtopiaMap | `UtopiaMap`}
3006
+ * ```tsx
3007
+ * <UtopiaMap>
3008
+ * ...
3009
+ * <Tags api={tagsApi} />
3010
+ * </UtopiaMap>
3011
+ * ```
3012
+ * @category Map
2960
3013
  */
2961
- function TextInput({ labelTitle, labelStyle, type, dataField, containerStyle, inputStyle, defaultValue, placeholder, autocomplete, pattern, required = true, updateFormValue, }) {
2962
- const [inputValue, setInputValue] = useState(defaultValue ?? '');
3014
+ function Tags({ data, api }) {
3015
+ const setTagData = useSetTagData();
3016
+ const setTagApi = useSetTagApi();
2963
3017
  useEffect(() => {
2964
- setInputValue(defaultValue ?? '');
2965
- }, [defaultValue]);
2966
- const handleChange = (e) => {
2967
- const newValue = e.target.value;
2968
- setInputValue(newValue);
2969
- if (updateFormValue) {
2970
- updateFormValue(newValue);
2971
- }
2972
- };
2973
- return (jsxs("div", { className: `tw:form-control ${containerStyle ?? ''}`, children: [labelTitle ? (jsx("label", { className: 'tw:label', children: jsx("span", { className: `tw:label-text tw:text-base-content ${labelStyle ?? ''}`, children: labelTitle }) })) : null, jsx("input", { required: required, pattern: pattern, type: type ?? 'text', name: dataField, value: inputValue, placeholder: placeholder ?? '', autoComplete: autocomplete, onChange: handleChange, className: `tw:input tw:input-bordered tw:w-full ${inputStyle ?? ''}` })] }));
2974
- }
2975
-
2976
- function ItemFormPopup(props) {
2977
- const [spinner, setSpinner] = useState(false);
2978
- const [popupTitle, setPopupTitle] = useState('');
2979
- const formRef = useRef(null);
2980
- const map = useMap();
2981
- const addItem = useAddItem();
2982
- const updateItem = useUpdateItem();
2983
- const items = useItems();
2984
- useRemoveItem();
2985
- const tags = useTags();
2986
- const addTag = useAddTag();
3018
+ data && setTagData(data);
3019
+ api && setTagApi(api);
3020
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3021
+ }, [api, data]);
3022
+ const location = useLocation();
3023
+ const addFilterTag = useAddFilterTag();
2987
3024
  const resetFilterTags = useResetFilterTags();
2988
- const { user } = useAuth();
2989
- const handleSubmit = async (evt) => {
2990
- const formItem = {};
2991
- Array.from(evt.target).forEach((input) => {
2992
- if (input.name) {
2993
- formItem[input.name] = input.value;
2994
- }
2995
- });
2996
- formItem.position = { type: 'Point', coordinates: [props.position.lng, props.position.lat] };
2997
- evt.preventDefault();
2998
- const name = formItem.name ? formItem.name : user?.first_name;
2999
- if (!name) {
3000
- toast.error('Name is must be defined');
3001
- return;
3002
- }
3003
- setSpinner(true);
3004
- formItem.text &&
3005
- formItem.text
3006
- .toLocaleLowerCase()
3007
- .match(hashTagRegex)
3008
- ?.map((tag) => {
3009
- if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
3010
- addTag({ id: crypto.randomUUID(), name: tag.slice(1), color: randomColor() });
3011
- }
3012
- return null;
3013
- });
3014
- if (props.item) {
3015
- let success = false;
3016
- try {
3017
- await props.layer.api?.updateItem({ ...formItem, id: props.item.id });
3018
- success = true;
3019
- // eslint-disable-next-line no-catch-all/no-catch-all
3020
- }
3021
- catch (error) {
3022
- toast.error(error.toString());
3023
- }
3024
- if (success) {
3025
- updateItem({ ...props.item, ...formItem });
3026
- toast.success('Item updated');
3027
- }
3028
- setSpinner(false);
3029
- map.closePopup();
3030
- }
3031
- else {
3032
- const item = items.find((i) => i.user_created?.id === user?.id && i.layer === props.layer);
3033
- const uuid = crypto.randomUUID();
3034
- let success = false;
3035
- try {
3036
- props.layer.userProfileLayer &&
3037
- item &&
3038
- (await props.layer.api?.updateItem({ ...formItem, id: item.id }));
3039
- (!props.layer.userProfileLayer || !item) &&
3040
- (await props.layer.api?.createItem({
3041
- ...formItem,
3042
- name,
3043
- id: uuid,
3044
- }));
3045
- success = true;
3046
- // eslint-disable-next-line no-catch-all/no-catch-all
3047
- }
3048
- catch (error) {
3049
- toast.error(error.toString());
3050
- }
3051
- if (success) {
3052
- if (props.layer.userProfileLayer && item)
3053
- updateItem({ ...item, ...formItem });
3054
- if (!props.layer.userProfileLayer || !item) {
3055
- addItem({
3056
- ...formItem,
3057
- name: (formItem.name ? formItem.name : user?.first_name) ?? '',
3058
- user_created: user ?? undefined,
3059
- id: uuid,
3060
- layer: props.layer,
3061
- public_edit: !user,
3062
- });
3063
- }
3064
- toast.success('New item created');
3065
- resetFilterTags();
3066
- }
3067
- setSpinner(false);
3068
- map.closePopup();
3069
- }
3070
- props.setItemFormPopup(null);
3071
- };
3072
- const resetPopup = () => {
3073
- if (formRef.current) {
3074
- formRef.current.reset();
3075
- }
3076
- };
3077
- useEffect(() => {
3078
- resetPopup();
3079
- }, [props.position]);
3080
- return (jsx(Popup, { minWidth: 275, maxWidth: 275, autoPanPadding: [20, 80], eventHandlers: {
3081
- remove: () => {
3082
- setTimeout(function () {
3083
- resetPopup();
3084
- }, 100);
3085
- },
3086
- }, position: props.position, children: jsxs("form", { ref: formRef, onReset: resetPopup, autoComplete: 'off', onSubmit: (e) => handleSubmit(e), children: [props.item ? (jsx("div", { className: 'tw:h-3' })) : (jsx("div", { className: 'tw:flex tw:justify-center', children: jsx("b", { className: 'tw:text-xl tw:text-center tw:font-bold', children: props.layer.menuText }) })), props.children ? (Children.toArray(props.children).map((child) => isValidElement(child)
3087
- ? cloneElement(child, {
3088
- item: props.item,
3089
- key: props.position.toString(),
3090
- setPopupTitle,
3091
- })
3092
- : '')) : (jsxs(Fragment, { children: [jsx(TextInput, { type: 'text', placeholder: 'Name', dataField: 'name', defaultValue: props.item ? props.item.name : '', inputStyle: '' }), jsx(TextAreaInput, { placeholder: 'Text', dataField: 'text', defaultValue: props.item?.text ?? '', inputStyle: 'tw:h-40 tw:mt-5' }, props.position.toString())] })), jsx("div", { className: 'tw:flex tw:justify-center', children: jsx("button", { className: spinner
3093
- ? 'tw:btn tw:btn-disabled tw:mt-5 tw:place-self-center'
3094
- : 'tw:btn tw:mt-5 tw:place-self-center', type: 'submit', children: spinner ? jsx("span", { className: 'tw:loading tw:loading-spinner' }) : 'Save' }) })] }) }));
3095
- }
3096
-
3097
- // in miliseconds
3098
- const units = [
3099
- { label: 'year', seconds: 31536000 },
3100
- { label: 'month', seconds: 2592000 },
3101
- { label: 'week', seconds: 604800 },
3102
- { label: 'day', seconds: 86400 },
3103
- { label: 'hour', seconds: 3600 },
3104
- { label: 'minute', seconds: 60 },
3105
- { label: 'second', seconds: 1 },
3106
- ];
3107
- const timeAgo = (date) => {
3108
- const time = Math.floor((new Date().valueOf() - new Date(date).valueOf()) / 1000);
3109
- const { interval, unit } = calculateTimeDifference(time);
3110
- const suffix = interval === 1 ? '' : 's';
3111
- return `${interval} ${unit}${suffix} ago`;
3112
- };
3113
- const calculateTimeDifference = (time) => {
3114
- for (const { label, seconds } of units) {
3115
- const interval = Math.floor(time / seconds);
3116
- if (interval >= 1) {
3117
- return {
3118
- interval,
3119
- unit: label,
3120
- };
3121
- }
3122
- }
3123
- return {
3124
- interval: 0,
3125
- unit: '',
3126
- };
3127
- };
3128
-
3129
- function EllipsisVerticalIcon({
3130
- title,
3131
- titleId,
3132
- ...props
3133
- }, svgRef) {
3134
- return /*#__PURE__*/React.createElement("svg", Object.assign({
3135
- xmlns: "http://www.w3.org/2000/svg",
3136
- viewBox: "0 0 16 16",
3137
- fill: "currentColor",
3138
- "aria-hidden": "true",
3139
- "data-slot": "icon",
3140
- ref: svgRef,
3141
- "aria-labelledby": titleId
3142
- }, props), title ? /*#__PURE__*/React.createElement("title", {
3143
- id: titleId
3144
- }, title) : null, /*#__PURE__*/React.createElement("path", {
3145
- d: "M8 2a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM8 6.5a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM9.5 12.5a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0Z"
3146
- }));
3147
- }
3148
- const ForwardRef$9 = /*#__PURE__*/ React.forwardRef(EllipsisVerticalIcon);
3149
-
3150
- function PencilIcon({
3151
- title,
3152
- titleId,
3153
- ...props
3154
- }, svgRef) {
3155
- return /*#__PURE__*/React.createElement("svg", Object.assign({
3156
- xmlns: "http://www.w3.org/2000/svg",
3157
- viewBox: "0 0 24 24",
3158
- fill: "currentColor",
3159
- "aria-hidden": "true",
3160
- "data-slot": "icon",
3161
- ref: svgRef,
3162
- "aria-labelledby": titleId
3163
- }, props), title ? /*#__PURE__*/React.createElement("title", {
3164
- id: titleId
3165
- }, title) : null, /*#__PURE__*/React.createElement("path", {
3166
- d: "M21.731 2.269a2.625 2.625 0 0 0-3.712 0l-1.157 1.157 3.712 3.712 1.157-1.157a2.625 2.625 0 0 0 0-3.712ZM19.513 8.199l-3.712-3.712-12.15 12.15a5.25 5.25 0 0 0-1.32 2.214l-.8 2.685a.75.75 0 0 0 .933.933l2.685-.8a5.25 5.25 0 0 0 2.214-1.32L19.513 8.2Z"
3167
- }));
3168
- }
3169
- const ForwardRef$8 = /*#__PURE__*/ React.forwardRef(PencilIcon);
3170
-
3171
- function TrashIcon({
3172
- title,
3173
- titleId,
3174
- ...props
3175
- }, svgRef) {
3176
- return /*#__PURE__*/React.createElement("svg", Object.assign({
3177
- xmlns: "http://www.w3.org/2000/svg",
3178
- viewBox: "0 0 24 24",
3179
- fill: "currentColor",
3180
- "aria-hidden": "true",
3181
- "data-slot": "icon",
3182
- ref: svgRef,
3183
- "aria-labelledby": titleId
3184
- }, props), title ? /*#__PURE__*/React.createElement("title", {
3185
- id: titleId
3186
- }, title) : null, /*#__PURE__*/React.createElement("path", {
3187
- fillRule: "evenodd",
3188
- d: "M16.5 4.478v.227a48.816 48.816 0 0 1 3.878.512.75.75 0 1 1-.256 1.478l-.209-.035-1.005 13.07a3 3 0 0 1-2.991 2.77H8.084a3 3 0 0 1-2.991-2.77L4.087 6.66l-.209.035a.75.75 0 0 1-.256-1.478A48.567 48.567 0 0 1 7.5 4.705v-.227c0-1.564 1.213-2.9 2.816-2.951a52.662 52.662 0 0 1 3.369 0c1.603.051 2.815 1.387 2.815 2.951Zm-6.136-1.452a51.196 51.196 0 0 1 3.273 0C14.39 3.05 15 3.684 15 4.478v.113a49.488 49.488 0 0 0-6 0v-.113c0-.794.609-1.428 1.364-1.452Zm-.355 5.945a.75.75 0 1 0-1.5.058l.347 9a.75.75 0 1 0 1.499-.058l-.346-9Zm5.48.058a.75.75 0 1 0-1.498-.058l-.347 9a.75.75 0 0 0 1.5.058l.345-9Z",
3189
- clipRule: "evenodd"
3190
- }));
3191
- }
3192
- const ForwardRef$7 = /*#__PURE__*/ React.forwardRef(TrashIcon);
3193
-
3194
- var TargetDotSVG = 'data:image/svg+xml;base64,PHN2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlPSdjdXJyZW50Q29sb3InCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPSdjdXJyZW50Q29sb3InCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2VXaWR0aD0nMCcKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdCb3g9JzAgMCA1MTIgNTEyJwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPSd3LTUgaC01JwogICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJwogICAgICAgICAgICAgICAgICAgICAgICAgID4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9J00yNTYgMGMxNy43IDAgMzIgMTQuMyAzMiAzMlY0Mi40YzkzLjcgMTMuOSAxNjcuNyA4OCAxODEuNiAxODEuNkg0ODBjMTcuNyAwIDMyIDE0LjMgMzIgMzJzLTE0LjMgMzItMzIgMzJINDY5LjZjLTEzLjkgOTMuNy04OCAxNjcuNy0xODEuNiAxODEuNlY0ODBjMCAxNy43LTE0LjMgMzItMzIgMzJzLTMyLTE0LjMtMzItMzJWNDY5LjZDMTMwLjMgNDU1LjcgNTYuMyAzODEuNyA0Mi40IDI4OEgzMmMtMTcuNyAwLTMyLTE0LjMtMzItMzJzMTQuMy0zMiAzMi0zMkg0Mi40QzU2LjMgMTMwLjMgMTMwLjMgNTYuMyAyMjQgNDIuNFYzMmMwLTE3LjcgMTQuMy0zMiAzMi0zMnpNMTA3LjQgMjg4YzEyLjUgNTguMyA1OC40IDEwNC4xIDExNi42IDExNi42VjM4NGMwLTE3LjcgMTQuMy0zMiAzMi0zMnMzMiAxNC4zIDMyIDMydjIwLjZjNTguMy0xMi41IDEwNC4xLTU4LjQgMTE2LjYtMTE2LjZIMzg0Yy0xNy43IDAtMzItMTQuMy0zMi0zMnMxNC4zLTMyIDMyLTMyaDIwLjZDMzkyLjEgMTY1LjcgMzQ2LjMgMTE5LjkgMjg4IDEwNy40VjEyOGMwIDE3LjctMTQuMyAzMi0zMiAzMnMtMzItMTQuMy0zMi0zMlYxMDcuNEMxNjUuNyAxMTkuOSAxMTkuOSAxNjUuNyAxMDcuNCAyMjRIMTI4YzE3LjcgMCAzMiAxNC4zIDMyIDMycy0xNC4zIDMyLTMyIDMySDEwNy40ek0yNTYgMjI0YTMyIDMyIDAgMSAxIDAgNjQgMzIgMzIgMCAxIDEgMC02NHonPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz4=';
3195
-
3196
- const isClickInsideRectangle = (e, element) => {
3197
- const r = element.getBoundingClientRect();
3198
- return e.clientX > r.left && e.clientX < r.right && e.clientY > r.top && e.clientY < r.bottom;
3199
- };
3200
- const DialogModal = ({ title, isOpened, onClose, children, showCloseButton = true, closeOnClickOutside = true, className, }) => {
3201
- const ref = useRef(null);
3202
- useEffect(() => {
3203
- if (isOpened) {
3204
- ref.current?.showModal();
3205
- ref.current?.classList.remove('tw:hidden');
3206
- document.body.classList.add('modal-open'); // prevent bg scroll
3207
- }
3208
- else {
3209
- ref.current?.close();
3210
- ref.current?.classList.add('tw:hidden');
3211
- document.body.classList.remove('modal-open');
3212
- }
3213
- }, [isOpened]);
3214
- if (isOpened) {
3215
- return (jsx("dialog", { className: `${className ?? ''} card tw:shadow-xl tw:absolute tw:right-0 tw:top-0 tw:bottom-0 tw:left-0 tw:m-auto tw:transition-opacity tw:duration-300 tw:p-4 tw:max-w-xl tw:bg-base-100`, ref: ref, onCancel: onClose, onClick: (e) => ref.current && !isClickInsideRectangle(e, ref.current) && closeOnClickOutside && onClose(), children: jsxs("div", { className: 'card-body tw:p-2', children: [jsx("h2", { className: 'tw:text-2xl tw:font-semibold tw:mb-2 tw:text-center', children: title }), children, showCloseButton && (jsx("button", { className: 'btn btn-sm btn-circle btn-ghost tw:absolute tw:right-2 tw:top-2', onClick: onClose, children: "\u2715" }))] }) }));
3216
- }
3217
- else
3218
- return jsx(Fragment, {});
3219
- };
3220
-
3221
- function HeaderView({ item, api, editCallback, deleteCallback, setPositionCallback, loading, hideMenu = false, big = false, truncateSubname = true, hideSubname = false, showAddress = false, }) {
3222
- const [modalOpen, setModalOpen] = useState(false);
3223
- const hasUserPermission = useHasUserPermission();
3224
- const navigate = useNavigate();
3225
- const appState = useAppState();
3226
- const [imageLoaded, setImageLoaded] = useState(false);
3227
- const avatar = item.image && appState.assetsApi.url + item.image + '?width=160&heigth=160';
3228
- const title = item.name;
3229
- const subtitle = item.subname;
3230
- const [address] = useState('');
3231
- const params = new URLSearchParams(window.location.search);
3232
- const openDeleteModal = async (event) => {
3233
- setModalOpen(true);
3234
- event.stopPropagation();
3235
- };
3236
- return (jsxs(Fragment, { children: [jsxs("div", { className: 'tw:flex tw:flex-row', children: [jsx("div", { className: 'tw:grow tw:max-w-[calc(100%-60px)] }', children: jsxs("div", { className: 'flex items-center', children: [avatar && (jsx("div", { className: 'tw:avatar', children: jsxs("div", { className: `${big ? 'tw:w-20' : 'tw:w-10'} tw:inline tw:items-center tw:justify-center overflow-hidden`, children: [jsx("img", { className: 'tw:w-full tw:h-full tw:object-cover tw:rounded-full', src: avatar, alt: item.name + ' logo', onLoad: () => setImageLoaded(true), onError: () => setImageLoaded(false), style: { display: imageLoaded ? 'block' : 'none' } }), !imageLoaded && (jsx("div", { className: 'tw:w-full tw:h-full tw:bg-gray-200 tw:rounded-full' }))] }) })), jsxs("div", { className: `${avatar ? 'tw:ml-2' : ''} tw:overflow-hidden`, children: [jsx("div", { className: `${big ? 'tw:xl:text-3xl tw:text-2xl' : 'tw:text-xl'} tw:font-semibold tw:truncate`, title: title, children: title }), showAddress && address && !hideSubname && (jsx("div", { className: `tw:text-xs tw:text-gray-500 ${truncateSubname && 'tw:truncate'}`, children: address })), subtitle && !hideSubname && (jsx("div", { className: `tw:text-xs tw:opacity-50 ${truncateSubname && 'tw:truncate'}`, children: subtitle }))] })] }) }), jsx("div", { onClick: (e) => e.stopPropagation(), className: `${big ? 'tw:mt-5' : 'tw:mt-1'}`, children: (api?.deleteItem || item.layer?.api?.updateItem) &&
3237
- (hasUserPermission(api?.collectionName, 'delete', item) ||
3238
- hasUserPermission(api?.collectionName, 'update', item)) &&
3239
- !hideMenu && (jsxs("div", { className: 'tw:dropdown tw:dropdown-bottom', children: [jsx("label", { tabIndex: 0, className: 'tw:bg-base-100 tw:btn tw:m-1 tw:leading-3 tw:border-none tw:min-h-0 tw:h-6', children: jsx(ForwardRef$9, { className: 'tw:h-5 tw:w-5' }) }), jsxs("ul", { tabIndex: 0, className: 'tw:dropdown-content tw:menu tw:p-2 tw:shadow tw:bg-base-100 tw:rounded-box tw:z-1000', children: [api?.updateItem &&
3240
- hasUserPermission(api.collectionName, 'update', item) &&
3241
- editCallback && (jsx("li", { children: jsx("a", { className: 'tw:text-base-content! tw:cursor-pointer', onClick: (e) => item.layer?.customEditLink
3242
- ? navigate(`${item.layer.customEditLink}${item.layer.customEditParameter ? `/${item.id}${params && '?' + params}` : ''} `)
3243
- : editCallback(e), children: jsx(ForwardRef$8, { className: 'tw:h-5 tw:w-5' }) }) })), api?.updateItem &&
3244
- hasUserPermission(api.collectionName, 'update', item) &&
3245
- setPositionCallback && (jsx("li", { children: jsx("a", { className: 'tw:text-base-content! tw:cursor-pointer', onClick: setPositionCallback, children: jsx(SVG, { src: TargetDotSVG, className: 'tw:w-5 tw:h-5' }) }) })), api?.deleteItem &&
3246
- hasUserPermission(api.collectionName, 'delete', item) &&
3247
- deleteCallback && (jsx("li", { children: jsx("a", { className: 'tw:cursor-pointer tw:text-error!', onClick: openDeleteModal, children: loading ? (jsx("span", { className: 'tw:loading tw:loading-spinner tw:loading-sm' })) : (jsx(ForwardRef$7, { className: 'tw:h-5 tw:w-5' })) }) }))] })] })) })] }), jsx(DialogModal, { isOpened: modalOpen, title: 'Are you sure?', showCloseButton: false, onClose: () => setModalOpen(false), children: jsxs("div", { onClick: (e) => e.stopPropagation(), children: [jsxs("span", { children: ["Do you want to delete ", jsx("b", { children: item.name }), "?"] }), jsx("div", { className: 'tw:grid', children: jsxs("div", { className: 'tw:flex tw:justify-between', children: [jsx("label", { className: 'tw:btn tw:mt-4 tw:btn-error', onClick: (e) => {
3248
- deleteCallback(e);
3249
- setModalOpen(false);
3250
- }, children: "Yes" }), jsx("label", { className: 'tw:btn tw:mt-4', onClick: () => setModalOpen(false), children: "No" })] }) })] }) })] }));
3251
- }
3252
-
3253
- // eslint-disable-next-line react/display-name
3254
- const ItemViewPopup = forwardRef((props, ref) => {
3255
- const map = useMap();
3256
- const [loading, setLoading] = useState(false);
3257
- const removeItem = useRemoveItem();
3258
- const updadateItem = useUpdateItem();
3259
- const navigate = useNavigate();
3260
- const setSelectPosition = useSetSelectPosition();
3261
- const [infoExpanded, setInfoExpanded] = useState(false);
3262
- const handleEdit = (event) => {
3263
- event.stopPropagation();
3264
- map.closePopup();
3265
- props.setItemFormPopup &&
3266
- props.setItemFormPopup({
3267
- position: new LatLng(props.item.position?.coordinates[1], props.item.position?.coordinates[0]),
3268
- layer: props.item.layer,
3269
- item: props.item,
3270
- setItemFormPopup: props.setItemFormPopup,
3271
- });
3272
- };
3273
- const handleDelete = async (event) => {
3274
- event.stopPropagation();
3275
- setLoading(true);
3276
- let success = false;
3277
- try {
3278
- !props.item.layer?.userProfileLayer &&
3279
- (await props.item.layer?.api?.deleteItem(props.item.id));
3280
- props.item.layer?.userProfileLayer &&
3281
- (await props.item.layer.api?.updateItem({ id: props.item.id, position: null }));
3282
- success = true;
3283
- // eslint-disable-next-line no-catch-all/no-catch-all
3284
- }
3285
- catch (error) {
3286
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
3287
- toast.error(error.toString());
3288
- }
3289
- if (success) {
3290
- !props.item.layer?.userProfileLayer && removeItem(props.item);
3291
- props.item.layer?.userProfileLayer && updadateItem({ ...props.item, position: undefined });
3292
- toast.success('Item deleted');
3293
- }
3294
- setLoading(false);
3295
- map.closePopup();
3296
- const params = new URLSearchParams(window.location.search);
3297
- window.history.pushState({}, '', '/' + `${params ? `?${params}` : ''}`);
3298
- navigate('/');
3299
- };
3300
- return (jsx(Popup, { ref: ref, maxHeight: 377, minWidth: 275, maxWidth: 275, autoPanPadding: [20, 80], children: jsxs("div", { className: 'tw:bg-base-100 tw:text-base-content', children: [jsx(HeaderView, { api: props.item.layer?.api, item: props.item, editCallback: handleEdit, deleteCallback: handleDelete, setPositionCallback: () => {
3301
- map.closePopup();
3302
- setSelectPosition(props.item);
3303
- navigate('/');
3304
- }, loading: loading }), jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: props.children ? (Children.toArray(props.children).map((child) => isValidElement(child)
3305
- ? cloneElement(child, { item: props.item })
3306
- : '')) : (jsx(TextView, { text: props.item.text, itemId: props.item.id })) }), jsxs("div", { className: 'tw:flex tw:-mb-1 tw:flex-row tw:mr-2 tw:mt-1', children: [infoExpanded ? (jsx("p", { className: 'tw:italic tw:min-h-[21px] tw:my-0! tw:opacity-50', children: `${props.item.date_updated && props.item.date_updated !== props.item.date_created ? 'updated' : 'posted'} ${props.item && props.item.user_created && props.item.user_created.first_name ? `by ${props.item.user_created.first_name}` : ''} ${props.item.date_updated ? timeAgo(props.item.date_updated) : timeAgo(props.item.date_created)}` })) : (jsx("p", { className: 'tw:my-0! tw:min-h-[21px] tw:font-bold tw:cursor-pointer tw:text-gray-500', onClick: () => setInfoExpanded(true), children: "\u24D8" })), jsx("div", { className: 'tw:grow' })] })] }) }));
3307
- });
3308
-
3309
- /**
3310
- * @category Map
3311
- */
3312
- const Layer = ({ data, children, name = 'places', menuIcon = 'MapPinIcon', menuText = 'add new place', menuColor = '#2E7D32', markerIcon, markerShape = 'circle', markerDefaultColor = '#777', markerDefaultColor2 = 'RGBA(35, 31, 32, 0.2)', api, itemType, userProfileLayer = false, customEditLink, customEditParameter,
3313
- // eslint-disable-next-line camelcase
3314
- public_edit_items, listed = true, setItemFormPopup, itemFormPopup, clusterRef, }) => {
3315
- const filterTags = useFilterTags();
3316
- const items = useItems();
3317
- const setItemsApi = useSetItemsApi();
3318
- const setItemsData = useSetItemsData();
3319
- const getItemTags = useGetItemTags();
3320
- const addMarker = useAddMarker();
3321
- const addPopup = useAddPopup();
3322
- const leafletRefs = useLeafletRefs();
3323
- const allTagsLoaded = useAllTagsLoaded();
3324
- const allItemsLoaded = useAllItemsLoaded();
3325
- const setMarkerClicked = useSetMarkerClicked();
3326
- const selectPosition = useSelectPosition();
3327
- const tags = useTags();
3328
- const addTag = useAddTag();
3329
- const [newTagsToAdd, setNewTagsToAdd] = useState([]);
3330
- const [tagsReady, setTagsReady] = useState(false);
3331
- const isLayerVisible = useIsLayerVisible();
3332
- const isGroupTypeVisible = useIsGroupTypeVisible();
3333
- const visibleGroupTypes = useVisibleGroupType();
3334
- const appState = useAppState();
3335
- useEffect(() => {
3336
- data &&
3337
- setItemsData({
3338
- data,
3339
- children,
3340
- name,
3341
- menuIcon,
3342
- menuText,
3343
- menuColor,
3344
- markerIcon,
3345
- markerShape,
3346
- markerDefaultColor,
3347
- markerDefaultColor2,
3348
- api,
3349
- itemType,
3350
- userProfileLayer,
3351
- // Can we just use editCallback for all cases?
3352
- customEditLink,
3353
- customEditParameter,
3354
- // eslint-disable-next-line camelcase
3355
- public_edit_items,
3356
- listed,
3357
- setItemFormPopup,
3358
- itemFormPopup,
3359
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
3360
- clusterRef,
3361
- });
3362
- api &&
3363
- setItemsApi({
3364
- data,
3365
- children,
3366
- name,
3367
- menuIcon,
3368
- menuText,
3369
- menuColor,
3370
- markerIcon,
3371
- markerShape,
3372
- markerDefaultColor,
3373
- markerDefaultColor2,
3374
- api,
3375
- itemType,
3376
- userProfileLayer,
3377
- customEditLink,
3378
- customEditParameter,
3379
- // eslint-disable-next-line camelcase
3380
- public_edit_items,
3381
- listed,
3382
- setItemFormPopup,
3383
- itemFormPopup,
3384
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
3385
- clusterRef,
3386
- });
3387
- // eslint-disable-next-line react-hooks/exhaustive-deps
3388
- }, [data, api]);
3389
- useEffect(() => {
3390
- if (tagsReady) {
3391
- const processedTags = {};
3392
- newTagsToAdd.map((newtag) => {
3393
- if (!processedTags[newtag.name]) {
3394
- processedTags[newtag.name] = true;
3395
- addTag(newtag);
3396
- }
3397
- return null;
3398
- });
3399
- }
3400
- // eslint-disable-next-line react-hooks/exhaustive-deps
3401
- }, [tagsReady]);
3402
- return (jsxs(Fragment, { children: [items &&
3403
- items
3404
- .filter((item) => item.layer?.name === name)
3405
- .filter((item) => filterTags.length === 0
3406
- ? item
3407
- : filterTags.some((tag) => getItemTags(item).some((filterTag) => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))
3408
- .filter((item) => item.layer && isLayerVisible(item.layer))
3409
- .filter((item) => (item.group_type && isGroupTypeVisible(item.group_type)) ||
3410
- visibleGroupTypes.length === 0)
3411
- .map((item) => {
3412
- if (item.position?.coordinates[0] && item.position?.coordinates[1]) {
3413
- if (item.tags) {
3414
- item.text += '\n\n';
3415
- item.tags.map((tag) => {
3416
- if (!item.text?.includes(`#${encodeTag(tag)}`)) {
3417
- item.text += `#${encodeTag(tag)}`;
3418
- }
3419
- return item.text;
3420
- });
3421
- }
3422
- if (allTagsLoaded && allItemsLoaded) {
3423
- item.text?.match(hashTagRegex)?.map((tag) => {
3424
- if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase()) &&
3425
- !newTagsToAdd.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
3426
- const newTag = {
3427
- id: crypto.randomUUID(),
3428
- name: tag.slice(1),
3429
- color: randomColor(),
3430
- };
3431
- setNewTagsToAdd((current) => [...current, newTag]);
3432
- }
3433
- return null;
3434
- });
3435
- !tagsReady && setTagsReady(true);
3436
- }
3437
- const itemTags = getItemTags(item);
3438
- const latitude = item.position.coordinates[1];
3439
- const longitude = item.position.coordinates[0];
3440
- let color1 = markerDefaultColor;
3441
- let color2 = markerDefaultColor2;
3442
- if (item.color) {
3443
- color1 = item.color;
3444
- }
3445
- else if (itemTags[0]) {
3446
- color1 = itemTags[0].color;
3447
- }
3448
- if (itemTags[0] && item.color) {
3449
- color2 = itemTags[0].color;
3450
- }
3451
- else if (itemTags[1]) {
3452
- color2 = itemTags[1].color;
3453
- }
3454
- return (jsxs(Marker, { ref: (r) => {
3455
- if (!(item.id in leafletRefs && leafletRefs[item.id].marker === r)) {
3456
- r && addMarker(item, r);
3457
- }
3458
- }, eventHandlers: {
3459
- click: () => {
3460
- selectPosition && setMarkerClicked(item);
3461
- },
3462
- }, icon: MarkerIconFactory(markerShape, color1, color2, item.markerIcon ? item.markerIcon : markerIcon, appState.assetsApi.url), position: [latitude, longitude], children: [children &&
3463
- Children.toArray(children).some((child) => isComponentWithType(child) && child.type.__TYPE === 'ItemView') ? (Children.toArray(children).map((child) => isComponentWithType(child) && child.type.__TYPE === 'ItemView' ? (jsx(ItemViewPopup, { ref: (r) => {
3464
- if (!(item.id in leafletRefs && leafletRefs[item.id].popup === r)) {
3465
- r && addPopup(item, r);
3466
- }
3467
- }, item: item, setItemFormPopup: setItemFormPopup, children: child }, item.id + item.name)) : null)) : (jsx(Fragment, { children: jsx(ItemViewPopup, { ref: (r) => {
3468
- if (!(item.id in leafletRefs && leafletRefs[item.id].popup === r)) {
3469
- r && addPopup(item, r);
3470
- }
3471
- }, item: item, setItemFormPopup: setItemFormPopup }, item.id + item.name) })), jsx(Tooltip, { offset: [0, -38], direction: 'top', children: item.name })] }, item.id));
3472
- }
3473
- else
3474
- return null;
3475
- }), itemFormPopup &&
3476
- itemFormPopup.layer.name === name &&
3477
- (children &&
3478
- Children.toArray(children).some((child) => isComponentWithType(child) && child.type.__TYPE === 'ItemForm') ? (Children.toArray(children).map((child) => isComponentWithType(child) && child.type.__TYPE === 'ItemForm' ? (jsx(ItemFormPopup, { position: itemFormPopup.position, layer: itemFormPopup.layer, setItemFormPopup: setItemFormPopup, item: itemFormPopup.item, children: child }, setItemFormPopup?.name)) : (''))) : (jsx(Fragment, { children: jsx(ItemFormPopup, { position: itemFormPopup.position, layer: itemFormPopup.layer, setItemFormPopup: setItemFormPopup, item: itemFormPopup.item }) })))] }));
3479
- };
3480
- function isComponentWithType(node) {
3481
- return isValidElement(node) && typeof node.type !== 'string' && '__TYPE' in node.type;
3482
- }
3483
-
3484
- /**
3485
- * This Components injects Tags comming from an {@link ItemsApi | `API`}
3486
- * ```tsx
3487
- * <Tags api={tagsApi} />
3488
- * ```
3489
- * or from on {@link Tag| `Array`}
3490
- * ```tsx
3491
- * <Tags data={tags} />
3492
- * ```
3493
- * Can be child of {@link AppShell | `AppShell`}
3494
- * ```tsx
3495
- * <AppShell>
3496
- * ...
3497
- * <Tags api={tagsApi} />
3498
- * </AppShell>
3499
- * ```
3500
- * Or child of {@link UtopiaMap | `UtopiaMap`}
3501
- * ```tsx
3502
- * <UtopiaMap>
3503
- * ...
3504
- * <Tags api={tagsApi} />
3505
- * </UtopiaMap>
3506
- * ```
3507
- * @category Map
3508
- */
3509
- function Tags({ data, api }) {
3510
- const setTagData = useSetTagData();
3511
- const setTagApi = useSetTagApi();
3512
- useEffect(() => {
3513
- data && setTagData(data);
3514
- api && setTagApi(api);
3515
- // eslint-disable-next-line react-hooks/exhaustive-deps
3516
- }, [api, data]);
3517
- const location = useLocation();
3518
- const addFilterTag = useAddFilterTag();
3519
- const resetFilterTags = useResetFilterTags();
3520
- const tags = useTags();
3521
- const filterTags = useFilterTags();
3522
- useEffect(() => {
3523
- const params = new URLSearchParams(location.search);
3524
- const urlTags = params.get('tags');
3525
- const decodedTags = urlTags ? decodeURIComponent(urlTags) : '';
3526
- const decodedTagsArray = decodedTags.split(';');
3527
- if (decodedTagsArray.some((ut) => !filterTags.find((ft) => ut.toLocaleLowerCase() === ft.name.toLocaleLowerCase())) ||
3528
- filterTags.some((ft) => !decodedTagsArray.find((ut) => ut.toLocaleLowerCase() === ft.name.toLocaleLowerCase()))) {
3529
- resetFilterTags();
3530
- decodedTagsArray.map((urlTag) => {
3531
- const tag = tags.find((t) => t.name.toLocaleLowerCase() === urlTag.toLocaleLowerCase());
3532
- tag && addFilterTag(tag);
3025
+ const tags = useTags();
3026
+ const filterTags = useFilterTags();
3027
+ useEffect(() => {
3028
+ const params = new URLSearchParams(location.search);
3029
+ const urlTags = params.get('tags');
3030
+ const decodedTags = urlTags ? decodeURIComponent(urlTags) : '';
3031
+ const decodedTagsArray = decodedTags.split(';');
3032
+ if (decodedTagsArray.some((ut) => !filterTags.find((ft) => ut.toLocaleLowerCase() === ft.name.toLocaleLowerCase())) ||
3033
+ filterTags.some((ft) => !decodedTagsArray.find((ut) => ut.toLocaleLowerCase() === ft.name.toLocaleLowerCase()))) {
3034
+ resetFilterTags();
3035
+ decodedTagsArray.map((urlTag) => {
3036
+ const tag = tags.find((t) => t.name.toLocaleLowerCase() === urlTag.toLocaleLowerCase());
3037
+ tag && addFilterTag(tag);
3533
3038
  return null;
3534
3039
  });
3535
3040
  }
@@ -3569,110 +3074,13 @@ function Permissions({ data, api, adminRole, }) {
3569
3074
  const setAdminRole = useSetAdminRole();
3570
3075
  const { user } = useAuth();
3571
3076
  useEffect(() => {
3572
- adminRole && setAdminRole(adminRole);
3573
- data && setPermissionData(data);
3574
- api && setPermissionApi(api);
3575
- // eslint-disable-next-line react-hooks/exhaustive-deps
3576
- }, [api, data, adminRole, user]);
3577
- return jsx(Fragment, {});
3578
- }
3579
-
3580
- /**
3581
- * @category Map
3582
- */
3583
- const ItemForm = ({ children, item, title, setPopupTitle, }) => {
3584
- useEffect(() => {
3585
- setPopupTitle && title && setPopupTitle(title);
3586
- // eslint-disable-next-line react-hooks/exhaustive-deps
3587
- }, [title]);
3588
- return (jsx("div", { children: children
3589
- ? Children.toArray(children).map((child) => isValidElement(child)
3590
- ? cloneElement(child, { item, test: 'test' })
3591
- : '')
3592
- : '' }));
3593
- };
3594
- ItemForm.__TYPE = 'ItemForm';
3595
-
3596
- /**
3597
- * @category Map
3598
- */
3599
- const ItemView = ({ children, item }) => {
3600
- return (jsx("div", { children: children
3601
- ? Children.toArray(children).map((child) => isValidElement(child) ? cloneElement(child, { item }) : null)
3602
- : null }));
3603
- };
3604
- ItemView.__TYPE = 'ItemView';
3605
-
3606
- /**
3607
- * @category Map
3608
- */
3609
- const PopupTextAreaInput = ({ dataField, placeholder, style, item, }) => {
3610
- return (jsx(TextAreaInput, { defaultValue: item?.text ? item.text : '', dataField: dataField, placeholder: placeholder, inputStyle: style }));
3611
- };
3612
-
3613
- /**
3614
- * @category Map
3615
- */
3616
- const PopupStartEndInput = ({ item, showLabels = true, updateStartValue, updateEndValue, }) => {
3617
- return (jsxs("div", { className: 'tw:grid tw:grid-cols-2 tw:gap-2', children: [jsx(TextInput, { type: 'date', placeholder: 'start', dataField: 'start', inputStyle: 'tw:text-sm tw:px-2', labelTitle: showLabels ? 'start' : '', defaultValue: item && item.start ? item.start.substring(0, 10) : '', autocomplete: 'one-time-code', updateFormValue: updateStartValue }), jsx(TextInput, { type: 'date', placeholder: 'end', dataField: 'end', inputStyle: 'tw:text-sm tw:px-2', labelTitle: showLabels ? 'end' : '', defaultValue: item && item.end ? item.end.substring(0, 10) : '', autocomplete: 'one-time-code', updateFormValue: updateEndValue })] }));
3618
- };
3619
-
3620
- /**
3621
- * @category Map
3622
- */
3623
- const PopupTextInput = ({ dataField, placeholder, style, item, }) => {
3624
- return (jsx(TextInput, { defaultValue: item?.name ? item.name : '', dataField: dataField, placeholder: placeholder, inputStyle: style, type: 'text', containerStyle: 'tw:mt-4' }));
3625
- };
3626
-
3627
- /**
3628
- * @category Map
3629
- */
3630
- const PopupCheckboxInput = ({ dataField, label, item, }) => {
3631
- return (jsxs("label", { htmlFor: item?.id, className: 'tw:label tw:justify-normal tw:pt-1 tw:pb-1', children: [jsx("input", { id: item?.id, type: 'checkbox', name: dataField, className: 'tw:checkbox tw:checkbox-xs tw:checkbox-success', checked: item?.public_edit }), jsx("span", { className: 'tw:text-sm tw:label-text tw:mx-2 tw:cursor-pointer', children: label })] }));
3632
- };
3633
-
3634
- function CalendarDaysIcon({
3635
- title,
3636
- titleId,
3637
- ...props
3638
- }, svgRef) {
3639
- return /*#__PURE__*/React.createElement("svg", Object.assign({
3640
- xmlns: "http://www.w3.org/2000/svg",
3641
- viewBox: "0 0 24 24",
3642
- fill: "currentColor",
3643
- "aria-hidden": "true",
3644
- "data-slot": "icon",
3645
- ref: svgRef,
3646
- "aria-labelledby": titleId
3647
- }, props), title ? /*#__PURE__*/React.createElement("title", {
3648
- id: titleId
3649
- }, title) : null, /*#__PURE__*/React.createElement("path", {
3650
- d: "M12.75 12.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM7.5 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM8.25 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM9.75 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM10.5 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM12 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM12.75 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM14.25 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM15 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM16.5 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM15 12.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM16.5 13.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z"
3651
- }), /*#__PURE__*/React.createElement("path", {
3652
- fillRule: "evenodd",
3653
- d: "M6.75 2.25A.75.75 0 0 1 7.5 3v1.5h9V3A.75.75 0 0 1 18 3v1.5h.75a3 3 0 0 1 3 3v11.25a3 3 0 0 1-3 3H5.25a3 3 0 0 1-3-3V7.5a3 3 0 0 1 3-3H6V3a.75.75 0 0 1 .75-.75Zm13.5 9a1.5 1.5 0 0 0-1.5-1.5H5.25a1.5 1.5 0 0 0-1.5 1.5v7.5a1.5 1.5 0 0 0 1.5 1.5h13.5a1.5 1.5 0 0 0 1.5-1.5v-7.5Z",
3654
- clipRule: "evenodd"
3655
- }));
3656
- }
3657
- const ForwardRef$6 = /*#__PURE__*/ React.forwardRef(CalendarDaysIcon);
3658
-
3659
- /**
3660
- * @category Map
3661
- */
3662
- const StartEndView = ({ item }) => {
3663
- return (jsxs("div", { className: 'tw:flex tw:flex-row tw:mb-4 tw:mt-1', children: [jsxs("div", { className: 'tw:basis-2/5 tw:flex tw:flex-row', children: [jsx(ForwardRef$6, { className: 'tw:h-4 tw:w-4 tw:mr-2' }), jsx("time", { className: 'tw:align-middle', dateTime: item && item.start ? item.start.substring(0, 10) : '', children: item && item.start ? new Date(item.start).toLocaleDateString() : '' })] }), jsx("div", { className: 'tw:basis-1/5 tw:place-content-center', children: jsx("span", { children: "-" }) }), jsxs("div", { className: 'tw:basis-2/5 tw:flex tw:flex-row', children: [jsx(ForwardRef$6, { className: 'tw:h-4 tw:w-4 tw:mr-2' }), jsx("time", { className: 'tw:align-middle', dateTime: item && item.end ? item.end.substring(0, 10) : '', children: item && item.end ? new Date(item.end).toLocaleDateString() : '' })] })] }));
3664
- };
3665
-
3666
- /**
3667
- * @category Map
3668
- */
3669
- const PopupButton = ({ url, parameterField, text, item, }) => {
3670
- const params = new URLSearchParams(window.location.search);
3671
- const getItemTags = useGetItemTags();
3672
- return (jsx(Link, { to: `${url}/${parameterField ? item?.id : ''}?${params}`, children: jsx("button", { style: {
3673
- backgroundColor: `${item?.color ?? (item && (getItemTags(item) && getItemTags(item)[0] && getItemTags(item)[0].color ? getItemTags(item)[0].color : (item?.layer?.markerDefaultColor ?? '#000')))}`,
3674
- }, className: 'tw:btn tw:text-white tw:btn-sm tw:float-right tw:mt-1', children: text }) }));
3675
- };
3077
+ adminRole && setAdminRole(adminRole);
3078
+ data && setPermissionData(data);
3079
+ api && setPermissionApi(api);
3080
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3081
+ }, [api, data, adminRole, user]);
3082
+ return jsx(Fragment, {});
3083
+ }
3676
3084
 
3677
3085
  const themes = [
3678
3086
  'default',
@@ -3702,6 +3110,27 @@ const ThemeControl = () => {
3702
3110
  return (jsxs("div", { className: 'tw:dropdown tw:mr-2', children: [jsxs("div", { tabIndex: 0, role: 'button', className: 'tw:btn tw:m-1', children: ["Theme", jsx("svg", { width: '12px', height: '12px', className: 'tw:inline-block tw:h-2 tw:w-2 tw:fill-current tw:opacity-60', xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 2048 2048', children: jsx("path", { d: 'M1799 349l242 241-1017 1017L7 590l242-241 775 775 775-775z' }) })] }), jsx("ul", { tabIndex: 0, className: 'tw:dropdown-content tw:bg-base-200 tw:rounded-box tw:z-1 tw:w-36 tw:p-2 tw:shadow-2xl', children: themes.map((t) => (jsx("li", { children: jsx("input", { className: `tw:btn ${theme === t ? 'tw:bg-base-300' : ''} tw:btn-sm tw:btn-block tw:btn-ghost tw:justify-start`, type: 'radio', name: 'theme', value: t, checked: theme === t, onChange: () => setTheme(t), "aria-label": t.toLowerCase() }) }, t))) })] }));
3703
3111
  };
3704
3112
 
3113
+ function EllipsisVerticalIcon({
3114
+ title,
3115
+ titleId,
3116
+ ...props
3117
+ }, svgRef) {
3118
+ return /*#__PURE__*/React.createElement("svg", Object.assign({
3119
+ xmlns: "http://www.w3.org/2000/svg",
3120
+ viewBox: "0 0 16 16",
3121
+ fill: "currentColor",
3122
+ "aria-hidden": "true",
3123
+ "data-slot": "icon",
3124
+ ref: svgRef,
3125
+ "aria-labelledby": titleId
3126
+ }, props), title ? /*#__PURE__*/React.createElement("title", {
3127
+ id: titleId
3128
+ }, title) : null, /*#__PURE__*/React.createElement("path", {
3129
+ d: "M8 2a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM8 6.5a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM9.5 12.5a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0Z"
3130
+ }));
3131
+ }
3132
+ const ForwardRef$9 = /*#__PURE__*/ React.forwardRef(EllipsisVerticalIcon);
3133
+
3705
3134
  const UserControl = () => {
3706
3135
  const { isAuthenticated, user, logout } = useAuth();
3707
3136
  const appState = useAppState();
@@ -4019,6 +3448,43 @@ function SetNewPasswordPage() {
4019
3448
  onClick: () => onReset(), children: loading ? jsx("span", { className: 'tw:loading tw:loading-spinner' }) : 'Set' }) })] }));
4020
3449
  }
4021
3450
 
3451
+ /**
3452
+ * @category Input
3453
+ */
3454
+ function TextAreaInput({ labelTitle, dataField, labelStyle, containerStyle, inputStyle, defaultValue, placeholder, required = true, updateFormValue, }) {
3455
+ const ref = useRef(null);
3456
+ const [inputValue, setInputValue] = useState(defaultValue);
3457
+ useEffect(() => {
3458
+ setInputValue(defaultValue);
3459
+ }, [defaultValue]);
3460
+ const handleChange = (e) => {
3461
+ const newValue = e.target.value;
3462
+ setInputValue(newValue);
3463
+ if (updateFormValue) {
3464
+ updateFormValue(newValue);
3465
+ }
3466
+ };
3467
+ return (jsxs("div", { className: `tw:form-control tw:w-full ${containerStyle ?? ''}`, children: [labelTitle ? (jsx("label", { className: 'tw:label', children: jsx("span", { className: `tw:label-text tw:text-base-content ${labelStyle ?? ''}`, children: labelTitle }) })) : null, jsx("textarea", { required: required, ref: ref, value: inputValue, name: dataField, className: `tw:textarea tw:textarea-bordered tw:w-full tw:leading-5 ${inputStyle ?? ''}`, placeholder: placeholder ?? '', onChange: handleChange })] }));
3468
+ }
3469
+
3470
+ /**
3471
+ * @category Input
3472
+ */
3473
+ function TextInput({ labelTitle, labelStyle, type, dataField, containerStyle, inputStyle, defaultValue, placeholder, autocomplete, pattern, required = true, updateFormValue, }) {
3474
+ const [inputValue, setInputValue] = useState(defaultValue ?? '');
3475
+ useEffect(() => {
3476
+ setInputValue(defaultValue ?? '');
3477
+ }, [defaultValue]);
3478
+ const handleChange = (e) => {
3479
+ const newValue = e.target.value;
3480
+ setInputValue(newValue);
3481
+ if (updateFormValue) {
3482
+ updateFormValue(newValue);
3483
+ }
3484
+ };
3485
+ return (jsxs("div", { className: `tw:form-control ${containerStyle ?? ''}`, children: [labelTitle ? (jsx("label", { className: 'tw:label', children: jsx("span", { className: `tw:label-text tw:text-base-content ${labelStyle ?? ''}`, children: labelTitle }) })) : null, jsx("input", { required: required, pattern: pattern, type: type ?? 'text', name: dataField, value: inputValue, placeholder: placeholder ?? '', autoComplete: autocomplete, onChange: handleChange, className: `tw:input tw:input-bordered tw:w-full ${inputStyle ?? ''}` })] }));
3486
+ }
3487
+
4022
3488
  function Subtitle({ styleClass, children }) {
4023
3489
  return jsx("div", { className: `tw:text-xl tw:font-semibold ${styleClass}`, children: children });
4024
3490
  }
@@ -4053,6 +3519,77 @@ const SelectUser = () => {
4053
3519
  }) }) }) }), jsx("div", { className: 'tw:w-full tw:grid tw:mt-4', children: jsx(Link, { className: 'tw:place-self-center ', to: '/attestation-form' + '?to=' + selectedUsers.map((u) => u, ','), children: jsx("button", { className: 'tw:btn tw:px-8', children: "Next" }) }) })] }));
4054
3520
  };
4055
3521
 
3522
+ /**
3523
+ * @category Map
3524
+ */
3525
+ const PopupTextAreaInput$1 = ({ dataField, placeholder, style, item, }) => {
3526
+ return (jsx(TextAreaInput, { defaultValue: item?.text ? item.text : '', dataField: dataField, placeholder: placeholder, inputStyle: style }));
3527
+ };
3528
+
3529
+ /**
3530
+ * @category Map
3531
+ */
3532
+ const PopupStartEndInput$1 = ({ item, showLabels = true, updateStartValue, updateEndValue, }) => {
3533
+ return (jsxs("div", { className: 'tw:grid tw:grid-cols-2 tw:gap-2', children: [jsx(TextInput, { type: 'date', placeholder: 'start', dataField: 'start', inputStyle: 'tw:text-sm tw:px-2', labelTitle: showLabels ? 'start' : '', defaultValue: item && item.start ? item.start.substring(0, 10) : '', autocomplete: 'one-time-code', updateFormValue: updateStartValue }), jsx(TextInput, { type: 'date', placeholder: 'end', dataField: 'end', inputStyle: 'tw:text-sm tw:px-2', labelTitle: showLabels ? 'end' : '', defaultValue: item && item.end ? item.end.substring(0, 10) : '', autocomplete: 'one-time-code', updateFormValue: updateEndValue })] }));
3534
+ };
3535
+
3536
+ /**
3537
+ * @category Map
3538
+ */
3539
+ const PopupTextInput$1 = ({ dataField, placeholder, style, item, }) => {
3540
+ return (jsx(TextInput, { defaultValue: item?.name ? item.name : '', dataField: dataField, placeholder: placeholder, inputStyle: style, type: 'text', containerStyle: 'tw:mt-4' }));
3541
+ };
3542
+
3543
+ /**
3544
+ * @category Map
3545
+ */
3546
+ const PopupCheckboxInput$1 = ({ dataField, label, item, }) => {
3547
+ return (jsxs("label", { htmlFor: item?.id, className: 'tw:label tw:justify-normal tw:pt-1 tw:pb-1', children: [jsx("input", { id: item?.id, type: 'checkbox', name: dataField, className: 'tw:checkbox tw:checkbox-xs tw:checkbox-success', checked: item?.public_edit }), jsx("span", { className: 'tw:text-sm tw:label-text tw:mx-2 tw:cursor-pointer', children: label })] }));
3548
+ };
3549
+
3550
+ function CalendarDaysIcon({
3551
+ title,
3552
+ titleId,
3553
+ ...props
3554
+ }, svgRef) {
3555
+ return /*#__PURE__*/React.createElement("svg", Object.assign({
3556
+ xmlns: "http://www.w3.org/2000/svg",
3557
+ viewBox: "0 0 24 24",
3558
+ fill: "currentColor",
3559
+ "aria-hidden": "true",
3560
+ "data-slot": "icon",
3561
+ ref: svgRef,
3562
+ "aria-labelledby": titleId
3563
+ }, props), title ? /*#__PURE__*/React.createElement("title", {
3564
+ id: titleId
3565
+ }, title) : null, /*#__PURE__*/React.createElement("path", {
3566
+ d: "M12.75 12.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM7.5 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM8.25 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM9.75 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM10.5 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM12 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM12.75 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM14.25 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM15 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM16.5 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM15 12.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM16.5 13.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z"
3567
+ }), /*#__PURE__*/React.createElement("path", {
3568
+ fillRule: "evenodd",
3569
+ d: "M6.75 2.25A.75.75 0 0 1 7.5 3v1.5h9V3A.75.75 0 0 1 18 3v1.5h.75a3 3 0 0 1 3 3v11.25a3 3 0 0 1-3 3H5.25a3 3 0 0 1-3-3V7.5a3 3 0 0 1 3-3H6V3a.75.75 0 0 1 .75-.75Zm13.5 9a1.5 1.5 0 0 0-1.5-1.5H5.25a1.5 1.5 0 0 0-1.5 1.5v7.5a1.5 1.5 0 0 0 1.5 1.5h13.5a1.5 1.5 0 0 0 1.5-1.5v-7.5Z",
3570
+ clipRule: "evenodd"
3571
+ }));
3572
+ }
3573
+ const ForwardRef$8 = /*#__PURE__*/ React.forwardRef(CalendarDaysIcon);
3574
+
3575
+ /**
3576
+ * @category Map
3577
+ */
3578
+ const StartEndView$1 = ({ item }) => {
3579
+ return (jsxs("div", { className: 'tw:flex tw:flex-row tw:mb-4 tw:mt-1', children: [jsxs("div", { className: 'tw:basis-2/5 tw:flex tw:flex-row', children: [jsx(ForwardRef$8, { className: 'tw:h-4 tw:w-4 tw:mr-2' }), jsx("time", { className: 'tw:align-middle', dateTime: item && item.start ? item.start.substring(0, 10) : '', children: item && item.start ? new Date(item.start).toLocaleDateString() : '' })] }), jsx("div", { className: 'tw:basis-1/5 tw:place-content-center', children: jsx("span", { children: "-" }) }), jsxs("div", { className: 'tw:basis-2/5 tw:flex tw:flex-row', children: [jsx(ForwardRef$8, { className: 'tw:h-4 tw:w-4 tw:mr-2' }), jsx("time", { className: 'tw:align-middle', dateTime: item && item.end ? item.end.substring(0, 10) : '', children: item && item.end ? new Date(item.end).toLocaleDateString() : '' })] })] }));
3580
+ };
3581
+
3582
+ /**
3583
+ * @category Map
3584
+ */
3585
+ const PopupButton$1 = ({ url, parameterField, text, item, }) => {
3586
+ const params = new URLSearchParams(window.location.search);
3587
+ const getItemTags = useGetItemTags();
3588
+ return (jsx(Link, { to: `${url}/${parameterField ? item?.id : ''}?${params}`, children: jsx("button", { style: {
3589
+ backgroundColor: `${item?.color ?? (item && (getItemTags(item) && getItemTags(item)[0] && getItemTags(item)[0].color ? getItemTags(item)[0].color : (item?.layer?.markerDefaultColor ?? '#000')))}`,
3590
+ }, className: 'tw:btn tw:text-white tw:btn-sm tw:float-right tw:mt-1', children: text }) }));
3591
+ };
3592
+
4056
3593
  function PlusIcon({
4057
3594
  title,
4058
3595
  titleId,
@@ -4076,15 +3613,203 @@ function PlusIcon({
4076
3613
  d: "M12 4.5v15m7.5-7.5h-15"
4077
3614
  }));
4078
3615
  }
4079
- const ForwardRef$5 = /*#__PURE__*/ React.forwardRef(PlusIcon);
3616
+ const ForwardRef$7 = /*#__PURE__*/ React.forwardRef(PlusIcon);
4080
3617
 
4081
3618
  function PlusButton({ layer, triggerAction, color, collection = 'items', }) {
4082
3619
  const hasUserPermission = useHasUserPermission();
4083
- return (jsx(Fragment, { children: hasUserPermission(collection, 'create', undefined, layer) && (jsx("div", { className: 'tw:dropdown tw:dropdown-top tw:dropdown-end tw:dropdown-hover tw:z-3000 tw:absolute tw:right-4 tw:bottom-4', children: jsx("button", { tabIndex: 0, className: 'tw:z-500 tw:btn tw:btn-circle tw:shadow', onClick: () => {
4084
- triggerAction();
4085
- }, style: { backgroundColor: color, color: '#fff' }, children: jsx(ForwardRef$5, { className: 'tw:w-5 tw:h-5 tw:stroke-[2.5]' }) }) })) }));
3620
+ return (jsx(Fragment, { children: hasUserPermission(collection, 'create', undefined, layer) && (jsx("div", { className: 'tw:dropdown tw:dropdown-top tw:dropdown-end tw:dropdown-hover tw:z-3000 tw:absolute tw:right-4 tw:bottom-4', children: jsx("button", { tabIndex: 0, className: 'tw:z-500 tw:btn tw:btn-circle tw:shadow', onClick: () => {
3621
+ triggerAction();
3622
+ }, style: { backgroundColor: color, color: '#fff' }, children: jsx(ForwardRef$7, { className: 'tw:w-5 tw:h-5 tw:stroke-[2.5]' }) }) })) }));
3623
+ }
3624
+
3625
+ const goldenRatioConjugate = 0.618033988749895;
3626
+ const randomColor = () => {
3627
+ return hsvToHex((Math.random() + goldenRatioConjugate) % 1, 0.8, 0.7);
3628
+ };
3629
+ function hsvToHex(h, s, v) {
3630
+ let r, g, b;
3631
+ const i = Math.floor(h * 6);
3632
+ const f = h * 6 - i;
3633
+ const p = v * (1 - s);
3634
+ const q = v * (1 - f * s);
3635
+ const t = v * (1 - (1 - f) * s);
3636
+ switch (i % 6) {
3637
+ case 0:
3638
+ r = v;
3639
+ g = t;
3640
+ b = p;
3641
+ break;
3642
+ case 1:
3643
+ r = q;
3644
+ g = v;
3645
+ b = p;
3646
+ break;
3647
+ case 2:
3648
+ r = p;
3649
+ g = v;
3650
+ b = t;
3651
+ break;
3652
+ case 3:
3653
+ r = p;
3654
+ g = q;
3655
+ b = v;
3656
+ break;
3657
+ case 4:
3658
+ r = t;
3659
+ g = p;
3660
+ b = v;
3661
+ break;
3662
+ case 5:
3663
+ r = v;
3664
+ g = p;
3665
+ b = q;
3666
+ break;
3667
+ }
3668
+ return rgbToHex(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
3669
+ }
3670
+ const rgbToHex = (r, g, b) => '#' +
3671
+ [r, g, b]
3672
+ .map((x) => {
3673
+ const hex = x.toString(16);
3674
+ return hex.length === 1 ? `0${hex}` : hex;
3675
+ })
3676
+ .join('');
3677
+
3678
+ function PencilIcon({
3679
+ title,
3680
+ titleId,
3681
+ ...props
3682
+ }, svgRef) {
3683
+ return /*#__PURE__*/React.createElement("svg", Object.assign({
3684
+ xmlns: "http://www.w3.org/2000/svg",
3685
+ viewBox: "0 0 24 24",
3686
+ fill: "currentColor",
3687
+ "aria-hidden": "true",
3688
+ "data-slot": "icon",
3689
+ ref: svgRef,
3690
+ "aria-labelledby": titleId
3691
+ }, props), title ? /*#__PURE__*/React.createElement("title", {
3692
+ id: titleId
3693
+ }, title) : null, /*#__PURE__*/React.createElement("path", {
3694
+ d: "M21.731 2.269a2.625 2.625 0 0 0-3.712 0l-1.157 1.157 3.712 3.712 1.157-1.157a2.625 2.625 0 0 0 0-3.712ZM19.513 8.199l-3.712-3.712-12.15 12.15a5.25 5.25 0 0 0-1.32 2.214l-.8 2.685a.75.75 0 0 0 .933.933l2.685-.8a5.25 5.25 0 0 0 2.214-1.32L19.513 8.2Z"
3695
+ }));
3696
+ }
3697
+ const ForwardRef$6 = /*#__PURE__*/ React.forwardRef(PencilIcon);
3698
+
3699
+ function TrashIcon({
3700
+ title,
3701
+ titleId,
3702
+ ...props
3703
+ }, svgRef) {
3704
+ return /*#__PURE__*/React.createElement("svg", Object.assign({
3705
+ xmlns: "http://www.w3.org/2000/svg",
3706
+ viewBox: "0 0 24 24",
3707
+ fill: "currentColor",
3708
+ "aria-hidden": "true",
3709
+ "data-slot": "icon",
3710
+ ref: svgRef,
3711
+ "aria-labelledby": titleId
3712
+ }, props), title ? /*#__PURE__*/React.createElement("title", {
3713
+ id: titleId
3714
+ }, title) : null, /*#__PURE__*/React.createElement("path", {
3715
+ fillRule: "evenodd",
3716
+ d: "M16.5 4.478v.227a48.816 48.816 0 0 1 3.878.512.75.75 0 1 1-.256 1.478l-.209-.035-1.005 13.07a3 3 0 0 1-2.991 2.77H8.084a3 3 0 0 1-2.991-2.77L4.087 6.66l-.209.035a.75.75 0 0 1-.256-1.478A48.567 48.567 0 0 1 7.5 4.705v-.227c0-1.564 1.213-2.9 2.816-2.951a52.662 52.662 0 0 1 3.369 0c1.603.051 2.815 1.387 2.815 2.951Zm-6.136-1.452a51.196 51.196 0 0 1 3.273 0C14.39 3.05 15 3.684 15 4.478v.113a49.488 49.488 0 0 0-6 0v-.113c0-.794.609-1.428 1.364-1.452Zm-.355 5.945a.75.75 0 1 0-1.5.058l.347 9a.75.75 0 1 0 1.499-.058l-.346-9Zm5.48.058a.75.75 0 1 0-1.498-.058l-.347 9a.75.75 0 0 0 1.5.058l.345-9Z",
3717
+ clipRule: "evenodd"
3718
+ }));
3719
+ }
3720
+ const ForwardRef$5 = /*#__PURE__*/ React.forwardRef(TrashIcon);
3721
+
3722
+ var TargetDotSVG = 'data:image/svg+xml;base64,PHN2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlPSdjdXJyZW50Q29sb3InCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPSdjdXJyZW50Q29sb3InCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2VXaWR0aD0nMCcKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdCb3g9JzAgMCA1MTIgNTEyJwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPSd3LTUgaC01JwogICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJwogICAgICAgICAgICAgICAgICAgICAgICAgID4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9J00yNTYgMGMxNy43IDAgMzIgMTQuMyAzMiAzMlY0Mi40YzkzLjcgMTMuOSAxNjcuNyA4OCAxODEuNiAxODEuNkg0ODBjMTcuNyAwIDMyIDE0LjMgMzIgMzJzLTE0LjMgMzItMzIgMzJINDY5LjZjLTEzLjkgOTMuNy04OCAxNjcuNy0xODEuNiAxODEuNlY0ODBjMCAxNy43LTE0LjMgMzItMzIgMzJzLTMyLTE0LjMtMzItMzJWNDY5LjZDMTMwLjMgNDU1LjcgNTYuMyAzODEuNyA0Mi40IDI4OEgzMmMtMTcuNyAwLTMyLTE0LjMtMzItMzJzMTQuMy0zMiAzMi0zMkg0Mi40QzU2LjMgMTMwLjMgMTMwLjMgNTYuMyAyMjQgNDIuNFYzMmMwLTE3LjcgMTQuMy0zMiAzMi0zMnpNMTA3LjQgMjg4YzEyLjUgNTguMyA1OC40IDEwNC4xIDExNi42IDExNi42VjM4NGMwLTE3LjcgMTQuMy0zMiAzMi0zMnMzMiAxNC4zIDMyIDMydjIwLjZjNTguMy0xMi41IDEwNC4xLTU4LjQgMTE2LjYtMTE2LjZIMzg0Yy0xNy43IDAtMzItMTQuMy0zMi0zMnMxNC4zLTMyIDMyLTMyaDIwLjZDMzkyLjEgMTY1LjcgMzQ2LjMgMTE5LjkgMjg4IDEwNy40VjEyOGMwIDE3LjctMTQuMyAzMi0zMiAzMnMtMzItMTQuMy0zMi0zMlYxMDcuNEMxNjUuNyAxMTkuOSAxMTkuOSAxNjUuNyAxMDcuNCAyMjRIMTI4YzE3LjcgMCAzMiAxNC4zIDMyIDMycy0xNC4zIDMyLTMyIDMySDEwNy40ek0yNTYgMjI0YTMyIDMyIDAgMSAxIDAgNjQgMzIgMzIgMCAxIDEgMC02NHonPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz4=';
3723
+
3724
+ const isClickInsideRectangle = (e, element) => {
3725
+ const r = element.getBoundingClientRect();
3726
+ return e.clientX > r.left && e.clientX < r.right && e.clientY > r.top && e.clientY < r.bottom;
3727
+ };
3728
+ const DialogModal = ({ title, isOpened, onClose, children, showCloseButton = true, closeOnClickOutside = true, className, }) => {
3729
+ const ref = useRef(null);
3730
+ useEffect(() => {
3731
+ if (isOpened) {
3732
+ ref.current?.showModal();
3733
+ ref.current?.classList.remove('tw:hidden');
3734
+ document.body.classList.add('modal-open'); // prevent bg scroll
3735
+ }
3736
+ else {
3737
+ ref.current?.close();
3738
+ ref.current?.classList.add('tw:hidden');
3739
+ document.body.classList.remove('modal-open');
3740
+ }
3741
+ }, [isOpened]);
3742
+ if (isOpened) {
3743
+ return (jsx("dialog", { className: `${className ?? ''} card tw:shadow-xl tw:absolute tw:right-0 tw:top-0 tw:bottom-0 tw:left-0 tw:m-auto tw:transition-opacity tw:duration-300 tw:p-4 tw:max-w-xl tw:bg-base-100`, ref: ref, onCancel: onClose, onClick: (e) => ref.current && !isClickInsideRectangle(e, ref.current) && closeOnClickOutside && onClose(), children: jsxs("div", { className: 'card-body tw:p-2', children: [jsx("h2", { className: 'tw:text-2xl tw:font-semibold tw:mb-2 tw:text-center', children: title }), children, showCloseButton && (jsx("button", { className: 'btn btn-sm btn-circle btn-ghost tw:absolute tw:right-2 tw:top-2', onClick: onClose, children: "\u2715" }))] }) }));
3744
+ }
3745
+ else
3746
+ return jsx(Fragment, {});
3747
+ };
3748
+
3749
+ function HeaderView({ item, api, editCallback, deleteCallback, setPositionCallback, loading, hideMenu = false, big = false, truncateSubname = true, hideSubname = false, showAddress = false, }) {
3750
+ const [modalOpen, setModalOpen] = useState(false);
3751
+ const hasUserPermission = useHasUserPermission();
3752
+ const navigate = useNavigate();
3753
+ const appState = useAppState();
3754
+ const [imageLoaded, setImageLoaded] = useState(false);
3755
+ const avatar = item.image && appState.assetsApi.url + item.image + '?width=160&heigth=160';
3756
+ const title = item.name;
3757
+ const subtitle = item.subname;
3758
+ const [address] = useState('');
3759
+ const params = new URLSearchParams(window.location.search);
3760
+ const openDeleteModal = async (event) => {
3761
+ setModalOpen(true);
3762
+ event.stopPropagation();
3763
+ };
3764
+ return (jsxs(Fragment, { children: [jsxs("div", { className: 'tw:flex tw:flex-row', children: [jsx("div", { className: 'tw:grow tw:max-w-[calc(100%-60px)] }', children: jsxs("div", { className: 'flex items-center', children: [avatar && (jsx("div", { className: 'tw:avatar', children: jsxs("div", { className: `${big ? 'tw:w-20' : 'tw:w-10'} tw:inline tw:items-center tw:justify-center overflow-hidden`, children: [jsx("img", { className: 'tw:w-full tw:h-full tw:object-cover tw:rounded-full', src: avatar, alt: item.name + ' logo', onLoad: () => setImageLoaded(true), onError: () => setImageLoaded(false), style: { display: imageLoaded ? 'block' : 'none' } }), !imageLoaded && (jsx("div", { className: 'tw:w-full tw:h-full tw:bg-gray-200 tw:rounded-full' }))] }) })), jsxs("div", { className: `${avatar ? 'tw:ml-2' : ''} tw:overflow-hidden`, children: [jsx("div", { className: `${big ? 'tw:xl:text-3xl tw:text-2xl' : 'tw:text-xl'} tw:font-semibold tw:truncate`, title: title, children: title }), showAddress && address && !hideSubname && (jsx("div", { className: `tw:text-xs tw:text-gray-500 ${truncateSubname && 'tw:truncate'}`, children: address })), subtitle && !hideSubname && (jsx("div", { className: `tw:text-xs tw:opacity-50 ${truncateSubname && 'tw:truncate'}`, children: subtitle }))] })] }) }), jsx("div", { onClick: (e) => e.stopPropagation(), className: `${big ? 'tw:mt-5' : 'tw:mt-1'}`, children: (api?.deleteItem || item.layer?.api?.updateItem) &&
3765
+ (hasUserPermission(api?.collectionName, 'delete', item) ||
3766
+ hasUserPermission(api?.collectionName, 'update', item)) &&
3767
+ !hideMenu && (jsxs("div", { className: 'tw:dropdown tw:dropdown-bottom', children: [jsx("label", { tabIndex: 0, className: 'tw:bg-base-100 tw:btn tw:m-1 tw:leading-3 tw:border-none tw:min-h-0 tw:h-6', children: jsx(ForwardRef$9, { className: 'tw:h-5 tw:w-5' }) }), jsxs("ul", { tabIndex: 0, className: 'tw:dropdown-content tw:menu tw:p-2 tw:shadow tw:bg-base-100 tw:rounded-box tw:z-1000', children: [api?.updateItem &&
3768
+ hasUserPermission(api.collectionName, 'update', item) &&
3769
+ editCallback && (jsx("li", { children: jsx("a", { className: 'tw:text-base-content! tw:cursor-pointer', onClick: (e) => item.layer?.customEditLink
3770
+ ? navigate(`${item.layer.customEditLink}${item.layer.customEditParameter ? `/${item.id}${params && '?' + params}` : ''} `)
3771
+ : editCallback(e), children: jsx(ForwardRef$6, { className: 'tw:h-5 tw:w-5' }) }) })), api?.updateItem &&
3772
+ hasUserPermission(api.collectionName, 'update', item) &&
3773
+ setPositionCallback && (jsx("li", { children: jsx("a", { className: 'tw:text-base-content! tw:cursor-pointer', onClick: setPositionCallback, children: jsx(SVG, { src: TargetDotSVG, className: 'tw:w-5 tw:h-5' }) }) })), api?.deleteItem &&
3774
+ hasUserPermission(api.collectionName, 'delete', item) &&
3775
+ deleteCallback && (jsx("li", { children: jsx("a", { className: 'tw:cursor-pointer tw:text-error!', onClick: openDeleteModal, children: loading ? (jsx("span", { className: 'tw:loading tw:loading-spinner tw:loading-sm' })) : (jsx(ForwardRef$5, { className: 'tw:h-5 tw:w-5' })) }) }))] })] })) })] }), jsx(DialogModal, { isOpened: modalOpen, title: 'Are you sure?', showCloseButton: false, onClose: () => setModalOpen(false), children: jsxs("div", { onClick: (e) => e.stopPropagation(), children: [jsxs("span", { children: ["Do you want to delete ", jsx("b", { children: item.name }), "?"] }), jsx("div", { className: 'tw:grid', children: jsxs("div", { className: 'tw:flex tw:justify-between', children: [jsx("label", { className: 'tw:btn tw:mt-4 tw:btn-error', onClick: (e) => {
3776
+ deleteCallback(e);
3777
+ setModalOpen(false);
3778
+ }, children: "Yes" }), jsx("label", { className: 'tw:btn tw:mt-4', onClick: () => setModalOpen(false), children: "No" })] }) })] }) })] }));
4086
3779
  }
4087
3780
 
3781
+ // in miliseconds
3782
+ const units = [
3783
+ { label: 'year', seconds: 31536000 },
3784
+ { label: 'month', seconds: 2592000 },
3785
+ { label: 'week', seconds: 604800 },
3786
+ { label: 'day', seconds: 86400 },
3787
+ { label: 'hour', seconds: 3600 },
3788
+ { label: 'minute', seconds: 60 },
3789
+ { label: 'second', seconds: 1 },
3790
+ ];
3791
+ const timeAgo = (date) => {
3792
+ const time = Math.floor((new Date().valueOf() - new Date(date).valueOf()) / 1000);
3793
+ const { interval, unit } = calculateTimeDifference(time);
3794
+ const suffix = interval === 1 ? '' : 's';
3795
+ return `${interval} ${unit}${suffix} ago`;
3796
+ };
3797
+ const calculateTimeDifference = (time) => {
3798
+ for (const { label, seconds } of units) {
3799
+ const interval = Math.floor(time / seconds);
3800
+ if (interval >= 1) {
3801
+ return {
3802
+ interval,
3803
+ unit: label,
3804
+ };
3805
+ }
3806
+ }
3807
+ return {
3808
+ interval: 0,
3809
+ unit: '',
3810
+ };
3811
+ };
3812
+
4088
3813
  const DateUserInfo = ({ item }) => {
4089
3814
  const [infoExpanded, setInfoExpanded] = useState(false);
4090
3815
  return (jsxs("div", { className: 'tw:flex tw:-mb-1 tw:flex-row tw:mr-2 tw:-mt-2', onClick: (e) => e.stopPropagation(), children: [infoExpanded ? (jsx("p", { className: 'tw:italic tw:min-h-[21px] tw:my-0! tw:text-gray-500', onClick: () => setInfoExpanded(false), children: `${item.date_updated && item.date_updated !== item.date_created ? 'updated' : 'posted'} ${item.user_created?.first_name ? `by ${item.user_created.first_name}` : ''} ${item.date_updated ? timeAgo(item.date_updated) : timeAgo(item.date_created)}` })) : (jsx("p", { className: 'tw:my-0! tw:min-h-[21px] tw:font-bold tw:cursor-pointer tw:text-gray-500', onClick: () => setInfoExpanded(true), children: "\u24D8" })), jsx("div", { className: 'tw:grow ' })] }));
@@ -4100,7 +3825,7 @@ const ItemCard = ({ i, loading, url, deleteCallback, }) => {
4100
3825
  navigate('/' + i.id + `${params.size > 0 ? `?${params.toString()}` : ''}`);
4101
3826
  else
4102
3827
  navigate(url + i.id + `${params.size > 0 ? `?${params.toString()}` : ''}`);
4103
- }, children: [jsx(HeaderView, { loading: loading, item: i, api: i.layer?.api, editCallback: () => navigate('/edit-item/' + i.id), deleteCallback: () => deleteCallback(i) }), jsxs("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: [i.layer?.itemType.show_start_end && jsx(StartEndView, { item: i }), i.layer?.itemType.show_text && jsx(TextView, { truncate: true, text: i.text, itemId: i.id })] }), jsx(DateUserInfo, { item: i })] }));
3828
+ }, children: [jsx(HeaderView, { loading: loading, item: i, api: i.layer?.api, editCallback: () => navigate('/edit-item/' + i.id), deleteCallback: () => deleteCallback(i) }), jsxs("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: [i.layer?.itemType.show_start_end && jsx(StartEndView$1, { item: i }), i.layer?.itemType.show_text && jsx(TextView$1, { truncate: true, text: i.text, itemId: i.id })] }), jsx(DateUserInfo, { item: i })] }));
4104
3829
  };
4105
3830
 
4106
3831
  /**
@@ -4202,7 +3927,7 @@ const OverlayItemsIndexPage = ({ url, layerName, parameterField, plusButton = tr
4202
3927
  : 0;
4203
3928
  return dateB - dateA; // Subtracts milliseconds which are numbers
4204
3929
  })
4205
- .map((i, k) => (jsx("div", { className: 'tw:break-inside-avoid tw:mb-6', children: jsx(ItemCard, { i: i, loading: loading, url: url, deleteCallback: () => deleteItem(i) }) }, k))), addItemPopupType === 'place' && (jsx("form", { ref: tabRef, autoComplete: 'off', onSubmit: (e) => submitNewItem(e), children: jsxs("div", { className: 'tw:cursor-pointer tw:break-inside-avoid card tw:border-[1px] tw:border-base-300 card-body tw:shadow-xl tw:bg-base-100 tw:text-base-content tw:p-6 tw:mb-10', children: [jsx("label", { className: 'btn btn-sm tw:rounded-2xl btn-circle btn-ghost tw:hover:bg-transparent tw:absolute tw:right-0 tw:top-0 tw:text-gray-600', onClick: () => setAddItemPopupType(''), children: jsx("p", { className: 'tw:text-center', children: "\u2715" }) }), jsx(TextInput, { type: 'text', placeholder: 'Name', dataField: 'name', defaultValue: '', inputStyle: '' }), layer?.itemType.show_start_end_input && jsx(PopupStartEndInput, {}), jsx(TextAreaInput, { placeholder: 'Text', dataField: 'text', defaultValue: '', inputStyle: 'tw:h-40 tw:mt-5' }), jsx("div", { className: 'tw:flex tw:justify-center', children: jsx("button", { className: loading
3930
+ .map((i, k) => (jsx("div", { className: 'tw:break-inside-avoid tw:mb-6', children: jsx(ItemCard, { i: i, loading: loading, url: url, deleteCallback: () => deleteItem(i) }) }, k))), addItemPopupType === 'place' && (jsx("form", { ref: tabRef, autoComplete: 'off', onSubmit: (e) => submitNewItem(e), children: jsxs("div", { className: 'tw:cursor-pointer tw:break-inside-avoid card tw:border-[1px] tw:border-base-300 card-body tw:shadow-xl tw:bg-base-100 tw:text-base-content tw:p-6 tw:mb-10', children: [jsx("label", { className: 'btn btn-sm tw:rounded-2xl btn-circle btn-ghost tw:hover:bg-transparent tw:absolute tw:right-0 tw:top-0 tw:text-gray-600', onClick: () => setAddItemPopupType(''), children: jsx("p", { className: 'tw:text-center', children: "\u2715" }) }), jsx(TextInput, { type: 'text', placeholder: 'Name', dataField: 'name', defaultValue: '', inputStyle: '' }), layer?.itemType.show_start_end_input && jsx(PopupStartEndInput$1, {}), jsx(TextAreaInput, { placeholder: 'Text', dataField: 'text', defaultValue: '', inputStyle: 'tw:h-40 tw:mt-5' }), jsx("div", { className: 'tw:flex tw:justify-center', children: jsx("button", { className: loading
4206
3931
  ? 'btn btn-disabled tw:mt-5 tw:place-self-center'
4207
3932
  : 'btn tw:mt-5 tw:place-self-center', type: 'submit', children: loading ? jsx("span", { className: 'loading loading-spinner' }) : 'Save' }) })] }) }))] }) })] }) }), plusButton && (jsx(PlusButton, { layer: layer, triggerAction: () => {
4208
3933
  setAddItemPopupType('place');
@@ -4891,7 +4616,7 @@ const GroupSubHeaderView = ({ item, shareBaseUrl, platforms, }) => (jsxs("div",
4891
4616
  : window.location.protocol + '//' + window.location.host + '/item/' + item.id, title: item.name, platforms: platforms }) })] }));
4892
4617
 
4893
4618
  const ProfileStartEndView = ({ item }) => {
4894
- return (jsx("div", { className: 'tw:mt-2 tw:px-6 tw:max-w-xs', children: jsx(StartEndView, { item: item }) }));
4619
+ return (jsx("div", { className: 'tw:mt-2 tw:px-6 tw:max-w-xs', children: jsx(StartEndView$1, { item: item }) }));
4895
4620
  };
4896
4621
 
4897
4622
  const get = (value, path, defaultValue) => {
@@ -4915,7 +4640,7 @@ const get = (value, path, defaultValue) => {
4915
4640
  const ProfileTextView = ({ item, dataField = 'text', heading, hideWhenEmpty, }) => {
4916
4641
  const text = get(item, dataField);
4917
4642
  const parsedText = typeof text !== 'string' ? '' : text;
4918
- return (jsxs("div", { className: 'tw:my-10 tw:mt-2 tw:px-6', children: [!(text === '' && hideWhenEmpty) && (jsx("h2", { className: 'tw:text-lg tw:font-semibold', children: heading })), jsx("div", { className: 'tw:mt-2 tw:text-sm', children: jsx(TextView, { itemId: item.id, rawText: parsedText }) })] }));
4643
+ return (jsxs("div", { className: 'tw:my-10 tw:mt-2 tw:px-6', children: [!(text === '' && hideWhenEmpty) && (jsx("h2", { className: 'tw:text-lg tw:font-semibold', children: heading })), jsx("div", { className: 'tw:mt-2 tw:text-sm', children: jsx(TextView$1, { itemId: item.id, rawText: parsedText }) })] }));
4919
4644
  };
4920
4645
 
4921
4646
  const componentMap$1 = {
@@ -4937,11 +4662,11 @@ const FlexView = ({ item }) => {
4937
4662
  };
4938
4663
 
4939
4664
  const OnepagerView = ({ item }) => {
4940
- return (jsxs("div", { className: 'tw:h-full tw:overflow-y-auto fade', children: [jsx(GroupSubHeaderView, { item: item, shareBaseUrl: `https://www.wuerdekompass.org/aktivitaeten/gruppensuche/#/gruppe/${item.slug}` }), item.user_created?.first_name && jsx(ContactInfoView, { heading: 'Du hast Fragen?', item: item }), jsx("div", { className: 'tw:my-10 tw:mt-2 tw:px-6 tw:text-sm ', children: jsx(TextView, { itemId: item.id, rawText: item.text ?? 'Keine Beschreibung vorhanden' }) }), item.next_appointment && (jsxs("div", { className: 'tw:my-10 tw:px-6', children: [jsx("h2", { className: 'tw:text-lg tw:font-semibold', children: "N\u00E4chste Termine" }), jsx("div", { className: 'tw:mt-2 tw:text-sm', children: jsx(TextView, { itemId: item.id, rawText: item.next_appointment }) })] })), ";"] }));
4665
+ return (jsxs("div", { className: 'tw:h-full tw:overflow-y-auto fade', children: [jsx(GroupSubHeaderView, { item: item, shareBaseUrl: `https://www.wuerdekompass.org/aktivitaeten/gruppensuche/#/gruppe/${item.slug}` }), item.user_created?.first_name && jsx(ContactInfoView, { heading: 'Du hast Fragen?', item: item }), jsx("div", { className: 'tw:my-10 tw:mt-2 tw:px-6 tw:text-sm ', children: jsx(TextView$1, { itemId: item.id, rawText: item.text ?? 'Keine Beschreibung vorhanden' }) }), item.next_appointment && (jsxs("div", { className: 'tw:my-10 tw:px-6', children: [jsx("h2", { className: 'tw:text-lg tw:font-semibold', children: "N\u00E4chste Termine" }), jsx("div", { className: 'tw:mt-2 tw:text-sm', children: jsx(TextView$1, { itemId: item.id, rawText: item.next_appointment }) })] })), ";"] }));
4941
4666
  };
4942
4667
 
4943
4668
  const SimpleView = ({ item }) => {
4944
- return (jsx("div", { className: 'tw:mt-8 tw:h-full tw:overflow-y-auto fade tw:px-6', children: jsx(TextView, { text: item.text, itemId: item.id }) }));
4669
+ return (jsx("div", { className: 'tw:mt-8 tw:h-full tw:overflow-y-auto fade tw:px-6', children: jsx(TextView$1, { text: item.text, itemId: item.id }) }));
4945
4670
  };
4946
4671
 
4947
4672
  function LinkIcon({
@@ -4993,7 +4718,7 @@ function ActionButton({ item, triggerAddButton, triggerItemSelected, existingRel
4993
4718
  }, style: {
4994
4719
  backgroundColor,
4995
4720
  color: '#fff',
4996
- }, children: jsx(ForwardRef$5, { className: 'tw:w-5 tw:h-5 tw:stroke-[2.5]' }) }))] }), jsxs(DialogModal, { title: 'Select', isOpened: modalOpen, onClose: () => setModalOpen(false), className: 'tw:w-xl tw:sm:w-2xl tw:min-h-80 tw:bg-base-200', children: [jsx(TextInput, { defaultValue: '', placeholder: '\uD83D\uDD0D Search', containerStyle: 'lg:col-span-2 tw:m-4 ', updateFormValue: (val) => {
4721
+ }, children: jsx(ForwardRef$7, { className: 'tw:w-5 tw:h-5 tw:stroke-[2.5]' }) }))] }), jsxs(DialogModal, { title: 'Select', isOpened: modalOpen, onClose: () => setModalOpen(false), className: 'tw:w-xl tw:sm:w-2xl tw:min-h-80 tw:bg-base-200', children: [jsx(TextInput, { defaultValue: '', placeholder: '\uD83D\uDD0D Search', containerStyle: 'lg:col-span-2 tw:m-4 ', updateFormValue: (val) => {
4997
4722
  setSearch(val);
4998
4723
  } }), jsx("div", { className: 'tw:grid tw:grid-cols-1 tw:sm:grid-cols-2', children: filterdItems
4999
4724
  .filter((item) => {
@@ -5073,7 +4798,7 @@ const TabsView = ({ attestations, item, offers, needs, relations, updatePermissi
5073
4798
  setActiveTab(urlTab ? Number(urlTab) : 1);
5074
4799
  // eslint-disable-next-line react-hooks/exhaustive-deps
5075
4800
  }, [location.search]);
5076
- return (jsxs("div", { role: 'tablist', className: 'tw:tabs tw:tabs-lift tw:mt-2 tw:mb-2 tw:px-6', children: [jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab tw:font-bold tw:ps-2! tw:pe-2! ', "aria-label": `${item.layer?.itemType.icon_as_labels && activeTab !== 1 ? '📝' : '📝\u00A0Info'}`, checked: activeTab === 1 && true, onChange: () => updateActiveTab(1) }), jsxs("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:!h-[calc(100dvh-280px)] tw:overflow-y-auto fade tw:pt-2 tw:pb-4 tw:mb-4 tw:overflow-x-hidden', children: [item.layer?.itemType.show_start_end && (jsx("div", { className: 'tw:max-w-xs', children: jsx(StartEndView, { item: item }) })), jsx(TextView, { text: item.text, itemId: item.id }), jsx("div", { className: 'tw:h-4' }), jsx(TextView, { text: item.contact, itemId: item.id })] }), item.layer?.itemType.questlog && (jsxs(Fragment, { children: [jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab tw:font-bold tw:ps-2! tw:pe-2!', "aria-label": `${item.layer.itemType.icon_as_labels && activeTab !== 2 ? '❤️' : '❤️\u00A0Trust'}`, checked: activeTab === 2 && true, onChange: () => updateActiveTab(2) }), jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:!h-[calc(100dvh-280px)] tw:overflow-y-auto fade tw:pt-2 tw:pb-4 tw:mb-4 tw:overflow-x-hidden', children: jsx("table", { className: 'sm:tw:table-sm md:tw:table-md tw:w-full', children: jsx("tbody", { children: attestations
4801
+ return (jsxs("div", { role: 'tablist', className: 'tw:tabs tw:tabs-lift tw:mt-2 tw:mb-2 tw:px-6', children: [jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab tw:font-bold tw:ps-2! tw:pe-2! ', "aria-label": `${item.layer?.itemType.icon_as_labels && activeTab !== 1 ? '📝' : '📝\u00A0Info'}`, checked: activeTab === 1 && true, onChange: () => updateActiveTab(1) }), jsxs("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:!h-[calc(100dvh-280px)] tw:overflow-y-auto fade tw:pt-2 tw:pb-4 tw:mb-4 tw:overflow-x-hidden', children: [item.layer?.itemType.show_start_end && (jsx("div", { className: 'tw:max-w-xs', children: jsx(StartEndView$1, { item: item }) })), jsx(TextView$1, { text: item.text, itemId: item.id }), jsx("div", { className: 'tw:h-4' }), jsx(TextView$1, { text: item.contact, itemId: item.id })] }), item.layer?.itemType.questlog && (jsxs(Fragment, { children: [jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab tw:font-bold tw:ps-2! tw:pe-2!', "aria-label": `${item.layer.itemType.icon_as_labels && activeTab !== 2 ? '❤️' : '❤️\u00A0Trust'}`, checked: activeTab === 2 && true, onChange: () => updateActiveTab(2) }), jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:!h-[calc(100dvh-280px)] tw:overflow-y-auto fade tw:pt-2 tw:pb-4 tw:mb-4 tw:overflow-x-hidden', children: jsx("table", { className: 'sm:tw:table-sm md:tw:table-md tw:w-full', children: jsx("tbody", { children: attestations
5077
4802
  .filter((a) => a.to.some((t) => t.directus_users_id === item.user_created?.id))
5078
4803
  .sort((a, b) => new Date(b.date_created).getTime() - new Date(a.date_created).getTime())
5079
4804
  .map((a, i) => (jsxs("tr", { children: [jsx("td", { children: jsx("div", { className: `tw:cursor-pointer tw:text-3xl tw:mask ${a.shape === 'squircle' ? 'tw:mask-squircle' : a.shape === 'circle' ? 'tw:mask-circle' : 'tw:mask-hexagon-2'} tw:p-2 tw:my-2 tw:mr-2 tw:shadow-xl`,
@@ -5083,7 +4808,7 @@ const TabsView = ({ attestations, item, offers, needs, relations, updatePermissi
5083
4808
  a.user_created.first_name, ' '] }), jsx("div", { className: 'tw:text-xs opacity-50 tw:text-zinc-500', children: timeAgo(a.date_created) })] })] }) })) : (jsxs("div", { children: [jsxs("div", { className: 'font-bold', children: [a.user_created.first_name, " "] }), jsx("div", { className: 'tw:text-xs opacity-50 tw:text-zinc-500', children: timeAgo(a.date_created) })] })) })] }, i))) }) }) })] })), item.layer?.itemType.offers_and_needs && (jsxs(Fragment, { children: [jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: `tw:tab tw:font-bold tw:ps-2! tw:pe-2! ${!(item.layer.itemType.icon_as_labels && activeTab !== 3) && 'tw:min-w-[10.4em]'} `, "aria-label": `${item.layer.itemType.icon_as_labels && activeTab !== 3 ? '♻️' : '♻️\u00A0Offers & Needs'}`, checked: activeTab === 3 && true, onChange: () => updateActiveTab(3) }), jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:h-[calc(100dvh-268px)] tw:overflow-y-auto fade tw:pt-4 tw:pb-1', children: jsx("div", { className: 'tw:h-full', children: jsxs("div", { className: 'tw:grid tw:grid-cols-1', children: [offers.length > 0 ? (jsxs("div", { className: 'tw:col-span-1', children: [jsx("h3", { className: 'tw:-mb-2', children: "Offers" }), jsx("div", { className: 'tw:flex tw:flex-wrap tw:mb-4', children: offers.map((o) => (jsx(TagView, { tag: o, onClick: () => {
5084
4809
  addFilterTag(o);
5085
4810
  } }, o.id))) })] })) : (''), needs.length > 0 ? (jsxs("div", { className: 'tw:col-span-1', children: [jsx("h3", { className: 'tw:-mb-2 tw:col-span-1', children: "Needs" }), jsx("div", { className: 'tw:flex tw:flex-wrap tw:mb-4', children: needs.map((n) => (jsx(TagView, { tag: n, onClick: () => addFilterTag(n) }, n.id))) })] })) : ('')] }) }) })] })), item.layer?.itemType.relations && (jsxs(Fragment, { children: [jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab tw:font-bold tw:ps-2! tw:pe-2! ', "aria-label": `${item.layer.itemType.icon_as_labels && activeTab !== 7 ? '🔗' : '🔗\u00A0Links'}`, checked: activeTab === 7 && true, onChange: () => updateActiveTab(7) }), jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:!h-[calc(100dvh-280px)] tw:overflow-y-auto tw:pt-4 tw:pb-1 tw:-mr-4 tw:-mb-4 tw:overflow-x-hidden', children: jsx("div", { className: 'tw:h-full', children: jsxs("div", { className: 'tw:grid tw:grid-cols-1 tw:sm:grid-cols-2 tw:md:grid-cols-1 tw:lg:grid-cols-1 tw:xl:grid-cols-1 tw:2xl:grid-cols-2 tw:pb-4', children: [relations &&
5086
- relations.map((i) => (jsxs("div", { className: 'tw:cursor-pointer tw:card tw:bg-base-200 tw:border-[1px] tw:border-base-300 tw:card-body tw:shadow-xl tw:text-base-content tw:p-6 tw:mr-4 tw:mb-4', onClick: () => navigate('/item/' + i.id), children: [jsx(LinkedItemsHeaderView, { unlinkPermission: updatePermission, item: i, unlinkCallback: unlinkItem, loading: loading }), jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: jsx(TextView, { truncate: true, text: i.text, itemId: item.id }) })] }, i.id))), updatePermission && (jsx(ActionButton, { collection: 'items', item: item, existingRelations: relations, triggerItemSelected: linkItem }))] }) }) })] }))] }));
4811
+ relations.map((i) => (jsxs("div", { className: 'tw:cursor-pointer tw:card tw:bg-base-200 tw:border-[1px] tw:border-base-300 tw:card-body tw:shadow-xl tw:text-base-content tw:p-6 tw:mr-4 tw:mb-4', onClick: () => navigate('/item/' + i.id), children: [jsx(LinkedItemsHeaderView, { unlinkPermission: updatePermission, item: i, unlinkCallback: unlinkItem, loading: loading }), jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: jsx(TextView$1, { truncate: true, text: i.text, itemId: item.id }) })] }, i.id))), updatePermission && (jsx(ActionButton, { collection: 'items', item: item, existingRelations: relations, triggerItemSelected: linkItem }))] }) }) })] }))] }));
5087
4812
  };
5088
4813
 
5089
4814
  /**
@@ -5471,7 +5196,7 @@ const GroupSubheaderForm = ({ state, setState, groupStates, groupTypes, }) => {
5471
5196
  };
5472
5197
 
5473
5198
  const ProfileStartEndForm = ({ item, setState, }) => {
5474
- return (jsx(PopupStartEndInput, { item: item, showLabels: false, updateEndValue: (e) => setState((prevState) => ({
5199
+ return (jsx(PopupStartEndInput$1, { item: item, showLabels: false, updateEndValue: (e) => setState((prevState) => ({
5475
5200
  ...prevState,
5476
5201
  end: e,
5477
5202
  })), updateStartValue: (s) => setState((prevState) => ({
@@ -5689,7 +5414,7 @@ const TabsForm = ({ item, state, setState, updatePermission, linkItem, unlinkIte
5689
5414
  setActiveTab(urlTab ? Number(urlTab) : 1);
5690
5415
  // eslint-disable-next-line react-hooks/exhaustive-deps
5691
5416
  }, [location.search]);
5692
- return (jsx("div", { className: 'tw:grow', children: jsxs("div", { role: 'tablist', className: 'tw:tabs tw:h-full tw:tabs-lift tw:mt-3', children: [jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab ', "aria-label": 'Info', checked: activeTab === 1 && true, onChange: () => updateActiveTab(1) }), jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:border-(--fallback-bc,oklch(var(--bc)/0.2)) tw:rounded-box tw:!h-[calc(100%-48px)] tw:min-h-56 tw:border-none', children: jsxs("div", { className: `tw:flex tw:flex-col tw:h-full ${item.layer.itemType.show_start_end_input && 'tw:pt-4'}`, children: [item.layer.itemType.show_start_end_input && (jsx(PopupStartEndInput, { item: item, showLabels: false, updateEndValue: (e) => setState((prevState) => ({
5417
+ return (jsx("div", { className: 'tw:grow', children: jsxs("div", { role: 'tablist', className: 'tw:tabs tw:h-full tw:tabs-lift tw:mt-3', children: [jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab ', "aria-label": 'Info', checked: activeTab === 1 && true, onChange: () => updateActiveTab(1) }), jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:border-(--fallback-bc,oklch(var(--bc)/0.2)) tw:rounded-box tw:!h-[calc(100%-48px)] tw:min-h-56 tw:border-none', children: jsxs("div", { className: `tw:flex tw:flex-col tw:h-full ${item.layer.itemType.show_start_end_input && 'tw:pt-4'}`, children: [item.layer.itemType.show_start_end_input && (jsx(PopupStartEndInput$1, { item: item, showLabels: false, updateEndValue: (e) => setState((prevState) => ({
5693
5418
  ...prevState,
5694
5419
  end: e,
5695
5420
  })), updateStartValue: (s) => setState((prevState) => ({
@@ -5708,7 +5433,7 @@ const TabsForm = ({ item, state, setState, updatePermission, linkItem, unlinkIte
5708
5433
  ...prevState,
5709
5434
  needs: v,
5710
5435
  })), placeholder: 'enter your needs', containerStyle: 'tw:bg-transparent tw:w-full tw:h-full tw:mt-3 tw:text-xs tw:h-[calc(100%-1rem)] tw:min-h-[5em] tw:pb-2 tw:overflow-auto' }) })] }) })] })), item.layer?.itemType.relations && (jsxs(Fragment, { children: [jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab ', "aria-label": 'Links', checked: activeTab === 7 && true, onChange: () => updateActiveTab(7) }), jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:rounded-box tw:!h-[calc(100%-48px)] tw:overflow-y-auto tw:pt-4 tw:overflow-x-hidden fade', children: jsx("div", { className: 'tw:h-full', children: jsxs("div", { className: 'tw:grid tw:grid-cols-1 tw:sm:grid-cols-2 tw:md:grid-cols-1 tw:lg:grid-cols-1 tw:xl:grid-cols-1 tw:2xl:grid-cols-2 tw:mb-4', children: [state.relations &&
5711
- state.relations.map((i) => (jsxs("div", { className: 'tw:cursor-pointer tw:card tw:bg-base-200 tw:border-[1px] tw:border-base-300 tw:card-body tw:shadow-xl tw:text-base-content tw:mx-4 tw:p-6 tw:mb-4', onClick: () => navigate('/item/' + i.id), children: [jsx(LinkedItemsHeaderView, { unlinkPermission: updatePermission, item: i, unlinkCallback: (id) => unlinkItem(id, item, updateItem), loading: loading }), jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: jsx(TextView, { truncate: true, itemId: item.id }) })] }, i.id))), updatePermission && (jsx(ActionButton, { customStyle: 'tw:bottom-24!', collection: 'items', item: item, existingRelations: state.relations, triggerItemSelected: (id) => linkItem(id, item, updateItem) }))] }) }) })] }))] }) }));
5436
+ state.relations.map((i) => (jsxs("div", { className: 'tw:cursor-pointer tw:card tw:bg-base-200 tw:border-[1px] tw:border-base-300 tw:card-body tw:shadow-xl tw:text-base-content tw:mx-4 tw:p-6 tw:mb-4', onClick: () => navigate('/item/' + i.id), children: [jsx(LinkedItemsHeaderView, { unlinkPermission: updatePermission, item: i, unlinkCallback: (id) => unlinkItem(id, item, updateItem), loading: loading }), jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: jsx(TextView$1, { truncate: true, itemId: item.id }) })] }, i.id))), updatePermission && (jsx(ActionButton, { customStyle: 'tw:bottom-24!', collection: 'items', item: item, existingRelations: state.relations, triggerItemSelected: (id) => linkItem(id, item, updateItem) }))] }) }) })] }))] }) }));
5712
5437
  };
5713
5438
 
5714
5439
  /**
@@ -5875,5 +5600,308 @@ function Quests() {
5875
5600
  return (jsx(Fragment, { children: questsOpen ? (jsx("div", { className: 'tw:card tw:w-48 tw:bg-base-100 tw:shadow-xl tw:absolute tw:bottom-4 tw:left-4 tw:z-2000', children: jsxs("div", { className: 'tw:card-body tw:p-4 tw:pt-0', children: [jsx("div", { className: 'tw:card-actions tw:justify-end', children: jsx("label", { className: 'tw:btn tw:btn-sm tw:btn-circle tw:btn-ghost tw:absolute tw:right-1 tw:top-1', onClick: () => setQuestsOpen(false), children: "\u2715" }) }), jsxs("h2", { className: 'tw:card-title tw:m-auto ', children: ["Level 1", jsx(QuestionMarkIcon, {})] }), jsxs("ul", { className: 'tw:flex-row', children: [jsx("li", { children: jsxs("label", { className: 'tw:label tw:justify-normal tw:pt-1 tw:pb-0', children: [jsx("input", { type: 'checkbox', readOnly: true, className: 'tw:checkbox tw:checkbox-xs tw:checkbox-success', checked: isAuthenticated || false }), jsx("span", { className: 'tw:text-sm tw:label-text tw:mx-2', children: "Sign Up" })] }) }), jsx("li", { children: jsxs("label", { className: 'tw:label tw:justify-normal tw:pt-1 tw:pb-0', children: [jsx("input", { type: 'checkbox', readOnly: true, className: 'tw:checkbox tw:checkbox-xs tw:checkbox-success', checked: !!profile?.text }), jsx("span", { className: 'tw:text-sm tw:label-text tw:mx-2', children: "Fill Profile" })] }) }), jsx("li", { children: jsxs("label", { className: 'tw:label tw:justify-normal tw:pt-1 tw:pb-0', children: [jsx("input", { type: 'checkbox', readOnly: true, className: 'tw:checkbox tw:checkbox-xs tw:checkbox-success', checked: !!profile?.image }), jsx("span", { className: 'tw:text-sm tw:label-text tw:mx-2', children: "Upload Avatar" })] }) })] }), ' '] }) })) : ('') }));
5876
5601
  }
5877
5602
 
5878
- export { AppShell, AttestationForm, AuthProvider, CardPage, Content, ItemForm, ItemView, Layer, LoginPage, MapOverlayPage, MarketView, Modal, OverlayItemsIndexPage, Permissions, PopupButton, PopupCheckboxInput, PopupStartEndInput, PopupTextAreaInput, PopupTextInput, ProfileForm, ProfileView, Quests, RequestPasswordPage, SelectUser, SetNewPasswordPage, SideBar, SignupPage, StartEndView, Tags, TextAreaInput, TextInput, TextView, TitleCard, UserSettings, UtopiaMap };
5603
+ const ItemContext = createContext(undefined);
5604
+
5605
+ function templateify(Component) {
5606
+ const TemplateComponent = (props) => {
5607
+ const item = useContext(ItemContext);
5608
+ return jsx(Component, { ...props, item: item });
5609
+ };
5610
+ return TemplateComponent;
5611
+ }
5612
+
5613
+ function ItemFormPopup(props) {
5614
+ const layerContext = useContext(LayerContext);
5615
+ const { menuText, name: activeLayerName } = layerContext;
5616
+ const { popupForm, setPopupForm } = usePopupForm();
5617
+ const [spinner, setSpinner] = useState(false);
5618
+ const formRef = useRef(null);
5619
+ const map = useMap();
5620
+ const addItem = useAddItem();
5621
+ const updateItem = useUpdateItem();
5622
+ const items = useItems();
5623
+ const tags = useTags();
5624
+ const addTag = useAddTag();
5625
+ const resetFilterTags = useResetFilterTags();
5626
+ const { user } = useAuth();
5627
+ const handleSubmit = async (evt) => {
5628
+ if (!popupForm) {
5629
+ throw new Error('Popup form is not defined');
5630
+ }
5631
+ const formItem = {};
5632
+ Array.from(evt.target).forEach((input) => {
5633
+ if (input.name) {
5634
+ formItem[input.name] = input.value;
5635
+ }
5636
+ });
5637
+ formItem.position = {
5638
+ type: 'Point',
5639
+ coordinates: [popupForm.position.lng, popupForm.position.lat],
5640
+ };
5641
+ evt.preventDefault();
5642
+ const name = formItem.name ? formItem.name : user?.first_name;
5643
+ if (!name) {
5644
+ toast.error('Name is must be defined');
5645
+ return;
5646
+ }
5647
+ setSpinner(true);
5648
+ formItem.text &&
5649
+ formItem.text
5650
+ .toLocaleLowerCase()
5651
+ .match(hashTagRegex)
5652
+ ?.map((tag) => {
5653
+ if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
5654
+ addTag({ id: crypto.randomUUID(), name: tag.slice(1), color: randomColor() });
5655
+ }
5656
+ return null;
5657
+ });
5658
+ if (popupForm.item) {
5659
+ let success = false;
5660
+ try {
5661
+ await popupForm.layer.api?.updateItem({ ...formItem, id: popupForm.item.id });
5662
+ success = true;
5663
+ // eslint-disable-next-line no-catch-all/no-catch-all
5664
+ }
5665
+ catch (error) {
5666
+ toast.error(error.toString());
5667
+ }
5668
+ if (success) {
5669
+ updateItem({ ...popupForm.item, ...formItem });
5670
+ toast.success('Item updated');
5671
+ }
5672
+ setSpinner(false);
5673
+ map.closePopup();
5674
+ }
5675
+ else {
5676
+ const item = items.find((i) => i.user_created?.id === user?.id && i.layer?.id === popupForm.layer.id);
5677
+ const uuid = crypto.randomUUID();
5678
+ let success = false;
5679
+ try {
5680
+ popupForm.layer.userProfileLayer &&
5681
+ item &&
5682
+ (await popupForm.layer.api?.updateItem({ ...formItem, id: item.id }));
5683
+ (!popupForm.layer.userProfileLayer || !item) &&
5684
+ (await popupForm.layer.api?.createItem({
5685
+ ...formItem,
5686
+ name,
5687
+ id: uuid,
5688
+ }));
5689
+ success = true;
5690
+ // eslint-disable-next-line no-catch-all/no-catch-all
5691
+ }
5692
+ catch (error) {
5693
+ toast.error(error.toString());
5694
+ }
5695
+ if (success) {
5696
+ if (popupForm.layer.userProfileLayer && item)
5697
+ updateItem({ ...item, ...formItem });
5698
+ if (!popupForm.layer.userProfileLayer || !item) {
5699
+ addItem({
5700
+ ...formItem,
5701
+ name: (formItem.name ? formItem.name : user?.first_name) ?? '',
5702
+ user_created: user ?? undefined,
5703
+ id: uuid,
5704
+ layer: popupForm.layer,
5705
+ public_edit: !user,
5706
+ });
5707
+ }
5708
+ toast.success('New item created');
5709
+ resetFilterTags();
5710
+ }
5711
+ setSpinner(false);
5712
+ map.closePopup();
5713
+ }
5714
+ setPopupForm(null);
5715
+ };
5716
+ const resetPopup = () => {
5717
+ if (formRef.current) {
5718
+ formRef.current.reset();
5719
+ }
5720
+ };
5721
+ useEffect(() => {
5722
+ resetPopup();
5723
+ }, [popupForm?.position]);
5724
+ return (popupForm &&
5725
+ popupForm.layer.name === activeLayerName && (jsx(Popup, { minWidth: 275, maxWidth: 275, autoPanPadding: [20, 80], eventHandlers: {
5726
+ remove: () => {
5727
+ setTimeout(function () {
5728
+ resetPopup();
5729
+ }, 100);
5730
+ },
5731
+ }, position: popupForm.position, children: jsxs("form", { ref: formRef, onReset: resetPopup, autoComplete: 'off', onSubmit: (e) => handleSubmit(e), children: [popupForm.item ? (jsx("div", { className: 'tw:h-3' })) : (jsx("div", { className: 'tw:flex tw:justify-center', children: jsx("b", { className: 'tw:text-xl tw:text-center tw:font-bold', children: menuText }) })), props.children ? (jsx(ItemContext.Provider, { value: popupForm.item, children: props.children })) : (jsxs(Fragment, { children: [jsx(TextInput, { type: 'text', placeholder: 'Name', dataField: 'name', defaultValue: popupForm.item ? popupForm.item.name : '', inputStyle: '' }), jsx(TextAreaInput, { placeholder: 'Text', dataField: 'text', defaultValue: popupForm.item?.text ?? '', inputStyle: 'tw:h-40 tw:mt-5' }, popupForm.position.toString())] })), jsx("div", { className: 'tw:flex tw:justify-center', children: jsx("button", { className: spinner
5732
+ ? 'tw:btn tw:btn-disabled tw:mt-5 tw:place-self-center'
5733
+ : 'tw:btn tw:mt-5 tw:place-self-center', type: 'submit', children: spinner ? jsx("span", { className: 'tw:loading tw:loading-spinner' }) : 'Save' }) })] }) })));
5734
+ }
5735
+
5736
+ /**
5737
+ * @category Item
5738
+ */
5739
+ const PopupForm = ({ children }) => {
5740
+ return jsx(ItemFormPopup, { children: children });
5741
+ };
5742
+
5743
+ // eslint-disable-next-line react/display-name
5744
+ const ItemViewPopup = forwardRef((props, ref) => {
5745
+ const map = useMap();
5746
+ const [loading, setLoading] = useState(false);
5747
+ const removeItem = useRemoveItem();
5748
+ const updadateItem = useUpdateItem();
5749
+ const navigate = useNavigate();
5750
+ const setSelectPosition = useSetSelectPosition();
5751
+ const { setPopupForm } = usePopupForm();
5752
+ const [infoExpanded, setInfoExpanded] = useState(false);
5753
+ const handleEdit = (event) => {
5754
+ event.stopPropagation();
5755
+ map.closePopup();
5756
+ if (!props.item.layer) {
5757
+ throw new Error('Layer is not defined');
5758
+ }
5759
+ setPopupForm({
5760
+ position: new LatLng(props.item.position?.coordinates[1], props.item.position?.coordinates[0]),
5761
+ layer: props.item.layer,
5762
+ item: props.item,
5763
+ });
5764
+ };
5765
+ const handleDelete = async (event) => {
5766
+ event.stopPropagation();
5767
+ setLoading(true);
5768
+ let success = false;
5769
+ try {
5770
+ !props.item.layer?.userProfileLayer &&
5771
+ (await props.item.layer?.api?.deleteItem(props.item.id));
5772
+ props.item.layer?.userProfileLayer &&
5773
+ (await props.item.layer.api?.updateItem({ id: props.item.id, position: null }));
5774
+ success = true;
5775
+ // eslint-disable-next-line no-catch-all/no-catch-all
5776
+ }
5777
+ catch (error) {
5778
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
5779
+ toast.error(error.toString());
5780
+ }
5781
+ if (success) {
5782
+ !props.item.layer?.userProfileLayer && removeItem(props.item);
5783
+ props.item.layer?.userProfileLayer && updadateItem({ ...props.item, position: undefined });
5784
+ toast.success('Item deleted');
5785
+ }
5786
+ setLoading(false);
5787
+ map.closePopup();
5788
+ const params = new URLSearchParams(window.location.search);
5789
+ window.history.pushState({}, '', '/' + `${params ? `?${params}` : ''}`);
5790
+ navigate('/');
5791
+ };
5792
+ return (jsx(Popup, { ref: ref, maxHeight: 377, minWidth: 275, maxWidth: 275, autoPanPadding: [20, 80], children: jsxs("div", { className: 'tw:bg-base-100 tw:text-base-content', children: [jsx(HeaderView, { api: props.item.layer?.api, item: props.item, editCallback: handleEdit, deleteCallback: handleDelete, setPositionCallback: () => {
5793
+ map.closePopup();
5794
+ setSelectPosition(props.item);
5795
+ navigate('/');
5796
+ }, loading: loading }), jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: props.children ?? jsx(TextView$1, { text: props.item.text, itemId: props.item.id }) }), jsxs("div", { className: 'tw:flex tw:-mb-1 tw:flex-row tw:mr-2 tw:mt-1', children: [infoExpanded ? (jsx("p", { className: 'tw:italic tw:min-h-[21px] tw:my-0! tw:opacity-50', children: `${props.item.date_updated && props.item.date_updated !== props.item.date_created ? 'updated' : 'posted'} ${props.item && props.item.user_created && props.item.user_created.first_name ? `by ${props.item.user_created.first_name}` : ''} ${props.item.date_updated ? timeAgo(props.item.date_updated) : timeAgo(props.item.date_created)}` })) : (jsx("p", { className: 'tw:my-0! tw:min-h-[21px] tw:font-bold tw:cursor-pointer tw:text-gray-500', onClick: () => setInfoExpanded(true), children: "\u24D8" })), jsx("div", { className: 'tw:grow' })] })] }) }));
5797
+ });
5798
+
5799
+ /**
5800
+ * @category Item
5801
+ */
5802
+ const PopupView = ({ children }) => {
5803
+ const layerContext = useContext(LayerContext);
5804
+ const { name, markerDefaultColor, markerDefaultColor2, markerShape, markerIcon } = layerContext;
5805
+ const filterTags = useFilterTags();
5806
+ const appState = useAppState();
5807
+ const items = useItems();
5808
+ const getItemTags = useGetItemTags();
5809
+ const addMarker = useAddMarker();
5810
+ const addPopup = useAddPopup();
5811
+ const leafletRefs = useLeafletRefs();
5812
+ const allTagsLoaded = useAllTagsLoaded();
5813
+ const allItemsLoaded = useAllItemsLoaded();
5814
+ const setMarkerClicked = useSetMarkerClicked();
5815
+ const selectPosition = useSelectPosition();
5816
+ const tags = useTags();
5817
+ const [newTagsToAdd, setNewTagsToAdd] = useState([]);
5818
+ const [tagsReady, setTagsReady] = useState(false);
5819
+ const isLayerVisible = useIsLayerVisible();
5820
+ const isGroupTypeVisible = useIsGroupTypeVisible();
5821
+ const visibleGroupTypes = useVisibleGroupType();
5822
+ const visibleItems = useMemo(() => items
5823
+ .filter((item) => item.layer?.name === name)
5824
+ .filter((item) => filterTags.length === 0
5825
+ ? item
5826
+ : filterTags.some((tag) => getItemTags(item).some((filterTag) => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))
5827
+ .filter((item) => item.layer && isLayerVisible(item.layer))
5828
+ .filter((item) => (item.group_type && isGroupTypeVisible(item.group_type)) ||
5829
+ visibleGroupTypes.length === 0), [
5830
+ filterTags,
5831
+ getItemTags,
5832
+ isGroupTypeVisible,
5833
+ isLayerVisible,
5834
+ items,
5835
+ name,
5836
+ visibleGroupTypes.length,
5837
+ ]);
5838
+ return visibleItems.map((item) => {
5839
+ if (!(item.position?.coordinates[0] && item.position.coordinates[1]))
5840
+ return null;
5841
+ if (item.tags) {
5842
+ item.text += '\n\n';
5843
+ item.tags.map((tag) => {
5844
+ if (!item.text?.includes(`#${encodeTag(tag)}`)) {
5845
+ item.text += `#${encodeTag(tag)}`;
5846
+ }
5847
+ return item.text;
5848
+ });
5849
+ }
5850
+ if (allTagsLoaded && allItemsLoaded) {
5851
+ item.text?.match(hashTagRegex)?.map((tag) => {
5852
+ if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase()) &&
5853
+ !newTagsToAdd.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
5854
+ const newTag = {
5855
+ id: crypto.randomUUID(),
5856
+ name: tag.slice(1),
5857
+ color: randomColor(),
5858
+ };
5859
+ setNewTagsToAdd((current) => [...current, newTag]);
5860
+ }
5861
+ return null;
5862
+ });
5863
+ !tagsReady && setTagsReady(true);
5864
+ }
5865
+ const itemTags = getItemTags(item);
5866
+ const latitude = item.position.coordinates[1];
5867
+ const longitude = item.position.coordinates[0];
5868
+ let color1 = markerDefaultColor;
5869
+ let color2 = markerDefaultColor2;
5870
+ if (item.color) {
5871
+ color1 = item.color;
5872
+ }
5873
+ else if (itemTags[0]) {
5874
+ color1 = itemTags[0].color;
5875
+ }
5876
+ if (itemTags[0] && item.color) {
5877
+ color2 = itemTags[0].color;
5878
+ }
5879
+ else if (itemTags[1]) {
5880
+ color2 = itemTags[1].color;
5881
+ }
5882
+ return (jsx(ItemContext.Provider, { value: item, children: jsxs(Marker, { ref: (r) => {
5883
+ if (!(item.id in leafletRefs && leafletRefs[item.id].marker === r)) {
5884
+ r && addMarker(item, r);
5885
+ }
5886
+ }, eventHandlers: {
5887
+ click: () => {
5888
+ selectPosition && setMarkerClicked(item);
5889
+ },
5890
+ }, icon: MarkerIconFactory(markerShape, color1, color2, item.markerIcon ?? markerIcon, appState.assetsApi.url), position: [latitude, longitude], children: [jsx(ItemViewPopup, { ref: (r) => {
5891
+ if (!(item.id in leafletRefs && leafletRefs[item.id].popup === r)) {
5892
+ r && addPopup(item, r);
5893
+ }
5894
+ }, item: item, children: children }), jsx(Tooltip, { offset: [0, -38], direction: 'top', children: item.name })] }) }, item.id));
5895
+ });
5896
+ };
5897
+
5898
+ const TextView = templateify(TextView$1);
5899
+ const StartEndView = templateify(StartEndView$1);
5900
+ const PopupTextInput = templateify(PopupTextInput$1);
5901
+ const PopupButton = templateify(PopupButton$1);
5902
+ const PopupCheckboxInput = templateify(PopupCheckboxInput$1);
5903
+ const PopupTextAreaInput = templateify(PopupTextAreaInput$1);
5904
+ const PopupStartEndInput = templateify(PopupStartEndInput$1);
5905
+
5906
+ export { AppShell, AttestationForm, AuthProvider, CardPage, Content, Layer, LoginPage, MapOverlayPage, MarketView, Modal, OverlayItemsIndexPage, Permissions, PopupButton, PopupCheckboxInput, PopupForm, PopupStartEndInput, PopupTextAreaInput, PopupTextInput, PopupView, ProfileForm, ProfileView, Quests, RequestPasswordPage, SelectUser, SetNewPasswordPage, SideBar, SignupPage, StartEndView, Tags, TextAreaInput, TextInput, TextView, TitleCard, UserSettings, UtopiaMap };
5879
5907
  //# sourceMappingURL=index.esm.js.map