mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
fix(source): external svg theming (#192)
* allow include of external svgs without breaking theming * 3.0.77 * 3.0.78 * fixed LocateControl and added react-inlinesvg to external dependencies * theming toast close button * fixed typing * theming search resuts * theming search resuts * theming search resuts * theming donation widget * theming donation widget --------- Co-authored-by: Ulf Gebhardt <ulf.gebhardt@webcraft-media.de>
This commit is contained in:
parent
8b7cff2b32
commit
4fc9516715
24
package-lock.json
generated
24
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "utopia-ui",
|
"name": "utopia-ui",
|
||||||
"version": "3.0.76",
|
"version": "3.0.78",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "utopia-ui",
|
"name": "utopia-ui",
|
||||||
"version": "3.0.76",
|
"version": "3.0.78",
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^2.0.17",
|
"@heroicons/react": "^2.0.17",
|
||||||
@ -18,6 +18,7 @@
|
|||||||
"radash": "^12.1.0",
|
"radash": "^12.1.0",
|
||||||
"react-colorful": "^5.6.1",
|
"react-colorful": "^5.6.1",
|
||||||
"react-image-crop": "^10.1.8",
|
"react-image-crop": "^10.1.8",
|
||||||
|
"react-inlinesvg": "^4.2.0",
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-leaflet-cluster": "^2.1.0",
|
"react-leaflet-cluster": "^2.1.0",
|
||||||
"react-markdown": "^9.0.1",
|
"react-markdown": "^9.0.1",
|
||||||
@ -10203,6 +10204,14 @@
|
|||||||
"react": "^18.3.1"
|
"react": "^18.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-from-dom": {
|
||||||
|
"version": "0.7.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-from-dom/-/react-from-dom-0.7.5.tgz",
|
||||||
|
"integrity": "sha512-CO92PmMKo/23uYPm6OFvh5CtZbMgHs/Xn+o095Lz/TZj9t8DSDhGdSOMLxBxwWI4sr0MF17KUn9yJWc5Q00R/w==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "16.8 - 19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-image-crop": {
|
"node_modules/react-image-crop": {
|
||||||
"version": "10.1.8",
|
"version": "10.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/react-image-crop/-/react-image-crop-10.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/react-image-crop/-/react-image-crop-10.1.8.tgz",
|
||||||
@ -10212,6 +10221,17 @@
|
|||||||
"react": ">=16.13.1"
|
"react": ">=16.13.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-inlinesvg": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-inlinesvg/-/react-inlinesvg-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-V59P6sFU7NACIbvoay9ikYKVFWyIIZFGd7w6YT1m+H7Ues0fOI6B6IftE6NPSYXXv7RHVmrncIyJeYurs3OJcA==",
|
||||||
|
"dependencies": {
|
||||||
|
"react-from-dom": "^0.7.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "16.8 - 19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "utopia-ui",
|
"name": "utopia-ui",
|
||||||
"version": "3.0.76",
|
"version": "3.0.78",
|
||||||
"description": "Reuseable React Components to build mapping apps for real life communities and networks",
|
"description": "Reuseable React Components to build mapping apps for real life communities and networks",
|
||||||
"repository": "https://github.com/utopia-os/utopia-ui",
|
"repository": "https://github.com/utopia-os/utopia-ui",
|
||||||
"homepage": "https://utopia-os.org/",
|
"homepage": "https://utopia-os.org/",
|
||||||
@ -99,6 +99,7 @@
|
|||||||
"radash": "^12.1.0",
|
"radash": "^12.1.0",
|
||||||
"react-colorful": "^5.6.1",
|
"react-colorful": "^5.6.1",
|
||||||
"react-image-crop": "^10.1.8",
|
"react-image-crop": "^10.1.8",
|
||||||
|
"react-inlinesvg": "^4.2.0",
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-leaflet-cluster": "^2.1.0",
|
"react-leaflet-cluster": "^2.1.0",
|
||||||
"react-markdown": "^9.0.1",
|
"react-markdown": "^9.0.1",
|
||||||
|
|||||||
@ -76,6 +76,7 @@ export default [
|
|||||||
'leaflet.locatecontrol/dist/L.Control.Locate.css',
|
'leaflet.locatecontrol/dist/L.Control.Locate.css',
|
||||||
'yet-another-react-lightbox',
|
'yet-another-react-lightbox',
|
||||||
'react-photo-album',
|
'react-photo-album',
|
||||||
|
'react-inlinesvg',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -15,9 +15,20 @@ import { TagsProvider } from '#components/Map/hooks/useTags'
|
|||||||
|
|
||||||
import { AppStateProvider } from './hooks/useAppState'
|
import { AppStateProvider } from './hooks/useAppState'
|
||||||
|
|
||||||
|
import type { CloseButtonProps } from 'react-toastify'
|
||||||
|
|
||||||
// Helper context to determine if the ContextWrapper is already present.
|
// Helper context to determine if the ContextWrapper is already present.
|
||||||
const ContextCheckContext = createContext(false)
|
const ContextCheckContext = createContext(false)
|
||||||
|
|
||||||
|
const CloseButton = ({ closeToast }: CloseButtonProps) => (
|
||||||
|
<button
|
||||||
|
className='tw-btn tw-btn-sm tw-btn-circle tw-btn-ghost tw-absolute tw-right-2 tw-top-2 focus:tw-outline-none'
|
||||||
|
onClick={closeToast}
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
export const ContextWrapper = ({ children }: { children: React.ReactNode }) => {
|
export const ContextWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||||
const isWrapped = useContext(ContextCheckContext)
|
const isWrapped = useContext(ContextCheckContext)
|
||||||
|
|
||||||
@ -67,6 +78,7 @@ export const Wrappers = ({ children }) => {
|
|||||||
draggable
|
draggable
|
||||||
pauseOnHover
|
pauseOnHover
|
||||||
theme='light'
|
theme='light'
|
||||||
|
closeButton={CloseButton}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
</QuestsProvider>
|
</QuestsProvider>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
export * from './AppShell'
|
export * from './AppShell'
|
||||||
export { SideBar } from './SideBar'
|
export { SideBar } from './SideBar'
|
||||||
export { Content } from './Content'
|
export { Content } from './Content'
|
||||||
|
export { default as SVG } from 'react-inlinesvg'
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||||
|
import SVG from 'react-inlinesvg'
|
||||||
|
|
||||||
import PlusSVG from '#assets/plus.svg'
|
import PlusSVG from '#assets/plus.svg'
|
||||||
import { useLayers } from '#components/Map/hooks/useLayers'
|
import { useLayers } from '#components/Map/hooks/useLayers'
|
||||||
import { useHasUserPermission } from '#components/Map/hooks/usePermissions'
|
import { useHasUserPermission } from '#components/Map/hooks/usePermissions'
|
||||||
@ -31,7 +33,7 @@ export default function AddButton({
|
|||||||
{canAddItems() ? (
|
{canAddItems() ? (
|
||||||
<div className='tw-dropdown tw-dropdown-top tw-dropdown-end tw-dropdown-hover tw-z-500 tw-absolute tw-right-4 tw-bottom-4'>
|
<div className='tw-dropdown tw-dropdown-top tw-dropdown-end tw-dropdown-hover tw-z-500 tw-absolute tw-right-4 tw-bottom-4'>
|
||||||
<label tabIndex={0} className='tw-z-500 tw-btn tw-btn-circle tw-shadow tw-bg-base-100'>
|
<label tabIndex={0} className='tw-z-500 tw-btn tw-btn-circle tw-shadow tw-bg-base-100'>
|
||||||
<img src={PlusSVG} alt='Layers' className='tw-h-5 tw-w-5' />
|
<SVG src={PlusSVG} className='tw-h-5 tw-w-5' />
|
||||||
</label>
|
</label>
|
||||||
<ul tabIndex={0} className='tw-dropdown-content tw-pr-1 tw-list-none'>
|
<ul tabIndex={0} className='tw-dropdown-content tw-pr-1 tw-list-none'>
|
||||||
{layers.map(
|
{layers.map(
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
import SVG from 'react-inlinesvg'
|
||||||
|
|
||||||
import LayerSVG from '#assets/layer.svg'
|
import LayerSVG from '#assets/layer.svg'
|
||||||
import { useIsLayerVisible, useToggleVisibleLayer } from '#components/Map/hooks/useFilter'
|
import { useIsLayerVisible, useToggleVisibleLayer } from '#components/Map/hooks/useFilter'
|
||||||
@ -56,7 +57,7 @@ export function LayerControl() {
|
|||||||
setOpen(true)
|
setOpen(true)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img src={LayerSVG} alt='Layers' />
|
<SVG src={LayerSVG} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
import { control } from 'leaflet'
|
import { control } from 'leaflet'
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
|
import SVG from 'react-inlinesvg'
|
||||||
import { useMap, useMapEvents } from 'react-leaflet'
|
import { useMap, useMapEvents } from 'react-leaflet'
|
||||||
|
|
||||||
import TargetSVG from '#assets/target.svg'
|
import TargetSVG from '#assets/target.svg'
|
||||||
@ -58,9 +59,8 @@ export const LocateControl = () => {
|
|||||||
{loading ? (
|
{loading ? (
|
||||||
<span className='tw-loading tw-loading-spinner tw-loading-md tw-mt-1'></span>
|
<span className='tw-loading tw-loading-spinner tw-loading-md tw-mt-1'></span>
|
||||||
) : (
|
) : (
|
||||||
<img
|
<SVG
|
||||||
src={TargetSVG}
|
src={TargetSVG}
|
||||||
alt='x'
|
|
||||||
className='tw-mt-1 tw-p-[1px]'
|
className='tw-mt-1 tw-p-[1px]'
|
||||||
style={{ fill: `${active ? '#fc8702' : 'currentColor'}` }}
|
style={{ fill: `${active ? '#fc8702' : 'currentColor'}` }}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import MagnifyingGlassIcon from '@heroicons/react/24/outline/MagnifyingGlassIcon
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { LatLng, LatLngBounds, marker } from 'leaflet'
|
import { LatLng, LatLngBounds, marker } from 'leaflet'
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
|
import SVG from 'react-inlinesvg'
|
||||||
import { useMap, useMapEvents } from 'react-leaflet'
|
import { useMap, useMapEvents } from 'react-leaflet'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
@ -169,7 +170,7 @@ export const SearchControl = () => {
|
|||||||
{itemsResults.slice(0, 5).map((item) => (
|
{itemsResults.slice(0, 5).map((item) => (
|
||||||
<div
|
<div
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className='tw-cursor-pointer hover:tw-font-bold'
|
className='tw-cursor-pointer hover:tw-font-bold tw-flex tw-flex-row'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const marker = Object.entries(leafletRefs).find((r) => r[1].item === item)?.[1]
|
const marker = Object.entries(leafletRefs).find((r) => r[1].item === item)?.[1]
|
||||||
.marker
|
.marker
|
||||||
@ -182,11 +183,19 @@ export const SearchControl = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className='tw-flex tw-flex-row'>
|
{item.layer?.menuIcon ? (
|
||||||
<img
|
<SVG
|
||||||
src={item.layer?.menuIcon}
|
src={item.layer.menuIcon}
|
||||||
className='tw-text-current tw-w-5 tw-mr-2 tw-mt-0'
|
className='tw-text-current tw-mr-2 tw-mt-0 tw-w-5'
|
||||||
|
preProcessor={(code: string): string => {
|
||||||
|
code = code.replace(/fill=".*?"/g, 'fill="currentColor"')
|
||||||
|
code = code.replace(/stroke=".*?"/g, 'stroke="currentColor"')
|
||||||
|
return code
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
<div className='tw-w-5' />
|
||||||
|
)}
|
||||||
<div>
|
<div>
|
||||||
<div className='tw-text-sm tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap tw-max-w-[17rem]'>
|
<div className='tw-text-sm tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap tw-max-w-[17rem]'>
|
||||||
{item.name}
|
{item.name}
|
||||||
@ -196,7 +205,6 @@ export const SearchControl = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
{Array.from(geoResults).length > 0 &&
|
{Array.from(geoResults).length > 0 &&
|
||||||
(itemsResults.length > 0 || tagsResults.length > 0) && (
|
(itemsResults.length > 0 || tagsResults.length > 0) && (
|
||||||
@ -236,7 +244,7 @@ export const SearchControl = () => {
|
|||||||
hide()
|
hide()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MagnifyingGlassIcon className='tw-text-current tw-mr-2 tw-mt-0 tw-w-4' />
|
<MagnifyingGlassIcon className='tw-text-current tw-mr-2 tw-mt-0 tw-w-5' />
|
||||||
<div>
|
<div>
|
||||||
<div className='tw-text-sm tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap tw-max-w-[17rem]'>
|
<div className='tw-text-sm tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap tw-max-w-[17rem]'>
|
||||||
{geo?.properties.name ? geo?.properties.name : value}
|
{geo?.properties.name ? geo?.properties.name : value}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import EllipsisVerticalIcon from '@heroicons/react/16/solid/EllipsisVerticalIcon
|
|||||||
import PencilIcon from '@heroicons/react/24/solid/PencilIcon'
|
import PencilIcon from '@heroicons/react/24/solid/PencilIcon'
|
||||||
import TrashIcon from '@heroicons/react/24/solid/TrashIcon'
|
import TrashIcon from '@heroicons/react/24/solid/TrashIcon'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
import SVG from 'react-inlinesvg'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
import TargetDotSVG from '#assets/targetDot.svg'
|
import TargetDotSVG from '#assets/targetDot.svg'
|
||||||
@ -159,7 +160,7 @@ export function HeaderView({
|
|||||||
className='!tw-text-base-content tw-cursor-pointer'
|
className='!tw-text-base-content tw-cursor-pointer'
|
||||||
onClick={setPositionCallback}
|
onClick={setPositionCallback}
|
||||||
>
|
>
|
||||||
<img src={TargetDotSVG} alt='Position' className='tw-w-5 tw-h-5' />
|
<SVG src={TargetDotSVG} className='tw-w-5 tw-h-5' />
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -75,10 +75,12 @@ export function UtopiaMapInner({
|
|||||||
<div>
|
<div>
|
||||||
<TextView
|
<TextView
|
||||||
itemId=''
|
itemId=''
|
||||||
rawText={'Support us building free opensource maps and help us grow 🌱☀️'}
|
rawText={
|
||||||
|
'Support us building free opensource maps for communities and help us grow 🌱☀️'
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<a href='https://opencollective.com/utopia-project'>
|
<a href='https://opencollective.com/utopia-project'>
|
||||||
<div className='tw-btn tw-btn-sm tw-float-right'>Donate</div>
|
<div className='tw-btn tw-btn-sm tw-float-right tw-btn-primary'>Donate</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</>,
|
</>,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user