このコミットが含まれているのは:
@@ -1,9 +1,10 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { useContext, useEffect, useRef } from 'react'
|
||||
|
||||
import SortableItem from '@/components/common/SortableItem'
|
||||
import CountsResizeHandle from '@/components/counts/CountsResizeHandle'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { useUITranslation } from '@/lib/useUITranslation'
|
||||
import { CountsTableScope, useCountsTableLayout } from '@/lib/countsTableLayout'
|
||||
|
||||
import type { CountSort } from '@/lib/counts'
|
||||
|
||||
@@ -19,6 +20,42 @@ const CountsSortHeader = (
|
||||
dragId?: string; totalKind?: string },
|
||||
) => {
|
||||
const { message } = useUITranslation ('counts')
|
||||
const family = useContext (CountsTableScope)
|
||||
const layout = useCountsTableLayout ()
|
||||
const heading = useRef<HTMLDivElement> (null)
|
||||
useEffect (() => {
|
||||
if (!resizable || colSpan != null && colSpan > 1) return
|
||||
const node = heading.current
|
||||
const text = node?.querySelector<HTMLElement> ('[data-counts-label]')
|
||||
const button = text?.closest ('button')
|
||||
if (node == null || text == null || button == null) return
|
||||
const canvas = document.createElement ('canvas')
|
||||
const context = canvas.getContext ('2d')
|
||||
if (context == null) return
|
||||
const measure = () => {
|
||||
context.font = getComputedStyle (text).font
|
||||
const padding = (element: Element) => {
|
||||
const style = getComputedStyle (element)
|
||||
return parseFloat (style.paddingLeft) + parseFloat (style.paddingRight)
|
||||
+ parseFloat (style.borderLeftWidth) + parseFloat (style.borderRightWidth)
|
||||
}
|
||||
const handles = Array.from (node.children).filter (child => child !== button)
|
||||
.reduce ((sum, child) => sum + Math.max (
|
||||
child.scrollWidth, child.getBoundingClientRect ().width), 0)
|
||||
const resize = node.parentElement?.querySelector ('[data-counts-resize]')
|
||||
const resizeWidth = resize?.getBoundingClientRect ().width ?? 0
|
||||
const indicator = button.querySelector ('[data-counts-sort-indicator]')
|
||||
const sortWidth = indicator?.getBoundingClientRect ().width ?? 0
|
||||
const gap = parseFloat (getComputedStyle (button).columnGap) || 0
|
||||
layout.fit (family, field, context.measureText (label.text).width
|
||||
+ handles + padding (button) + padding (node.parentElement!)
|
||||
+ sortWidth + gap + resizeWidth)
|
||||
}
|
||||
measure ()
|
||||
let active = true
|
||||
void document.fonts.ready.then (() => { if (active) measure () })
|
||||
return () => { active = false }
|
||||
}, [family, field, label.text, dragId, resizable, colSpan, layout])
|
||||
const press = useRef<{ x: number; y: number
|
||||
timer: ReturnType<typeof setTimeout> } | null> (null)
|
||||
const suppressClick = useRef (false)
|
||||
@@ -44,7 +81,7 @@ const CountsSortHeader = (
|
||||
data-counts-heading={label.text} rowSpan={rowSpan} colSpan={colSpan}
|
||||
className="relative overflow-hidden whitespace-nowrap px-1 py-1"
|
||||
aria-sort={(sorts.length > 1 && priority >= 0) ? 'other' : state}>
|
||||
<div className="flex min-w-0 items-center">
|
||||
<div ref={heading} className="flex min-w-0 items-center">
|
||||
{shell?.handle}
|
||||
<Button type="button" variant="ghost" size="sm"
|
||||
className="h-auto w-full max-w-full justify-start select-none px-1 py-0 pr-3"
|
||||
@@ -92,9 +129,10 @@ const CountsSortHeader = (
|
||||
}
|
||||
change (field, event.ctrlKey || event.metaKey)
|
||||
}}>
|
||||
<span className="truncate" lang={label.language}>{label.text}</span>
|
||||
{priority >= 0 && <span aria-hidden>
|
||||
{direction === 'asc' ? '▲' : '▼'}{sorts.length > 1 && priority + 1}</span>}
|
||||
<span data-counts-label className="truncate" lang={label.language}>{label.text}</span>
|
||||
<span aria-hidden data-counts-sort-indicator className="inline-block w-10 shrink-0">
|
||||
{priority >= 0 && <>{direction === 'asc' ? '▲' : '▼'}
|
||||
{sorts.length > 1 && priority + 1}</>}</span>
|
||||
</Button>
|
||||
</div>
|
||||
{resizable && <CountsResizeHandle field={field} label={label}/>}
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする