feat(source): lazy loading (#229)

* optimized build for lazy loading

* 3.0.95

* loading map overlay component

* 3.0.96

* loading screen for dynamic imports

* replace RichTextEditor with TextAreaInput (dummy)

* reduce changeset

---------

Co-authored-by: Anton Tranelis <mail@antontranelis.de>
This commit is contained in:
Ulf Gebhardt 2025-06-04 15:12:57 +02:00 committed by GitHub
parent c82084576a
commit 5dd0191d79
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 112 additions and 17 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "utopia-ui",
"version": "3.0.93",
"version": "3.0.96",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "utopia-ui",
"version": "3.0.93",
"version": "3.0.96",
"license": "GPL-3.0-only",
"dependencies": {
"@heroicons/react": "^2.0.17",

View File

@ -1,6 +1,6 @@
{
"name": "utopia-ui",
"version": "3.0.93",
"version": "3.0.96",
"description": "Reuseable React Components to build mapping apps for real life communities and networks",
"repository": "https://github.com/utopia-os/utopia-ui",
"homepage": "https://utopia-os.org/",
@ -12,6 +12,11 @@
"types": "./dist/index.d.ts",
"import": "./dist/index.esm.js",
"require": "./dist/index.cjs"
},
"./Profile": {
"types": "./dist/Profile.d.ts",
"import": "./dist/Profile.esm.js",
"require": "./dist/Profile.cjs.js"
}
},
"type": "module",

View File

@ -17,17 +17,22 @@ const aliasConfig = alias({
export default [
{
input: 'src/index.tsx',
input: {
index: 'src/index.tsx',
Profile: 'src/Components/Profile/index.tsx',
},
output: [
{
file: 'dist/index.esm.js',
dir: 'dist/',
format: 'esm',
sourcemap: true,
entryFileNames: '[name].esm.js',
},
{
file: 'dist/index.cjs',
dir: 'dist/',
format: 'cjs',
sourcemap: true,
entryFileNames: '[name].cjs.js',
},
],
plugins: [
@ -78,8 +83,15 @@ export default [
],
},
{
input: 'dist/types/src/index.d.ts',
output: [{ file: 'dist/index.d.ts', format: 'es' }],
input: {
index: path.resolve(__dirname, 'dist/types/src/index.d.ts'),
Profile: path.resolve(__dirname, 'dist/types/src/Components/Profile/index.d.ts'),
},
output: {
dir: path.resolve(__dirname, 'dist'),
format: 'es',
entryFileNames: '[name].d.ts',
},
plugins: [
aliasConfig,
dts({
@ -88,7 +100,7 @@ export default [
},
}),
],
external: [/\.css$/], //, /\.d\.ts$/
external: [/\.css$/],
watch: false,
},
]

View File

@ -0,0 +1,65 @@
import { useEffect, useRef, useState } from 'react'
interface TextAreaProps {
labelTitle?: string
labelStyle?: string
containerStyle?: string
dataField?: string
inputStyle?: string
defaultValue: string
placeholder?: string
required?: boolean
size?: string
updateFormValue?: (value: string) => void
}
/**
* @category Input
*/
export function RichTextEditor({
labelTitle,
dataField,
labelStyle,
containerStyle,
inputStyle,
defaultValue,
placeholder,
required = true,
updateFormValue,
}: TextAreaProps) {
const ref = useRef<HTMLTextAreaElement>(null)
const [inputValue, setInputValue] = useState<string>(defaultValue)
useEffect(() => {
setInputValue(defaultValue)
}, [defaultValue])
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
const newValue = e.target.value
setInputValue(newValue)
if (updateFormValue) {
updateFormValue(newValue)
}
}
return (
<div className={`tw:form-control tw:w-full ${containerStyle ?? ''}`}>
{labelTitle ? (
<label className='tw:label'>
<span className={`tw:label-text tw:text-base-content ${labelStyle ?? ''}`}>
{labelTitle}
</span>
</label>
) : null}
<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}
></textarea>
</div>
)
}

View File

@ -4,7 +4,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useEffect, useState } from 'react'
import { TextAreaInput } from '#components/Input'
import { RichTextEditor } from '#components/Input/RichTextEditor'
import { MarkdownHint } from './MarkdownHint'
@ -47,7 +47,7 @@ export const ProfileTextForm = ({
</label>
<MarkdownHint />
</div>
<TextAreaInput
<RichTextEditor
placeholder={'...'}
// eslint-disable-next-line security/detect-object-injection
defaultValue={state[field]}

View File

@ -9,7 +9,7 @@
import { useCallback, useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { TextAreaInput } from '#components/Input'
import { RichTextEditor } from '#components/Input/RichTextEditor'
import { useUpdateItem } from '#components/Map/hooks/useItems'
import { PopupStartEndInput, TextView } from '#components/Map/Subcomponents/ItemPopupComponents'
import { ActionButton } from '#components/Profile/Subcomponents/ActionsButton'
@ -90,7 +90,8 @@ export const TabsForm = ({
></PopupStartEndInput>
)}
<TextAreaInput
<RichTextEditor
labelTitle='About me'
placeholder='about ...'
defaultValue={item?.text ? item.text : ''}
updateFormValue={(v) =>
@ -102,7 +103,8 @@ export const TabsForm = ({
containerStyle='tw:grow'
inputStyle={`tw:h-full ${!item.layer.itemType.show_start_end_input && 'tw:border-t-0 tw:rounded-tl-none'}`}
/>
<TextAreaInput
<RichTextEditor
labelTitle='Contact Info'
placeholder='contact info ...'
defaultValue={state.contact || ''}
updateFormValue={(c) =>

View File

@ -0,0 +1,11 @@
import { MapOverlayPage } from '#components/Templates/MapOverlayPage'
export const LoadingMapOverlay = () => {
return (
<MapOverlayPage backdrop className='tw:max-w-xs tw:h-64 tw:bg-transparent' card={false}>
<div className='tw:flex tw:justify-center tw:items-center tw:h-full'>
<div className='tw:loading tw:loading-spinner tw:loading-xl'></div>
</div>
</MapOverlayPage>
)
}

View File

@ -45,7 +45,7 @@ export function MapOverlayPage({
>
<div
ref={overlayRef}
className={`${card ? 'tw:card tw:card-body' : ''} tw:shadow-xl tw:bg-base-100 tw:p-6 ${className ?? ''} ${backdrop ? '' : 'tw:z-2000'} tw:absolute tw:top-0 tw:bottom-0 tw:right-0 tw:left-0 tw:m-auto`}
className={`${card ? 'tw:card tw:card-body tw:shadow-xl' : ''} tw:bg-base-100 tw:p-6 ${className ?? ''} ${backdrop ? '' : 'tw:z-2000'} tw:absolute tw:top-0 tw:bottom-0 tw:right-0 tw:left-0 tw:m-auto`}
>
{children}
<button

View File

@ -5,3 +5,4 @@ export { SelectUser } from './SelectUser'
export { OverlayItemsIndexPage } from './OverlayItemsIndexPage'
export { AttestationForm } from './AttestationForm'
export { MarketView } from './MarketView'
export { LoadingMapOverlay } from './LoadingMapOverlay'

View File

@ -4,7 +4,6 @@ import './css'
export * from './Components/Map'
export * from './Components/AppShell'
export * from './Components/Auth'
export * from './Components/Profile'
export * from './Components/Gaming'
export * from './Components/Templates'
export * from './Components/Input'

View File

@ -7,7 +7,7 @@
"module": "esnext",
"target": "ESNext",
"lib": ["es6", "dom","es2015", "es2016", "es2017", "es2020"],
"sourceMap": false,
"sourceMap": true,
"allowJs": false,
"jsx": "react-jsx",
"moduleResolution": "node",