タグ D&D 時の表示位置修正 (#268) #400
@@ -13,6 +13,7 @@ import type { CSSProperties, FC, MutableRefObject } from 'react'
|
|||||||
import type { Tag } from '@/types'
|
import type { Tag } from '@/types'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
activeDndId?: string
|
||||||
tag: Tag
|
tag: Tag
|
||||||
nestLevel: number
|
nestLevel: number
|
||||||
pathKey: string
|
pathKey: string
|
||||||
@@ -21,7 +22,15 @@ type Props = {
|
|||||||
sp?: boolean }
|
sp?: boolean }
|
||||||
|
|
||||||
|
|
||||||
const DraggableDroppableTagRow: FC<Props> = ({ tag, nestLevel, pathKey, parentTagId, suppressClickRef, sp }) => {
|
const DraggableDroppableTagRow: FC<Props> = ({
|
||||||
|
activeDndId,
|
||||||
|
tag,
|
||||||
|
nestLevel,
|
||||||
|
pathKey,
|
||||||
|
parentTagId,
|
||||||
|
suppressClickRef,
|
||||||
|
sp,
|
||||||
|
}) => {
|
||||||
const behaviourSettings = useClientBehaviourSettings ()
|
const behaviourSettings = useClientBehaviourSettings ()
|
||||||
const animationMode = behaviourSettings.animation ?? 'normal'
|
const animationMode = behaviourSettings.animation ?? 'normal'
|
||||||
const layoutTransition = clientAnimationTransition (
|
const layoutTransition = clientAnimationTransition (
|
||||||
@@ -53,19 +62,23 @@ const DraggableDroppableTagRow: FC<Props> = ({ tag, nestLevel, pathKey, parentTa
|
|||||||
const { attributes,
|
const { attributes,
|
||||||
listeners,
|
listeners,
|
||||||
setNodeRef: setDragRef,
|
setNodeRef: setDragRef,
|
||||||
transform,
|
transform } = useDraggable ({ id: dndId,
|
||||||
isDragging: dragging } = useDraggable ({ id: dndId,
|
data: { kind: 'tag',
|
||||||
data: { kind: 'tag',
|
dndId,
|
||||||
tagId: tag.id,
|
tagId: tag.id,
|
||||||
parentTagId,
|
parentTagId,
|
||||||
nestLevel } })
|
nestLevel } })
|
||||||
|
|
||||||
const { setNodeRef: setDropRef, isOver: over } = useDroppable ({
|
const { setNodeRef: setDropRef, isOver: over } = useDroppable ({
|
||||||
id: dndId,
|
id: dndId,
|
||||||
data: { kind: 'tag', tagId: tag.id } })
|
data: { kind: 'tag', tagId: tag.id } })
|
||||||
|
|
||||||
|
const activeDragging = activeDndId === dndId
|
||||||
const style: CSSProperties = { transform: CSS.Translate.toString (transform),
|
const style: CSSProperties = { transform: CSS.Translate.toString (transform),
|
||||||
visibility: dragging ? 'hidden' : 'visible' }
|
visibility: activeDragging ? 'hidden' : 'visible' }
|
||||||
|
const innerClassName = cn (
|
||||||
|
'inline-flex min-w-0 max-w-full items-baseline overflow-hidden',
|
||||||
|
sp && 'touch-pan-y')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -101,20 +114,29 @@ const DraggableDroppableTagRow: FC<Props> = ({ tag, nestLevel, pathKey, parentTa
|
|||||||
sp && 'touch-pan-y',
|
sp && 'touch-pan-y',
|
||||||
over && 'ring-2 ring-offset-2')}
|
over && 'ring-2 ring-offset-2')}
|
||||||
>
|
>
|
||||||
<motion.div
|
{activeDragging
|
||||||
ref={setDragRef}
|
? (
|
||||||
style={style}
|
<div
|
||||||
className={cn (
|
ref={setDragRef}
|
||||||
'inline-flex min-w-0 max-w-full items-baseline overflow-hidden',
|
style={style}
|
||||||
sp && 'touch-pan-y')}
|
className={innerClassName}
|
||||||
{...attributes}
|
{...attributes}
|
||||||
{...listeners}
|
{...listeners}>
|
||||||
transition={{ layout: layoutTransition }}
|
<TagLink tag={tag} nestLevel={nestLevel}/>
|
||||||
layoutId={animationMode === 'off'
|
</div>)
|
||||||
? undefined
|
: (
|
||||||
: `tag-${ sp ? 'sp-' : '' }${ tag.id }`}>
|
<motion.div
|
||||||
<TagLink tag={tag} nestLevel={nestLevel}/>
|
ref={setDragRef}
|
||||||
</motion.div>
|
style={style}
|
||||||
|
className={innerClassName}
|
||||||
|
{...attributes}
|
||||||
|
{...listeners}
|
||||||
|
transition={{ layout: layoutTransition }}
|
||||||
|
layoutId={animationMode === 'off'
|
||||||
|
? undefined
|
||||||
|
: `tag-${ sp ? 'sp-' : '' }${ tag.id }`}>
|
||||||
|
<TagLink tag={tag} nestLevel={nestLevel}/>
|
||||||
|
</motion.div>)}
|
||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ const alwaysMeasureDroppables = {
|
|||||||
|
|
||||||
|
|
||||||
const renderTagTree = (
|
const renderTagTree = (
|
||||||
|
activeDndId: string | undefined,
|
||||||
tag: TagWithSections,
|
tag: TagWithSections,
|
||||||
nestLevel: number,
|
nestLevel: number,
|
||||||
path: string,
|
path: string,
|
||||||
@@ -54,6 +55,7 @@ const renderTagTree = (
|
|||||||
const self = (
|
const self = (
|
||||||
<li key={key} className="mb-1">
|
<li key={key} className="mb-1">
|
||||||
<DraggableDroppableTagRow
|
<DraggableDroppableTagRow
|
||||||
|
activeDndId={activeDndId}
|
||||||
tag={tag}
|
tag={tag}
|
||||||
nestLevel={nestLevel}
|
nestLevel={nestLevel}
|
||||||
pathKey={key}
|
pathKey={key}
|
||||||
@@ -67,7 +69,14 @@ const renderTagTree = (
|
|||||||
...((tag.children
|
...((tag.children
|
||||||
?.sort ((a, b) => a.name < b.name ? -1 : 1)
|
?.sort ((a, b) => a.name < b.name ? -1 : 1)
|
||||||
.flatMap (child =>
|
.flatMap (child =>
|
||||||
renderTagTree (child, nestLevel + 1, key, suppressClickRef, tag.id, sp)))
|
renderTagTree (
|
||||||
|
activeDndId,
|
||||||
|
child,
|
||||||
|
nestLevel + 1,
|
||||||
|
key,
|
||||||
|
suppressClickRef,
|
||||||
|
tag.id,
|
||||||
|
sp)))
|
||||||
?? [])]
|
?? [])]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,6 +220,7 @@ type Props = {
|
|||||||
sp?: boolean }
|
sp?: boolean }
|
||||||
|
|
||||||
type ActiveTagDrag = {
|
type ActiveTagDrag = {
|
||||||
|
dndId: string
|
||||||
tagId: number
|
tagId: number
|
||||||
nestLevel: number }
|
nestLevel: number }
|
||||||
|
|
||||||
@@ -251,6 +261,7 @@ const TagDetailSidebar: FC<Props> = ({ className, post, sp }) => {
|
|||||||
() => buildFlatTagByCategory (tags),
|
() => buildFlatTagByCategory (tags),
|
||||||
[tags],
|
[tags],
|
||||||
)
|
)
|
||||||
|
const activeDndId = activeTagDrag?.dndId
|
||||||
|
|
||||||
const suppressClickRef = useRef (false)
|
const suppressClickRef = useRef (false)
|
||||||
|
|
||||||
@@ -366,10 +377,11 @@ const TagDetailSidebar: FC<Props> = ({ className, post, sp }) => {
|
|||||||
{
|
{
|
||||||
const tagId = e.active.data.current?.tagId
|
const tagId = e.active.data.current?.tagId
|
||||||
const nestLevel = e.active.data.current?.nestLevel
|
const nestLevel = e.active.data.current?.nestLevel
|
||||||
|
const dndId = e.active.data.current?.dndId
|
||||||
setActiveTagDrag (
|
setActiveTagDrag (
|
||||||
tagId == null || nestLevel == null
|
tagId == null || nestLevel == null || dndId == null
|
||||||
? null
|
? null
|
||||||
: { tagId, nestLevel })
|
: { dndId, tagId, nestLevel })
|
||||||
}
|
}
|
||||||
setDragging (true)
|
setDragging (true)
|
||||||
suppressClickRef.current = true
|
suppressClickRef.current = true
|
||||||
@@ -426,6 +438,7 @@ const TagDetailSidebar: FC<Props> = ({ className, post, sp }) => {
|
|||||||
{(tagRelationDisplay === 'grouped'
|
{(tagRelationDisplay === 'grouped'
|
||||||
? (tags[cat] ?? []).flatMap (tag =>
|
? (tags[cat] ?? []).flatMap (tag =>
|
||||||
renderTagTree (
|
renderTagTree (
|
||||||
|
activeDndId,
|
||||||
tag,
|
tag,
|
||||||
0,
|
0,
|
||||||
`cat-${ cat }`,
|
`cat-${ cat }`,
|
||||||
@@ -437,6 +450,7 @@ const TagDetailSidebar: FC<Props> = ({ className, post, sp }) => {
|
|||||||
: (flatTagsByCategory[cat] ?? []).map (tag => (
|
: (flatTagsByCategory[cat] ?? []).map (tag => (
|
||||||
<li key={`flat-${ cat }-${ tag.id }`} className="mb-1">
|
<li key={`flat-${ cat }-${ tag.id }`} className="mb-1">
|
||||||
<DraggableDroppableTagRow
|
<DraggableDroppableTagRow
|
||||||
|
activeDndId={activeDndId}
|
||||||
tag={tag}
|
tag={tag}
|
||||||
nestLevel={0}
|
nestLevel={0}
|
||||||
pathKey={`flat-${ cat }-${ tag.id }`}
|
pathKey={`flat-${ cat }-${ tag.id }`}
|
||||||
|
|||||||
新しい課題から参照
ユーザをブロックする