mirror of
https://github.com/lumehq/lume.git
synced 2025-03-18 05:41:53 +01:00
resizable widget
This commit is contained in:
parent
296136203a
commit
0e5adb246f
@ -18,6 +18,7 @@
|
||||
"**/*.{ts, tsx, css, md, html, json}": "prettier --cache --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.0.8",
|
||||
"@getalby/sdk": "^2.4.0",
|
||||
"@nostr-dev-kit/ndk": "^1.2.1",
|
||||
"@nostr-fetch/adapter-ndk": "^0.12.2",
|
||||
@ -47,6 +48,7 @@
|
||||
"nostr-fetch": "^0.13.0",
|
||||
"nostr-tools": "^1.15.0",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"re-resizable": "^6.9.11",
|
||||
"react": "^18.2.0",
|
||||
"react-currency-input-field": "^3.6.11",
|
||||
"react-dom": "^18.2.0",
|
||||
|
53
pnpm-lock.yaml
generated
53
pnpm-lock.yaml
generated
@ -5,6 +5,9 @@ settings:
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
'@dnd-kit/core':
|
||||
specifier: ^6.0.8
|
||||
version: 6.0.8(react-dom@18.2.0)(react@18.2.0)
|
||||
'@getalby/sdk':
|
||||
specifier: ^2.4.0
|
||||
version: 2.4.0
|
||||
@ -92,6 +95,9 @@ dependencies:
|
||||
qrcode.react:
|
||||
specifier: ^3.1.0
|
||||
version: 3.1.0(react@18.2.0)
|
||||
re-resizable:
|
||||
specifier: ^6.9.11
|
||||
version: 6.9.11(react-dom@18.2.0)(react@18.2.0)
|
||||
react:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0
|
||||
@ -124,7 +130,7 @@ dependencies:
|
||||
version: 3.0.1
|
||||
tauri-plugin-sql-api:
|
||||
specifier: github:tauri-apps/tauri-plugin-sql#v1
|
||||
version: github.com/tauri-apps/tauri-plugin-sql/b8fd19dac907cc8c3d78681cd4803a326b8b861e
|
||||
version: github.com/tauri-apps/tauri-plugin-sql/26467343db277e79daf3a216372ba25e1fec0deb
|
||||
tauri-plugin-store-api:
|
||||
specifier: github:tauri-apps/tauri-plugin-store#v1
|
||||
version: github.com/tauri-apps/tauri-plugin-store/a65ce9bfb168a9a3cd7ed4102b9f22770cc3abfa
|
||||
@ -369,6 +375,37 @@ packages:
|
||||
to-fast-properties: 2.0.0
|
||||
dev: true
|
||||
|
||||
/@dnd-kit/accessibility@3.0.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-HXRrwS9YUYQO9lFRc/49uO/VICbM+O+ZRpFDe9Pd1rwVv2PCNkRiTZRdxrDgng/UkvdC3Re9r2vwPpXXrWeFzg==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/@dnd-kit/core@6.0.8(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-lYaoP8yHTQSLlZe6Rr9qogouGUz9oRUj4AHhDQGQzq/hqaJRpFo65X+JKsdHf8oUFBzx5A+SJPUvxAwTF2OabA==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
react-dom: '>=16.8.0'
|
||||
dependencies:
|
||||
'@dnd-kit/accessibility': 3.0.1(react@18.2.0)
|
||||
'@dnd-kit/utilities': 3.2.1(react@18.2.0)
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/@dnd-kit/utilities@3.2.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-OOXqISfvBw/1REtkSK2N3Fi2EQiLMlWUlqnOK/UpOISqBZPWpE6TqL+jcPtMOkE8TqYGiURvRdPSI9hltNUjEA==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/@esbuild/android-arm64@0.18.20:
|
||||
resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
|
||||
engines: {node: '>=12'}
|
||||
@ -5134,6 +5171,16 @@ packages:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
dev: true
|
||||
|
||||
/re-resizable@6.9.11(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-a3hiLWck/NkmyLvGWUuvkAmN1VhwAz4yOhS6FdMTaxCUVN9joIWkT11wsO68coG/iEYuwn+p/7qAmfQzRhiPLQ==}
|
||||
peerDependencies:
|
||||
react: ^16.13.1 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-currency-input-field@3.6.11(react@18.2.0):
|
||||
resolution: {integrity: sha512-M9vOx1eaioSaYWirm7W2WSBi4bpLg+LK4Gf7C1kNhy6MvoSoOzd0mYZPxA78OC9UBIQ2nM080Wu9D1CwTY6n3w==}
|
||||
peerDependencies:
|
||||
@ -6314,8 +6361,8 @@ packages:
|
||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||
dev: false
|
||||
|
||||
github.com/tauri-apps/tauri-plugin-sql/b8fd19dac907cc8c3d78681cd4803a326b8b861e:
|
||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-sql/tar.gz/b8fd19dac907cc8c3d78681cd4803a326b8b861e}
|
||||
github.com/tauri-apps/tauri-plugin-sql/26467343db277e79daf3a216372ba25e1fec0deb:
|
||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-sql/tar.gz/26467343db277e79daf3a216372ba25e1fec0deb}
|
||||
name: tauri-plugin-sql-api
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
|
@ -7,6 +7,7 @@ import { useNDK } from '@libs/ndk/provider';
|
||||
|
||||
import { ArticleNote, NoteSkeleton, NoteWrapper } from '@shared/notes';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
@ -51,7 +52,7 @@ export function GlobalArticlesWidget({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<div ref={parentRef} className="scrollbar-hide h-full overflow-y-auto pb-20">
|
||||
{status === 'loading' ? (
|
||||
@ -89,6 +90,6 @@ export function GlobalArticlesWidget({ params }: { params: Widget }) {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import { useNDK } from '@libs/ndk/provider';
|
||||
|
||||
import { FileNote, NoteSkeleton, NoteWrapper } from '@shared/notes';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
@ -52,7 +53,7 @@ export function GlobalFilesWidget({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<div ref={parentRef} className="scrollbar-hide h-full overflow-y-auto pb-20">
|
||||
{status === 'loading' ? (
|
||||
@ -90,6 +91,6 @@ export function GlobalFilesWidget({ params }: { params: Widget }) {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import {
|
||||
UnknownNote,
|
||||
} from '@shared/notes';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { nHoursAgo } from '@utils/date';
|
||||
import { Widget } from '@utils/types';
|
||||
@ -114,7 +115,7 @@ export function GlobalHashtagWidget({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title + ' in 24 hours ago'} />
|
||||
<div ref={parentRef} className="scrollbar-hide h-full overflow-y-auto pb-20">
|
||||
{status === 'loading' ? (
|
||||
@ -152,6 +153,6 @@ export function GlobalHashtagWidget({ params }: { params: Widget }) {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
export * from './wrapper';
|
||||
export * from './local/feeds';
|
||||
export * from './local/network';
|
||||
export * from './local/user';
|
||||
|
@ -8,6 +8,7 @@ import { useStorage } from '@libs/storage/provider';
|
||||
import { ArrowRightCircleIcon, LoaderIcon } from '@shared/icons';
|
||||
import { FileNote, NoteSkeleton, NoteWrapper } from '@shared/notes';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { DBEvent, Widget } from '@utils/types';
|
||||
|
||||
@ -53,7 +54,7 @@ export function LocalArticlesWidget({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<div ref={parentRef} className="scrollbar-hide h-full overflow-y-auto pb-20">
|
||||
{status === 'loading' ? (
|
||||
@ -125,6 +126,6 @@ export function LocalArticlesWidget({ params }: { params: Widget }) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
} from '@shared/notes';
|
||||
import { NoteSkeleton } from '@shared/notes/skeleton';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { DBEvent, Widget } from '@utils/types';
|
||||
|
||||
@ -116,7 +117,7 @@ export function LocalFeedsWidget({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<div ref={parentRef} className="scrollbar-hide h-full overflow-y-auto pb-20">
|
||||
{status === 'loading' ? (
|
||||
@ -188,6 +189,6 @@ export function LocalFeedsWidget({ params }: { params: Widget }) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { useStorage } from '@libs/storage/provider';
|
||||
import { ArrowRightCircleIcon, LoaderIcon } from '@shared/icons';
|
||||
import { FileNote, NoteSkeleton, NoteWrapper } from '@shared/notes';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { DBEvent, Widget } from '@utils/types';
|
||||
|
||||
@ -53,7 +54,7 @@ export function LocalFilesWidget({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<div ref={parentRef} className="scrollbar-hide h-full overflow-y-auto pb-20">
|
||||
{status === 'loading' ? (
|
||||
@ -125,6 +126,6 @@ export function LocalFilesWidget({ params }: { params: Widget }) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
} from '@shared/notes';
|
||||
import { NoteSkeleton } from '@shared/notes/skeleton';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { DBEvent, Widget } from '@utils/types';
|
||||
|
||||
@ -115,7 +116,7 @@ export function LocalFollowsWidget({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title="Follows" />
|
||||
<div ref={parentRef} className="scrollbar-hide h-full overflow-y-auto pb-20">
|
||||
{status === 'loading' ? (
|
||||
@ -193,6 +194,6 @@ export function LocalFollowsWidget({ params }: { params: Widget }) {
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
} from '@shared/notes';
|
||||
import { NoteSkeleton } from '@shared/notes/skeleton';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { useNostr } from '@utils/hooks/useNostr';
|
||||
import { toRawEvent } from '@utils/rawEvent';
|
||||
@ -127,19 +128,15 @@ export function LocalNetworkWidget() {
|
||||
since: db.account.last_login_at ?? Math.floor(Date.now() / 1000),
|
||||
};
|
||||
|
||||
sub(
|
||||
filter,
|
||||
async (event) => {
|
||||
const rawEvent = toRawEvent(event);
|
||||
await db.createEvent(rawEvent);
|
||||
},
|
||||
false // don't close sub on eose
|
||||
);
|
||||
sub(filter, async (event) => {
|
||||
const rawEvent = toRawEvent(event);
|
||||
await db.createEvent(rawEvent);
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar title="👋 Network" />
|
||||
<div ref={parentRef} className="scrollbar-hide h-full overflow-y-auto pb-20">
|
||||
{status === 'loading' ? (
|
||||
@ -217,6 +214,6 @@ export function LocalNetworkWidget() {
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import { RepliesList } from '@shared/notes/replies/list';
|
||||
import { NoteSkeleton } from '@shared/notes/skeleton';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { User } from '@shared/user';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { useEvent } from '@utils/hooks/useEvent';
|
||||
import { Widget } from '@utils/types';
|
||||
@ -41,7 +42,7 @@ export function LocalThreadWidget({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="scrollbar-hide relative shrink-0 grow-0 basis-[400px] overflow-y-auto bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<div className="h-full">
|
||||
{status === 'loading' ? (
|
||||
@ -69,6 +70,6 @@ export function LocalThreadWidget({ params }: { params: Widget }) {
|
||||
<RepliesList id={params.content} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
} from '@shared/notes';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { UserProfile } from '@shared/userProfile';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { nHoursAgo } from '@utils/date';
|
||||
import { Widget } from '@utils/types';
|
||||
@ -120,7 +121,7 @@ export function LocalUserWidget({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<div ref={parentRef} className="scrollbar-hide h-full overflow-y-auto pb-20">
|
||||
<div className="px-3 pt-1.5">
|
||||
@ -166,6 +167,6 @@ export function LocalUserWidget({ params }: { params: Widget }) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { NoteSkeleton } from '@shared/notes/skeleton';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
import { NostrBandUserProfile, type Profile } from '@shared/widgets/nostrBandUserProfile';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
@ -31,7 +32,7 @@ export function TrendingAccountsWidget({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title="Trending Accounts" />
|
||||
<div className="scrollbar-hide h-full max-w-full overflow-y-auto pb-20">
|
||||
{status === 'loading' ? (
|
||||
@ -56,6 +57,6 @@ export function TrendingAccountsWidget({ params }: { params: Widget }) {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { NoteSkeleton, NoteWrapper, TextNote } from '@shared/notes';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
@ -31,7 +32,7 @@ export function TrendingNotesWidget({ params }: { params: Widget }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title="Trending Notes" />
|
||||
<div className="scrollbar-hide h-full max-w-full overflow-y-auto pb-20">
|
||||
{status === 'loading' ? (
|
||||
@ -58,6 +59,6 @@ export function TrendingNotesWidget({ params }: { params: Widget }) {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { ArrowRightIcon } from '@shared/icons';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { useResources } from '@stores/resources';
|
||||
|
||||
@ -21,7 +22,7 @@ export function LearnNostrWidget({ params }: { params: Widget }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl">
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title="The Joy of Nostr" />
|
||||
<div className="scrollbar-hide h-full overflow-y-auto px-3 pb-20">
|
||||
{resources.map((resource, index) => (
|
||||
@ -58,6 +59,6 @@ export function LearnNostrWidget({ params }: { params: Widget }) {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
|
32
src/shared/widgets/wrapper.tsx
Normal file
32
src/shared/widgets/wrapper.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import { Resizable } from 're-resizable';
|
||||
import { ReactNode, useState } from 'react';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export function WidgetWrapper({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
}) {
|
||||
const [width, setWidth] = useState(400);
|
||||
|
||||
return (
|
||||
<Resizable
|
||||
size={{ width: width, height: '100vh' }}
|
||||
onResizeStart={(e) => e.preventDefault()}
|
||||
onResizeStop={(e, direction, ref, d) => {
|
||||
setWidth((prevWidth) => prevWidth + d.width);
|
||||
}}
|
||||
minWidth={400}
|
||||
minHeight={'100vh'}
|
||||
className={twMerge(
|
||||
'relative shrink-0 grow-0 basis-[400px] bg-white/10 backdrop-blur-xl',
|
||||
className
|
||||
)}
|
||||
enable={{ right: true }}
|
||||
>
|
||||
{children}
|
||||
</Resizable>
|
||||
);
|
||||
}
|
@ -10,6 +10,7 @@ interface WidgetState {
|
||||
fetchWidgets: (db: LumeStorage) => void;
|
||||
setWidget: (db: LumeStorage, { kind, title, content }: Widget) => void;
|
||||
removeWidget: (db: LumeStorage, id: string) => void;
|
||||
reorderWidget: (id: string, position: number) => void;
|
||||
}
|
||||
|
||||
export const WidgetKinds = {
|
||||
@ -141,6 +142,18 @@ export const useWidgets = create<WidgetState>()(
|
||||
await db.removeWidget(id);
|
||||
set((state) => ({ widgets: state.widgets.filter((widget) => widget.id !== id) }));
|
||||
},
|
||||
reorderWidget: (id: string, position: number) =>
|
||||
set((state) => {
|
||||
const widgets = [...state.widgets];
|
||||
const widget = widgets.find((widget) => widget.id === id);
|
||||
if (!widget) return { widgets };
|
||||
|
||||
const idx = widgets.indexOf(widget);
|
||||
widgets.splice(idx, 1);
|
||||
widgets.splice(position, 0, widget);
|
||||
|
||||
return { widgets };
|
||||
}),
|
||||
}),
|
||||
{
|
||||
name: 'widgets',
|
||||
|
Loading…
x
Reference in New Issue
Block a user