fix(ui): завершить основу таблиц и фильтров серверов
This commit is contained in:
1 parent
f9a4a07996
commit
3d3c45e4d2
24 files changed
+385
-263
No files matched your search
@@ -765,6 +765,7 @@ export function useCascaderLoader<T = unknown>({
|
||||
const hasSearch = typeof onSearch === "function"
|
||||
const hasResolve = typeof resolveValue === "function"
|
||||
const trimmed = query.trim()
|
||||
if ((!enabled || !trimmed) && search !== null) setSearch(null)
|
||||
|
||||
// Serialised so the effects key on CONTENT, not on the array identity.
|
||||
const levelsKey = JSON.stringify(levels)
|
||||
@@ -783,7 +784,6 @@ export function useCascaderLoader<T = unknown>({
|
||||
if (!hasSearch) return undefined
|
||||
if (!enabled || !trimmed) {
|
||||
abortKey(SEARCH_KEY)
|
||||
setSearch((prev) => (prev === null ? prev : null))
|
||||
return undefined
|
||||
}
|
||||
const timer = setTimeout(() => runSearch(trimmed), searchDebounce)
|
||||
@@ -863,4 +863,4 @@ export function useCascaderLoadState(
|
||||
): CascaderLoadState | null {
|
||||
const { loadStates } = useCascaderState()
|
||||
return loadStates.get(parent ?? CASCADER_ROOT_KEY) ?? null
|
||||
}
|
||||
}
|
||||
@@ -125,6 +125,7 @@ function useCascaderVirtualGutter(
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
if (!contentElement) return
|
||||
const measure = () => {
|
||||
const styles = getComputedStyle(contentElement)
|
||||
const block = Number.parseFloat(styles.paddingTop) || 0
|
||||
const inline =
|
||||
@@ -134,6 +135,10 @@ function useCascaderVirtualGutter(
|
||||
? previous
|
||||
: { block, inline }
|
||||
)
|
||||
}
|
||||
const observer = new ResizeObserver(measure)
|
||||
observer.observe(contentElement)
|
||||
return () => observer.disconnect()
|
||||
}, [contentElement])
|
||||
|
||||
return gutter
|
||||
@@ -455,4 +460,4 @@ function CascaderVirtualColumnRows({
|
||||
)
|
||||
}
|
||||
|
||||
export { CascaderVirtualColumn, CascaderVirtualItems }
|
||||
export { CascaderVirtualColumn, CascaderVirtualItems }
|
||||
@@ -925,23 +925,30 @@ function Cascader<T>({
|
||||
|
||||
// Remembers every selected node, so the trigger keeps a label after it
|
||||
// leaves the loaded set (or was never in it).
|
||||
const labelCacheRef = React.useRef(new Map<string, CascaderNode<T>>())
|
||||
const [labelCache, setLabelCache] = React.useState(() => new Map<string, CascaderNode<T>>())
|
||||
|
||||
// Populated during render, since the trigger reads it while rendering.
|
||||
// Idempotent and prop-derived, so a discarded render is harmless.
|
||||
for (const selected of selectedValues) {
|
||||
if (selectedValues.some(selected => {
|
||||
const node = index.byValue.get(selected)
|
||||
if (node) labelCacheRef.current.set(selected, node)
|
||||
return node && labelCache.get(selected) !== node
|
||||
})) {
|
||||
const nextCache = new Map(labelCache)
|
||||
for (const selected of selectedValues) {
|
||||
const node = index.byValue.get(selected)
|
||||
if (node) nextCache.set(selected, node)
|
||||
}
|
||||
setLabelCache(nextCache)
|
||||
}
|
||||
|
||||
const resolveNode = React.useCallback(
|
||||
(nodeValue: string): CascaderNode<T> =>
|
||||
index.byValue.get(nodeValue) ??
|
||||
labelCacheRef.current.get(nodeValue) ?? {
|
||||
labelCache.get(nodeValue) ?? {
|
||||
value: nodeValue,
|
||||
label: nodeValue,
|
||||
},
|
||||
[index]
|
||||
[index, labelCache]
|
||||
)
|
||||
|
||||
/* ------------------------------ derived view ----------------------------- */
|
||||
@@ -1086,7 +1093,9 @@ function Cascader<T>({
|
||||
const swapping = swap.active && swap.key === levelKey
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
if (swap.active) setSwap((prev) => ({ ...prev, active: false }))
|
||||
if (!swap.active) return
|
||||
const frame = requestAnimationFrame(() => setSwap(prev => ({ ...prev, active: false })))
|
||||
return () => cancelAnimationFrame(frame)
|
||||
}, [swap.active])
|
||||
|
||||
/* ----------------------------- virtualization ---------------------------- */
|
||||
@@ -1139,7 +1148,8 @@ function Cascader<T>({
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!virtualized) return
|
||||
setVirtualSyncs((count) => count + 1)
|
||||
const frame = requestAnimationFrame(() => setVirtualSyncs(count => count + 1))
|
||||
return () => cancelAnimationFrame(frame)
|
||||
}, [virtualized])
|
||||
|
||||
React.useEffect(() => {
|
||||
@@ -1669,24 +1679,23 @@ function Cascader<T>({
|
||||
const state = loadStates.get(pendingNavigation.value)
|
||||
if (!state || state.loading || state.error) return
|
||||
|
||||
setPendingNavigation(null)
|
||||
|
||||
if (pendingNavigation.kind === "expand") {
|
||||
toggleExpanded(pendingNavigation.value)
|
||||
return
|
||||
}
|
||||
if (pendingNavigation.kind === "at") {
|
||||
goToLevelAt(pendingNavigation.value, pendingNavigation.depth)
|
||||
return
|
||||
}
|
||||
pushLevel(pendingNavigation.value)
|
||||
}, [pendingNavigation, loadStates, toggleExpanded, goToLevelAt, pushLevel])
|
||||
if (!open && !inline) return
|
||||
// Navigation notifies the controlled parent; dispatch only after this
|
||||
// commit and discard the intent if the popup/context changes first.
|
||||
let cancelled = false
|
||||
queueMicrotask(() => {
|
||||
if (cancelled) return
|
||||
setPendingNavigation(null)
|
||||
if (pendingNavigation.kind === "expand") toggleExpanded(pendingNavigation.value)
|
||||
else if (pendingNavigation.kind === "at") goToLevelAt(pendingNavigation.value, pendingNavigation.depth)
|
||||
else pushLevel(pendingNavigation.value)
|
||||
})
|
||||
return () => { cancelled = true }
|
||||
}, [pendingNavigation, loadStates, toggleExpanded, goToLevelAt, pushLevel, open, inline])
|
||||
|
||||
// A popup that closes mid-flight must not drill in when the answer arrives;
|
||||
// the loader aborts the request, this drops the intent.
|
||||
React.useEffect(() => {
|
||||
if (!open && !inline) setPendingNavigation(null)
|
||||
}, [open, inline])
|
||||
if (!open && !inline && pendingNavigation !== null) setPendingNavigation(null)
|
||||
|
||||
/* ------------------------------- selection ------------------------------ */
|
||||
|
||||
@@ -2931,4 +2940,4 @@ export type {
|
||||
CascaderItemState,
|
||||
CascaderRenderContextValue,
|
||||
CascaderStateContextValue,
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user