feat(rbd): transform rbd types to Preact from React

This commit is contained in:
Paul 2021-10-31 16:04:37 +00:00
parent c208064d2c
commit f97925073a
2 changed files with 227 additions and 192 deletions

56
src/lib/dnd.ts Normal file
View file

@ -0,0 +1,56 @@
import {
Draggable as rbdDraggable,
DraggableProps as rbdDraggableProps,
DraggableProvided as rbdDraggableProvided,
DraggableProvidedDraggableProps as rbdDraggableProvidedDraggableProps,
DraggableProvidedDragHandleProps as rbdDraggableProvidedDragHandleProps,
DraggableRubric,
DraggableStateSnapshot,
Droppable as rbdDroppable,
DroppableProps,
DroppableProvided,
DroppableStateSnapshot,
} from "react-beautiful-dnd";
export type DraggableProvidedDraggableProps = Omit<
rbdDraggableProvidedDraggableProps,
"style" | "onTransitionEnd"
> & {
style?: string;
onTransitionEnd?: JSX.TransitionEventHandler<HTMLElement>;
};
export type DraggableProvidedDragHandleProps = Omit<
rbdDraggableProvidedDragHandleProps,
"onDragStart"
> & {
onDragStart?: JSX.DragEventHandler<HTMLElement>;
};
export type DraggableProvided = rbdDraggableProvided & {
draggableProps: DraggableProvidedDraggableProps;
dragHandleProps?: DraggableProvidedDragHandleProps | undefined;
};
export type DraggableChildrenFn = (
provided: DraggableProvided,
snapshot: DraggableStateSnapshot,
rubric: DraggableRubric,
) => JSX.Element;
export type DraggableProps = Omit<rbdDraggableProps, "children"> & {
children: DraggableChildrenFn;
};
export const Draggable = rbdDraggable as unknown as (
props: DraggableProps,
) => JSX.Element;
export const Droppable = rbdDroppable as unknown as (
props: Omit<DroppableProps, "children"> & {
children(
provided: DroppableProvided,
snapshot: DroppableStateSnapshot,
): JSX.Element;
},
) => JSX.Element;

View file

