mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
some Item Popup Components ready to use
This commit is contained in:
parent
6bd062c1b3
commit
a68d4951af
@ -26,6 +26,7 @@ const DialogModal = ({
|
||||
onClose,
|
||||
children,
|
||||
}: Props) => {
|
||||
|
||||
const ref = useRef<HTMLDialogElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@ -7,13 +7,14 @@ type InputTextProps = {
|
||||
type?: string;
|
||||
dataField?: string;
|
||||
containerStyle?: string;
|
||||
inputStyle?: string;
|
||||
defaultValue?: string;
|
||||
placeholder?: string;
|
||||
updateFormValue?: (value: string ) => void;
|
||||
}
|
||||
|
||||
|
||||
export function TextInput({labelTitle, labelStyle, type, dataField, containerStyle, defaultValue, placeholder, updateFormValue} : InputTextProps){
|
||||
export function TextInput({labelTitle, labelStyle, type, dataField, containerStyle, inputStyle, defaultValue, placeholder, updateFormValue} : InputTextProps){
|
||||
|
||||
return(
|
||||
<div className={`tw-form-control tw-w-full ${containerStyle}`}>
|
||||
@ -21,7 +22,7 @@ export function TextInput({labelTitle, labelStyle, type, dataField, containerSty
|
||||
<span className={"tw-label-text tw-text-base-content " + labelStyle}>{labelTitle}</span>
|
||||
</label>
|
||||
: " "}
|
||||
<input type={type || "text"} name={dataField} defaultValue={defaultValue} placeholder={placeholder || ""} onChange={(e) => updateFormValue&& updateFormValue(e.target.value)}className="tw-input tw-input-bordered tw-w-full " />
|
||||
<input type={type || "text"} name={dataField} defaultValue={defaultValue} placeholder={placeholder || ""} onChange={(e) => updateFormValue&& updateFormValue(e.target.value)}className={`tw-input tw-input-bordered tw-w-full ${inputStyle ? inputStyle : ""}`} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
import * as React from 'react'
|
||||
import { Item } from '../../types'
|
||||
|
||||
export const ItemForm = ({ children }:{children?: React.ReactNode}) => {
|
||||
return (
|
||||
<div>{children}</div>
|
||||
)
|
||||
export const ItemForm = ({ children, item }: { children?: React.ReactNode, item?: Item }) => {
|
||||
return (
|
||||
<div>{
|
||||
children ?
|
||||
React.Children.toArray(children).map((child) =>
|
||||
React.isValidElement<{ item: Item, test: string }>(child) ?
|
||||
React.cloneElement(child, { item: item, test: "test" }) : ""
|
||||
) : ""
|
||||
}</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
import * as React from 'react'
|
||||
import { Item } from '../../types'
|
||||
|
||||
export const ItemView = ({ children }:{children?: React.ReactNode}) => {
|
||||
export const ItemView = ({ children, item }: { children?: React.ReactNode, item?: Item }) => {
|
||||
return (
|
||||
<div>{children}</div>
|
||||
<div>
|
||||
{children ?
|
||||
React.Children.toArray(children).map((child) =>
|
||||
React.isValidElement<{ item: Item, test: string }>(child) ?
|
||||
React.cloneElement(child, { item: item, test: "test" }) : ""
|
||||
) : ""}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -88,12 +88,12 @@ export const Layer = (props: LayerProps) => {
|
||||
<Marker icon={MarkerIconFactory(props.markerShape, color1, color2, props.markerIcon)} key={place.id} position={[place.position.coordinates[1], place.position.coordinates[0]]}>
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
(props.children && React.Children.toArray(props.children).some(e => React.isValidElement(e) && typeof e.type !== "string" && e.type.name === "ItemForm") ?
|
||||
(props.children && React.Children.toArray(props.children).some(e => React.isValidElement(e) && typeof e.type !== "string" && e.type.name === "ItemView") ?
|
||||
React.Children.toArray(props.children).map((child) =>
|
||||
React.isValidElement(child) && typeof child.type !== "string" && child.type.name === "ItemView" ?
|
||||
<ItemViewPopup key={place.id} item={place} setItemFormPopup={props.setItemFormPopup} >{child}</ItemViewPopup>
|
||||
<ItemViewPopup key={place.id} item={place} setItemFormPopup={props.setItemFormPopup} >{child}</ItemViewPopup>
|
||||
: ""
|
||||
)
|
||||
:
|
||||
@ -106,7 +106,8 @@ export const Layer = (props: LayerProps) => {
|
||||
);
|
||||
})
|
||||
}
|
||||
{props.children}
|
||||
{//{props.children}}
|
||||
}
|
||||
{props.itemFormPopup && props.itemFormPopup.layer!.name == props.name &&
|
||||
(props.children && React.Children.toArray(props.children).some(e => React.isValidElement(e) && typeof e.type !== "string" && e.type.name === "ItemForm") ?
|
||||
React.Children.toArray(props.children).map((child) =>
|
||||
|
||||
@ -85,9 +85,17 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
|
||||
position={props.position}>
|
||||
<form ref={formRef} onReset={resetPopup} onSubmit={e => handleSubmit(e)}>
|
||||
<div className='tw-flex tw-justify-center'><b className="tw-text-xl tw-font-bold">New {props.layer.name}</b></div>
|
||||
{props.children ? props.children :
|
||||
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={props.item ? props.item.name : ""} inputStyle=''/>
|
||||
|
||||
{props.children ?
|
||||
|
||||
React.Children.toArray(props.children).map((child) =>
|
||||
React.isValidElement<{ item: Item, test: string }>(child) ?
|
||||
React.cloneElement(child, { item: props.item}) : ""
|
||||
)
|
||||
|
||||
:
|
||||
<>
|
||||
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={props.item ? props.item.name : ""} />
|
||||
<TextAreaInput placeholder="Text" dataField="text" defaultValue={props.item ? props.item.text : ""} inputStyle='tw-h-40 tw-mt-5' />
|
||||
</>
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import * as React from "react"
|
||||
import { useRemoveItem } from "../hooks/useItems";
|
||||
import { useRemoveItem } from "../../hooks/useItems";
|
||||
import { useMap } from "react-leaflet";
|
||||
import { ItemFormPopupProps } from "./ItemFormPopup";
|
||||
import { ItemFormPopupProps } from "../ItemFormPopup";
|
||||
import { LatLng } from "leaflet";
|
||||
import { Item } from "../../../types";
|
||||
import { Item } from "../../../../types";
|
||||
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@ export function HeaderView({item, setItemFormPopup}: {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='tw-grid tw-grid-cols-6'>
|
||||
<div className='tw-grid tw-grid-cols-6 tw-pb-2'>
|
||||
<div className='tw-col-span-5'>
|
||||
<b className="tw-text-xl tw-font-bold">{item.name}</b>
|
||||
</div>
|
||||
@ -0,0 +1,12 @@
|
||||
import * as React from 'react'
|
||||
import { TextInput } from '../../../Input'
|
||||
import { Item } from '../../../../types'
|
||||
|
||||
export const PopupStartEndInput = ({item}:{item?:Item}) => {
|
||||
return (
|
||||
<div className='tw-grid tw-grid-cols-2 tw-gap-2 tw-mb-5'>
|
||||
<TextInput type='date' placeholder='start' dataField='start' inputStyle='tw-text-sm tw-px-2' labelTitle='start' defaultValue={item && item.start? item.start.substring(0, 10) : ""}></TextInput>
|
||||
<TextInput type='date' placeholder='end' dataField='end' inputStyle='tw-text-sm tw-px-2' labelTitle='end' defaultValue={item && item.end ? item.end.substring(0, 10) : ""}></TextInput>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
import * as React from 'react'
|
||||
import { TextAreaInput } from '../../../Input'
|
||||
import { Item } from '../../../../types'
|
||||
|
||||
export const PopupTextAreaInput = ({ dataField, placeholder, style, item }:
|
||||
{
|
||||
dataField: string,
|
||||
placeholder: string,
|
||||
style?: string,
|
||||
item?: Item
|
||||
}) => {
|
||||
|
||||
return (
|
||||
<TextAreaInput defaultValue={item?.text ? item.text : ""} dataField={dataField} placeholder={placeholder} inputStyle={style}></TextAreaInput>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
import * as React from 'react'
|
||||
|
||||
export const PopupTextInput = () => {
|
||||
return (
|
||||
<div>PopupTextInput</div>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import * as React from 'react'
|
||||
import { Item } from '../../../../types'
|
||||
|
||||
export const StartEndView = ({item} : {item?:Item}) => {
|
||||
return (
|
||||
<div className="tw-flex tw-flex-row tw-mb-4 tw-mt-2">
|
||||
<div className="tw-basis-2/5 tw-flex tw-flex-row">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-4 tw-w-4 tw-mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
<time className='tw-align-middle' dateTime={item && item.start? item.start.substring(0, 10) : ""}>{item && item.start? new Date(item.start).toLocaleDateString(): ""}</time>
|
||||
</div>
|
||||
<div className="tw-basis-1/5 tw-place-content-center">
|
||||
<span>-</span>
|
||||
</div>
|
||||
<div className="tw-basis-2/5 tw-flex tw-flex-row">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-4 tw-w-4 tw-mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
<time className='tw-align-middle' dateTime={item && item.end? item.end.substring(0, 10) : ""}>{item && item.end ? new Date(item.end).toLocaleDateString() : ""}</time>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
import * as React from 'react'
|
||||
import { Item } from '../../../../types'
|
||||
import { useTags } from '../../hooks/useTags';
|
||||
import { replaceURLs } from '../../../../Utils/ReplaceURLs';
|
||||
import { heighlightTags } from '../../../../Utils/HeighlightTags';
|
||||
|
||||
export const TextView = ({item} : {item?: Item}) => {
|
||||
const all_tags = useTags();
|
||||
|
||||
return (
|
||||
<p style={{ whiteSpace: "pre-wrap" }} className="!tw-m-0 !tw-mb-2" dangerouslySetInnerHTML={{ __html: replaceURLs(heighlightTags(item && item.text ? item.text:"", all_tags)) }} />
|
||||
|
||||
)
|
||||
}
|
||||
@ -2,9 +2,9 @@ import * as React from 'react'
|
||||
import { Popup as LeafletPopup, useMap } from 'react-leaflet'
|
||||
import { Item } from '../../../types'
|
||||
import { ItemFormPopupProps } from './ItemFormPopup'
|
||||
import { HeaderView } from './HeaderView'
|
||||
import StartEndView from './StartEndView'
|
||||
import { TextView } from './TextView'
|
||||
import { HeaderView } from './ItemPopupComponents/HeaderView'
|
||||
import { StartEndView } from './ItemPopupComponents/StartEndView'
|
||||
import { TextView } from './ItemPopupComponents/TextView'
|
||||
|
||||
export interface ItemViewPopupProps {
|
||||
item: Item,
|
||||
@ -21,13 +21,20 @@ export const ItemViewPopup = (props: ItemViewPopupProps) => {
|
||||
<LeafletPopup maxHeight={377} minWidth={275} maxWidth={275} autoPanPadding={[20, 5]}>
|
||||
<div>
|
||||
<HeaderView item={props.item} setItemFormPopup={props.setItemFormPopup} />
|
||||
{props.children ? props.children :
|
||||
<div className='tw-overflow-y-auto tw-max-h-72'>
|
||||
{item.start && item.end &&
|
||||
<StartEndView item={props.item} />}
|
||||
<div className='tw-overflow-y-auto tw-max-h-72'>
|
||||
{props.children ?
|
||||
|
||||
React.Children.toArray(props.children).map((child) =>
|
||||
React.isValidElement<{ item: Item, test: string }>(child) ?
|
||||
React.cloneElement(child, { item: props.item }) : ""
|
||||
)
|
||||
|
||||
:
|
||||
|
||||
<TextView item={props.item} />
|
||||
</div>
|
||||
}
|
||||
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</LeafletPopup>
|
||||
)
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
import * as React from 'react'
|
||||
import { Item } from '../../../types'
|
||||
|
||||
const StartEndView = ({item} : {item:Item}) => {
|
||||
return (
|
||||
<div className="tw-flex tw-flex-row">
|
||||
<div className="tw-basis-2/5">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-6 tw-w-6 tw-mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
<span className='tw-align-middle'>{new Date(item.start!).toISOString().substring(0, 10) || ""}</span>
|
||||
</div>
|
||||
<div className="tw-basis-1/5 tw-place-content-center">
|
||||
<span>-</span>
|
||||
</div>
|
||||
<div className="tw-basis-2/5">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-6 tw-w-6 tw-mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
<span className='tw-align-middle tw-leading-6'>{new Date(item.end!).toISOString().substring(0, 10) || ""}</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default StartEndView
|
||||
@ -1,14 +0,0 @@
|
||||
import * as React from 'react'
|
||||
import { Item } from '../../../types'
|
||||
import { useTags } from '../hooks/useTags';
|
||||
import { replaceURLs } from '../../../Utils/ReplaceURLs';
|
||||
import { heighlightTags } from '../../../Utils/HeighlightTags';
|
||||
|
||||
export const TextView = ({item} : {item: Item}) => {
|
||||
const all_tags = useTags();
|
||||
|
||||
return (
|
||||
<p style={{ whiteSpace: "pre-wrap" }} dangerouslySetInnerHTML={{ __html: replaceURLs(heighlightTags(item.text, all_tags)) }} />
|
||||
|
||||
)
|
||||
}
|
||||
@ -31,7 +31,7 @@ function MapEventListener(props: MapEventListenerProps) {
|
||||
},
|
||||
resize: () => {
|
||||
console.log("resize");
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
return null
|
||||
@ -57,14 +57,15 @@ function UtopiaMap({
|
||||
<TagsProvider initialTags={[]}>
|
||||
<ItemsProvider initialItems={[]}>
|
||||
<div className={(selectMode != null ? "crosshair-cursor-enabled" : undefined)}>
|
||||
<MapContainer ref={mapDivRef} style={{ height: height, width: width }} center={center} zoom={zoom}>
|
||||
<MapContainer ref={mapDivRef} style={{ height: height, width: width }} center={center} zoom={zoom}>
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://tile.osmand.net/hd/{z}/{x}/{y}.png" />
|
||||
<MarkerClusterGroup showCoverageOnHover chunkedLoading maxClusterRadius={50}>
|
||||
{
|
||||
React.Children.toArray(children).map((child) =>
|
||||
React.isValidElement<{ setItemFormPopup: React.Dispatch<React.SetStateAction<ItemFormPopupProps>>, itemFormPopup: ItemFormPopupProps | null }>(child) ? React.cloneElement(child, { setItemFormPopup: setItemFormPopup, itemFormPopup: itemFormPopup }) : child
|
||||
React.isValidElement<{ setItemFormPopup: React.Dispatch<React.SetStateAction<ItemFormPopupProps>>, itemFormPopup: ItemFormPopupProps | null }>(child) && typeof child.type !== "string" && child.type.name === "Layer" ?
|
||||
React.cloneElement(child, { setItemFormPopup: setItemFormPopup, itemFormPopup: itemFormPopup }) : child
|
||||
)
|
||||
}
|
||||
</MarkerClusterGroup>
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
export { UtopiaMap } from './UtopiaMap';
|
||||
export { Layer } from './Layer';
|
||||
export { Tags } from "./Tags";
|
||||
export {ItemViewPopup} from './Subcomponents/ItemViewPopup';
|
||||
export {ItemForm} from './ItemForm';
|
||||
export {ItemView} from './ItemView';
|
||||
export {ItemView} from './ItemView';
|
||||
export {PopupTextAreaInput} from './Subcomponents/ItemPopupComponents/PopupTextAreaInput';
|
||||
export {PopupStartEndInput} from './Subcomponents/ItemPopupComponents/PopupStartEndInput';
|
||||
export {TextView} from './Subcomponents/ItemPopupComponents/TextView';
|
||||
export {StartEndView} from './Subcomponents/ItemPopupComponents/StartEndView'
|
||||
@ -1,4 +1,4 @@
|
||||
export { UtopiaMap, Layer, Tags, ItemViewPopup, ItemForm, ItemView } from './Components/Map/index';
|
||||
export { UtopiaMap, Layer, Tags, ItemForm, ItemView, PopupTextAreaInput, PopupStartEndInput, TextView, StartEndView } from './Components/Map/index';
|
||||
export {AppShell, Content, SideBar} from "./Components/AppShell"
|
||||
export {AuthProvider, useAuth, LoginPage, SignupPage} from "./Components/Auth"
|
||||
export {Settings} from './Components/Profile'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user