mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-12 23:36:00 +00:00
Tabs and rich Text Editor in Profile Settings
This commit is contained in:
parent
a7b0be3c79
commit
31b131cea0
876
package-lock.json
generated
876
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -45,6 +45,7 @@
|
||||
"@heroicons/react": "^2.0.17",
|
||||
"@tanstack/react-query": "^5.17.8",
|
||||
"@types/offscreencanvas": "^2019.7.1",
|
||||
"@uiw/react-md-editor": "^4.0.3",
|
||||
"axios": "^1.6.5",
|
||||
"leaflet": "^1.9.4",
|
||||
"leaflet.locatecontrol": "^0.79.0",
|
||||
@ -57,6 +58,7 @@
|
||||
"react-router-dom": "^6.16.0",
|
||||
"react-string-replace": "^1.1.1",
|
||||
"react-toastify": "^9.1.3",
|
||||
"rehype-sanitize": "^6.0.0",
|
||||
"rehype-video": "^2.0.2",
|
||||
"remark-breaks": "^4.0.0",
|
||||
"tributejs": "^5.1.3",
|
||||
|
||||
42
src/Components/Profile/Editor.tsx
Normal file
42
src/Components/Profile/Editor.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import * as React from "react";
|
||||
import MDEditor from '@uiw/react-md-editor';
|
||||
import rehypeSanitize from "rehype-sanitize";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export function TextEditor({ value, updateFormValue }: { value: string, updateFormValue: (string) => void }) {
|
||||
|
||||
useEffect(() => {
|
||||
setHeightFromSourceToTarget("wmde-markdown-color","w-md-editor-text-input");
|
||||
}, [value])
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<MDEditor
|
||||
value={value}
|
||||
onChange={(val) => updateFormValue(val)}
|
||||
preview="edit"
|
||||
height="100%"
|
||||
previewOptions={{
|
||||
rehypePlugins: [[rehypeSanitize]],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// TypeScript
|
||||
const setHeightFromSourceToTarget = (sourceClassName: string, targetClassName: string): void => {
|
||||
// Select the source element and get its height
|
||||
const sourceElement = document.querySelector(`.${sourceClassName}`) as HTMLElement;
|
||||
const height = sourceElement ? (sourceElement.clientHeight +10) + 'px' : '0'; // Convert to string to use in style
|
||||
|
||||
// Select all target elements
|
||||
const targetElements = document.querySelectorAll(`.${targetClassName}`);
|
||||
|
||||
// Set the height of all target elements to match the source element's height
|
||||
targetElements.forEach((element) => {
|
||||
(element as HTMLElement).style.height = height;
|
||||
});
|
||||
}
|
||||
@ -15,6 +15,8 @@ import { randomColor } from '../../Utils/RandomColor';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { UserItem } from '../../types';
|
||||
import { MapOverlayPage } from '../Templates';
|
||||
import {TextEditor} from './Editor';
|
||||
|
||||
|
||||
export function OverlayProfileSettings() {
|
||||
|
||||
@ -26,6 +28,8 @@ export function OverlayProfileSettings() {
|
||||
const [avatar, setAvatar] = useState<string>("");
|
||||
const [color, setColor] = useState<string>("");
|
||||
|
||||
const [activeTab, setActiveTab] = useState<number>(1);
|
||||
|
||||
|
||||
const [crop, setCrop] = useState<Crop>();
|
||||
const [image, setImage] = useState<string>("");
|
||||
@ -45,7 +49,7 @@ export function OverlayProfileSettings() {
|
||||
setName(user?.first_name ? user.first_name : "");
|
||||
setText(user?.description ? user.description : "");
|
||||
setAvatar(user?.avatar ? user?.avatar : ""),
|
||||
setColor(user?.color ? user.color : "#aabbcc")
|
||||
setColor(user?.color ? user.color : "#aabbcc")
|
||||
}, [user])
|
||||
|
||||
const imgRef = React.useRef<HTMLImageElement>(null)
|
||||
@ -208,9 +212,33 @@ export function OverlayProfileSettings() {
|
||||
<TextInput placeholder="Name" defaultValue={user?.first_name ? user.first_name : ""} updateFormValue={(v) => setName(v)} containerStyle='tw-grow tw-ml-6 tw-my-auto ' />
|
||||
</div>
|
||||
|
||||
<div className="tw-grid tw-grid-cols-1 tw-md:grid-cols-1 tw-gap-6 tw-pt-6 tw-pb-6 tw-grow">
|
||||
<TextAreaInput placeholder="About me, Contact, #Tags, ..." defaultValue={user?.description ? user.description : ""} updateFormValue={(v) => setText(v)} containerStyle='tw-h-full' inputStyle='tw-h-full'/>
|
||||
|
||||
<div role="tablist" className="tw-tabs tw-tabs-lifted tw-mt-4">
|
||||
<input type="radio" name="my_tabs_2" role="tab" className={`tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]`} aria-label="Text" checked={activeTab == 1 && true} onChange={() => setActiveTab(1)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-border-[var(--fallback-bc,oklch(var(--bc)/0.2))] tw-rounded-box tw-h-[calc(100dvh-332px)]">
|
||||
<TextEditor value={text} updateFormValue={(v) => setText(v)} ></TextEditor>
|
||||
</div>
|
||||
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab tw-min-w-[10em] [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Offers & Needs" checked={activeTab == 2 && true} onChange={() => setActiveTab(2)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-pt-6 tw-h-[calc(100dvh-332px)]">
|
||||
<textarea className="tw-textarea tw-textarea-bordered tw-w-full tw-mb-4 tw-h-32 " placeholder="Offers"></textarea>
|
||||
<textarea className="tw-textarea tw-textarea-bordered tw-w-full tw-h-32 " placeholder="Needs"></textarea>
|
||||
|
||||
</div>
|
||||
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Contact" checked={activeTab == 3 && true} onChange={() => setActiveTab(3)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-pt-6 tw-h-[calc(100dvh-332px)] tw-overflow-y-auto">
|
||||
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='E-Mail ...'></input>
|
||||
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Telefon ...'></input>
|
||||
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Webpage ...'></input>
|
||||
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Matrix ... '></input>
|
||||
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Telegram ...'></input>
|
||||
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Instagram ...'></input>
|
||||
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Twitter ...'></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div className="tw-mt-2"><button className={loading ? " tw-loading tw-btn-disabled tw-btn tw-btn-primary tw-float-right" : "tw-btn tw-btn-primary tw-float-right"} onClick={() => onUpdateUser()}>Update</button></div>
|
||||
|
||||
@ -62,4 +62,16 @@ input[type="file"] {
|
||||
position: absolute;
|
||||
transform: translate(8px, 8px);
|
||||
|
||||
}
|
||||
|
||||
.tw-tab-content .container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.w-md-editor-text {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.w-md-editor-text-input {
|
||||
min-height: 100%;
|
||||
}
|
||||
@ -7,6 +7,8 @@ module.exports = {
|
||||
theme: {
|
||||
extend: {
|
||||
zIndex: {
|
||||
'3000': '3000',
|
||||
'2000': '2000',
|
||||
'1000': '1000',
|
||||
'500': '500',
|
||||
},
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
"outDir": "dist",
|
||||
"module": "esnext",
|
||||
"target": "es5",
|
||||
"lib": ["es6", "dom", "es2016", "es2017", "es2020"],
|
||||
"lib": ["es6", "dom","es2015", "es2016", "es2017", "es2020"],
|
||||
"sourceMap": true,
|
||||
"allowJs": false,
|
||||
"jsx": "react",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user