mirror of
https://github.com/aljazceru/rabbit.git
synced 2025-12-17 05:54:19 +01:00
feat: draggable column
This commit is contained in:
@@ -10,6 +10,16 @@ import {
|
|||||||
createMemo,
|
createMemo,
|
||||||
} from 'solid-js';
|
} from 'solid-js';
|
||||||
|
|
||||||
|
import {
|
||||||
|
DragDropProvider,
|
||||||
|
DragDropSensors,
|
||||||
|
DragEventHandler,
|
||||||
|
SortableProvider,
|
||||||
|
createSortable,
|
||||||
|
closestCenter,
|
||||||
|
useDragDropContext,
|
||||||
|
type Transformer,
|
||||||
|
} from '@thisbeyond/solid-dnd';
|
||||||
import Bell from 'heroicons/24/outline/bell.svg';
|
import Bell from 'heroicons/24/outline/bell.svg';
|
||||||
import BookmarkIcon from 'heroicons/24/outline/bookmark.svg';
|
import BookmarkIcon from 'heroicons/24/outline/bookmark.svg';
|
||||||
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
|
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
|
||||||
@@ -149,6 +159,8 @@ const columns: Readonly<Record<ColumnKind, { icon: string /* svg */; nameKey: Pa
|
|||||||
const ColumnButton: Component<{ column: ColumnType; index: number }> = (props) => {
|
const ColumnButton: Component<{ column: ColumnType; index: number }> = (props) => {
|
||||||
const i18n = useTranslation();
|
const i18n = useTranslation();
|
||||||
|
|
||||||
|
const sortable = createSortable(props.column.id);
|
||||||
|
|
||||||
const request = useRequestCommand();
|
const request = useRequestCommand();
|
||||||
const jumpToColumn = () => {
|
const jumpToColumn = () => {
|
||||||
request({
|
request({
|
||||||
@@ -162,7 +174,12 @@ const ColumnButton: Component<{ column: ColumnType; index: number }> = (props) =
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
class="relative flex w-full flex-col items-center py-3 text-primary hover:text-primary-hover"
|
// https://github.com/thisbeyond/solid-dnd/issues/60
|
||||||
|
// https://github.com/thisbeyond/solid-dnd/issues/68
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
use:sortable
|
||||||
|
class="relative flex w-full touch-none select-none flex-col items-center py-3 text-primary hover:text-primary-hover"
|
||||||
onClick={() => jumpToColumn()}
|
onClick={() => jumpToColumn()}
|
||||||
title={props.column.name ?? i18n.t(columnNameKey())}
|
title={props.column.name ?? i18n.t(columnNameKey())}
|
||||||
>
|
>
|
||||||
@@ -174,15 +191,52 @@ const ColumnButton: Component<{ column: ColumnType; index: number }> = (props) =
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ConstrainDragAxis = () => {
|
||||||
|
const dragDropContext = useDragDropContext();
|
||||||
|
const actions = dragDropContext?.[1];
|
||||||
|
|
||||||
|
const transformer: Transformer = {
|
||||||
|
id: 'constrain-x-axis',
|
||||||
|
order: 100,
|
||||||
|
callback: (transform) => ({ ...transform, x: 0 }),
|
||||||
|
};
|
||||||
|
|
||||||
|
actions?.onDragStart(({ draggable }) => {
|
||||||
|
actions?.addTransformer('draggables', draggable.id, transformer);
|
||||||
|
});
|
||||||
|
|
||||||
|
actions?.onDragEnd(({ draggable }) => {
|
||||||
|
actions?.removeTransformer('draggables', draggable.id, transformer.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
|
|
||||||
const ColumnButtons: Component = () => {
|
const ColumnButtons: Component = () => {
|
||||||
const { config } = useConfig();
|
const { config, moveColumnById } = useConfig();
|
||||||
|
|
||||||
|
const columnIds = () => config().columns.map((column) => column.id);
|
||||||
|
|
||||||
|
const handleDragEnd: DragEventHandler = ({ draggable, droppable }) => {
|
||||||
|
if (draggable && droppable) {
|
||||||
|
const columnId = draggable?.id as string;
|
||||||
|
const insertBeforeId = droppable?.id as string;
|
||||||
|
moveColumnById(columnId, insertBeforeId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="scrollbar flex w-full grow overflow-y-auto overflow-x-hidden border-y border-primary/30 px-2 ">
|
<div class="scrollbar flex w-full grow overflow-y-auto overflow-x-hidden border-y border-primary/30 px-2 ">
|
||||||
<div class="size-full flex-col items-center justify-center py-2">
|
<div class="size-full flex-col items-center justify-center py-2">
|
||||||
|
<DragDropProvider onDragEnd={handleDragEnd} collisionDetector={closestCenter}>
|
||||||
|
<DragDropSensors />
|
||||||
|
<ConstrainDragAxis />
|
||||||
|
<SortableProvider ids={columnIds()}>
|
||||||
<For each={config().columns}>
|
<For each={config().columns}>
|
||||||
{(column, index) => <ColumnButton column={column} index={index() + 1} />}
|
{(column, index) => <ColumnButton column={column} index={index() + 1} />}
|
||||||
</For>
|
</For>
|
||||||
|
</SortableProvider>
|
||||||
|
</DragDropProvider>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ type UseConfig = {
|
|||||||
// column
|
// column
|
||||||
saveColumn: (column: ColumnType) => void;
|
saveColumn: (column: ColumnType) => void;
|
||||||
moveColumn: (columnId: string, index: number) => void;
|
moveColumn: (columnId: string, index: number) => void;
|
||||||
|
moveColumnById: (columnId: string, insertBeforeId: string) => void;
|
||||||
removeColumn: (columnId: string) => void;
|
removeColumn: (columnId: string) => void;
|
||||||
initializeColumns: (param: { pubkey: string }) => void;
|
initializeColumns: (param: { pubkey: string }) => void;
|
||||||
// emoji
|
// emoji
|
||||||
@@ -184,6 +185,11 @@ const useConfig = (): UseConfig => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const moveColumnById = (columnId: string, insertBeforeId: string) => {
|
||||||
|
const toIndex = config.columns.findIndex((column) => column.id === insertBeforeId);
|
||||||
|
moveColumn(columnId, toIndex + 1);
|
||||||
|
};
|
||||||
|
|
||||||
const removeColumn = (columnId: string) => {
|
const removeColumn = (columnId: string) => {
|
||||||
setConfig('columns', (current) => current.filter((e) => e.id !== columnId));
|
setConfig('columns', (current) => current.filter((e) => e.id !== columnId));
|
||||||
};
|
};
|
||||||
@@ -259,6 +265,7 @@ const useConfig = (): UseConfig => {
|
|||||||
// column
|
// column
|
||||||
saveColumn,
|
saveColumn,
|
||||||
moveColumn,
|
moveColumn,
|
||||||
|
moveColumnById,
|
||||||
removeColumn,
|
removeColumn,
|
||||||
initializeColumns,
|
initializeColumns,
|
||||||
// emoji
|
// emoji
|
||||||
|
|||||||
Reference in New Issue
Block a user