@ -1,7 +1,6 @@
import { Filter, Plus, X } from "@styled-icons/boxicons-regular"; import { Plus, X } from "@styled-icons/boxicons-regular";
import isEqual from "lodash.isequal";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd"; import { DragDropContext } from "react-beautiful-dnd";
import { TextChannel, VoiceChannel } from "revolt-api/types/Channels"; import { TextChannel, VoiceChannel } from "revolt-api/types/Channels";
import { Category } from "revolt-api/types/Servers"; import { Category } from "revolt-api/types/Servers";
import { Server } from "revolt.js/dist/maps/Servers"; import { Server } from "revolt.js/dist/maps/Servers";
@ -12,16 +11,13 @@ import { Text } from "preact-i18n";
import { useCallback, useEffect, useMemo, useState } from "preact/hooks"; import { useCallback, useEffect, useMemo, useState } from "preact/hooks";
import { useAutosave } from "../../../lib/debounce"; import { useAutosave } from "../../../lib/debounce";
import { Draggable, Droppable } from "../../../lib/dnd";
import { noop } from "../../../lib/js"; import { noop } from "../../../lib/js";
import { useIntermediate } from "../../../context/intermediate/Intermediate"; import { useIntermediate } from "../../../context/intermediate/Intermediate";
import ChannelIcon from "../../../components/common/ChannelIcon"; import ChannelIcon from "../../../components/common/ChannelIcon";
import Button from "../../../components/ui/Button";
import ComboBox from "../../../components/ui/ComboBox";
import InputBox from "../../../components/ui/InputBox";
import SaveStatus, { EditStatus } from "../../../components/ui/SaveStatus"; import SaveStatus, { EditStatus } from "../../../components/ui/SaveStatus";
import Tip from "../../../components/ui/Tip";
const KanbanEntry = styled.div` const KanbanEntry = styled.div`
padding: 2px 4px; padding: 2px 4px;
@ -234,86 +230,83 @@ export const Categories = observer(({ server }: Props) => {
droppableId="categories" droppableId="categories"
direction="horizontal" direction="horizontal"
type="column"> type="column">
{(provided) => {(provided) => (
( <div
<div ref={provided.innerRef}
ref={provided.innerRef} {...provided.droppableProps}>
{...provided.droppableProps}> <KanbanBoard>
<KanbanBoard> <ListElement
category={defaultCategory}
server={server}
index={0}
addChannel={noop}
/>
{categories.map((category, index) => (
<ListElement <ListElement
category={defaultCategory} draggable
category={category}
server={server} server={server}
index={0} index={index + 1}
addChannel={noop} key={category.id}
setTitle={(title) => {
setCategories(
categories.map((x) =>
x.id === category.id
? {
...x,
title,
}
: x,
),
);
}}
deleteSelf={() =>
setCategories(
categories.filter(
(x) =>
x.id !==
category.id,
),
)
}
addChannel={(channel) => {
setCategories(
categories.map((x) =>
x.id === category.id
? {
...x,
channels: [
...x.channels,
channel._id,
],
}
: x,
),
);
}}
/> />
{categories.map((category, index) => ( ))}
<ListElement <KanbanList last>
draggable <div class="inner">
category={category} <KanbanListHeader
server={server} onClick={() =>
index={index + 1} setCategories([
key={category.id} ...categories,
setTitle={(title) => { {
setCategories( id: ulid(),
categories.map((x) => title: "New Category",
x.id === category.id channels: [],
? { },
...x, ])
title, }>
} <Plus size={24} />
: x, </KanbanListHeader>
), </div>
); </KanbanList>
}} {provided.placeholder}
deleteSelf={() => </KanbanBoard>
setCategories( </div>
categories.filter( )}
(x) =>
x.id !==
category.id,
),
)
}
addChannel={(channel) => {
setCategories(
categories.map((x) =>
x.id === category.id
? {
...x,
channels:
[
...x.channels,
channel._id,
],
}
: x,
),
);
}}
/>
))}
<KanbanList last>
<div class="inner">
<KanbanListHeader
onClick={() =>
setCategories([
...categories,
{
id: ulid(),
title: "New Category",
channels: [],
},
])
}>
<Plus size={24} />
</KanbanListHeader>
</div>
</KanbanList>
{provided.placeholder}
</KanbanBoard>
</div>
) as any
}
</Droppable> </Droppable>
</FullSize> </FullSize>
</DragDropContext> </DragDropContext>
@ -366,116 +359,102 @@ function ListElement({
key={category.id} key={category.id}
draggableId={category.id} draggableId={category.id}
index={index}> index={index}>
{(provided) => {(provided) => (
( <div {...provided.draggableProps} ref={provided.innerRef}>
<div <KanbanList last={false} key={category.id}>
{...(provided.draggableProps as any)} <div class="inner">
ref={provided.innerRef}> <Row>
<KanbanList last={false} key={category.id}> <KanbanListHeader {...provided.dragHandleProps}>
<div class="inner"> {editing ? (
<Row> <input
<KanbanListHeader value={editing}
{...(provided.dragHandleProps as any)}> onChange={(e) =>
{editing ? ( setEditing(
<input e.currentTarget.value,
value={editing} )
onChange={(e) => }
setEditing( onKeyDown={(e) =>
e.currentTarget.value, e.key === "Enter" && save()
) }
} id={category.id}
onKeyDown={(e) => />
e.key === "Enter" && save() ) : (
} <span onClick={startEditing}>
id={category.id} {category.title}
/> </span>
) : (
<span onClick={startEditing}>
{category.title}
</span>
)}
</KanbanListHeader>
{deleteSelf && (
<KanbanListHeader onClick={deleteSelf}>
<X size={24} />
</KanbanListHeader>
)} )}
</Row>
<Droppable
droppableId={category.id}
key={category.id}>
{(provided) =>
(
<div
ref={provided.innerRef}
{...provided.droppableProps}>
{category.channels.map(
(x, index) => {
const channel =
server.client.channels.get(
x,
);
if (!channel)
return null;
return (
<Draggable
key={x}
draggableId={x}
index={index}>
{(provided) =>
(
<div
{...(provided.draggableProps as any)}
{...provided.dragHandleProps}
ref={
provided.innerRef
}>
<KanbanEntry>
<div class="inner">
<ChannelIcon
target={
channel
}
size={
24
}
/>
<span>
{
channel.name
}
</span>
</div>
</KanbanEntry>
</div>
) as any
}
</Draggable>
);
},
)}
{provided.placeholder}
</div>
) as any
}
</Droppable>
<KanbanListHeader
onClick={() =>
openScreen({
id: "special_prompt",
type: "create_channel",
target: server,
cb: addChannel,
})
}>
<Plus size={24} />
</KanbanListHeader> </KanbanListHeader>
</div> {deleteSelf && (
</KanbanList> <KanbanListHeader onClick={deleteSelf}>
</div> <X size={24} />
) as any </KanbanListHeader>
} )}
</Row>
<Droppable
droppableId={category.id}
key={category.id}>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.droppableProps}>
{category.channels.map((x, index) => {
const channel =
server.client.channels.get(x);
if (!channel) return null;
return (
<Draggable
key={x}
draggableId={x}
index={index}>
{(provided) => (
<div
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={
provided.innerRef
}>
<KanbanEntry>
<div class="inner">
<ChannelIcon
target={
channel
}
size={
24
}
/>
<span>
{
channel.name
}
</span>
</div>
</KanbanEntry>
</div>
)}
</Draggable>
);
})}
{provided.placeholder}
</div>
)}
</Droppable>
<KanbanListHeader
onClick={() =>
openScreen({
id: "special_prompt",
type: "create_channel",
target: server,
cb: addChannel,
})
}>
<Plus size={24} />
</KanbanListHeader>
</div>
</KanbanList>
</div>
)}
</Draggable> </Draggable>
); );
} }