@ryuzaki13/react-foundation-lib 1.1.10 → 1.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/hooks/useBlockBrowserZoom.ts","../../src/hooks/useDebounce.ts","../../src/hooks/useDebounceCallback.ts","../../src/hooks/useDndSortableSensors.ts","../../src/hooks/useFloatingListbox.ts","../../src/hooks/useLazyComponent.ts","../../src/hooks/useReferenceTrace.ts","../../src/hooks/useSearchLink.ts","../../src/hooks/useSearchParams.ts","../../src/hooks/useThrottledCallback.ts"],"sourcesContent":["import { useEffect } from \"react\";\n\n/**\n * Глобально отключает браузерный zoom (ctrl+wheel).\n *\n * @param enabled если true — блокируем нативный зум страницы\n */\nexport function useBlockBrowserZoom(enabled: boolean) {\n\tuseEffect(() => {\n\t\tif (!enabled) return;\n\n\t\tconst handler = (e: WheelEvent) => {\n\t\t\tif (e.ctrlKey) {\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener(\"wheel\", handler, { passive: false });\n\t\treturn () => window.removeEventListener(\"wheel\", handler);\n\t}, [enabled]);\n}\n","import { useEffect, useState } from \"react\";\n\nexport function useDebounce<T>(value: T, delay: number): T {\n\tconst [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n\tuseEffect(() => {\n\t\tconst timeoutId = setTimeout(() => {\n\t\t\tsetDebouncedValue(value);\n\t\t}, delay);\n\n\t\treturn () => clearTimeout(timeoutId);\n\t}, [value, delay]);\n\n\treturn debouncedValue;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\n\n/**\n * Дебаунсит вызов колбэка: частые вызовы `call(value)` не вызывают `cb` сразу,\n * а откладывают его на `delayMs` после последнего вызова.\n *\n * Важно:\n * - Всегда сохраняется *последнее* значение (last-write-wins).\n * - `flush()` немедленно вызывает cb с последним сохранённым значением (если оно есть).\n * - `cancel()` отменяет таймер и забывает последнее значение.\n * - На unmount автоматически вызывается `cancel()` чтобы не было setState после размонтирования.\n *\n * Типовой кейс:\n * - onNodesChange -> call(snapshot)\n * - pointerup / blur / unmount -> flush() (или cancel(), если не надо сохранять)\n */\nexport function useDebouncedCallback<T>(cb: (arg: T) => void, delayMs: number, options?: { flushOnUnmount?: boolean }) {\n\t/**\n\t * Храним актуальную версию cb в ref, чтобы:\n\t * - не пересоздавать дебаунсер при каждом рендере,\n\t * - не ловить устаревший замыканием cb (stale closure),\n\t * - при этом всегда вызывать самую свежую функцию.\n\t */\n\tconst cbRef = useRef<(arg: T) => void>(cb);\n\n\t/**\n\t * Обновляем актуальную версию cb после commit'а\n\t */\n\tuseEffect(() => {\n\t\tcbRef.current = cb;\n\t}, [cb]);\n\n\t/**\n\t * id таймера. null означает что таймер не активен.\n\t */\n\tconst tRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n\t/**\n\t * Последнее значение, которое мы хотим \"закоммитить\" в cb.\n\t * Используем стратегию last-write-wins.\n\t */\n\tconst lastRef = useRef<T | null>(null);\n\n\t/**\n\t * cancel():\n\t * - останавливаем таймер, если он был,\n\t * - очищаем последнее значение (ничего не будет вызвано).\n\t */\n\tconst cancel = useCallback(() => {\n\t\tif (tRef.current) {\n\t\t\tclearTimeout(tRef.current);\n\t\t\ttRef.current = null;\n\t\t}\n\t\tlastRef.current = null;\n\t}, []);\n\n\t/**\n\t * flush():\n\t * - если есть отложенное значение, вызываем cb немедленно,\n\t * - сбрасываем таймер и lastRef.\n\t *\n\t * Используется, когда нужно гарантированно сохранить \"последнее\" прямо сейчас:\n\t * - unmount\n\t * - visibilitychange/blur\n\t * - pointerup/mouseup (конец взаимодействия)\n\t */\n\tconst flush = useCallback(() => {\n\t\tconst v = lastRef.current;\n\t\tif (v === null) return;\n\n\t\t// Сбрасываем before-call, чтобы если cb вызовет call() рекурсивно,\n\t\t// мы не держали старое значение.\n\t\tlastRef.current = null;\n\n\t\tif (tRef.current) {\n\t\t\tclearTimeout(tRef.current);\n\t\t\ttRef.current = null;\n\t\t}\n\n\t\tcbRef.current(v);\n\t}, []);\n\n\t/**\n\t * call(arg):\n\t * - сохраняем arg как \"последнее значение\"\n\t * - перезапускаем таймер\n\t * - по истечении delayMs вызываем flush()\n\t */\n\tconst call = useCallback(\n\t\t(arg: T) => {\n\t\t\tlastRef.current = arg;\n\n\t\t\t// Перезапуск таймера -> классический debounce\n\t\t\tif (tRef.current) clearTimeout(tRef.current);\n\n\t\t\ttRef.current = setTimeout(() => {\n\t\t\t\ttRef.current = null;\n\t\t\t\tflush();\n\t\t\t}, delayMs);\n\t\t},\n\t\t[delayMs, flush]\n\t);\n\n\t/**\n\t * Авто-cancel на unmount:\n\t * - убирает pending timeout\n\t * - предотвращает вызовы cb после размонтирования компонента\n\t */\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (options?.flushOnUnmount) {\n\t\t\t\tflush();\n\t\t\t} else {\n\t\t\t\tcancel();\n\t\t\t}\n\t\t};\n\t}, [cancel, flush, options?.flushOnUnmount]);\n\n\treturn { call, flush, cancel };\n}\n","import { KeyboardSensor, PointerSensor, useSensor, useSensors } from \"@dnd-kit/core\";\nimport { sortableKeyboardCoordinates } from \"@dnd-kit/sortable\";\n\nexport interface UseDndSortableSensorsOptions {\n\tactivationDistance?: number;\n}\n\n/**\n * Стандартная конфигурация DnD-сенсоров для сортируемых списков.\n *\n * Зачем: исключить дублирование одинаковой настройки PointerSensor + KeyboardSensor\n * в каждом хуке персонализации (колонки, сортировки, группировки).\n *\n * @param distance — минимальное смещение указателя (px) для начала перетаскивания (по умолчанию 6).\n */\nexport function useDndSortableSensors(distanceOrOptions: number | UseDndSortableSensorsOptions = 6) {\n\tconst distance = typeof distanceOrOptions === \"number\" ? distanceOrOptions : (distanceOrOptions.activationDistance ?? 6);\n\n\treturn useSensors(\n\t\tuseSensor(PointerSensor, { activationConstraint: { distance } }),\n\t\tuseSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })\n\t);\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nimport {\n\tautoUpdate,\n\tflip,\n\tsize as floatingSize,\n\toffset,\n\tPlacement,\n\tshift,\n\tuseDismiss,\n\tuseFloating,\n\tuseInteractions,\n\tuseRole\n} from \"@floating-ui/react\";\n\nimport { findFirstEnabledIndex, findLastEnabledIndex, findNextEnabledIndex, handleKeyboardActivation } from \"../utils\";\n\n/** Геометрия, которую Floating UI вычислил для доступной стороны listbox. */\nexport type FloatingListboxSizeContext = {\n\tavailableWidth: number;\n\tavailableHeight: number;\n\tviewportWidth: number;\n\tviewportHeight: number;\n\treferenceWidth: number;\n\treferenceHeight: number;\n};\n\n/**\n * Размеры floating-элемента и CSS custom properties, которые специализированный\n * picker может вычислить из доступного viewport без собственного middleware.\n */\nexport type FloatingListboxSizeStyle = {\n\twidth?: string;\n\tminWidth?: string;\n\tmaxWidth?: string;\n\tmaxHeight?: string;\n} & {\n\t[customProperty: `--${string}`]: string | undefined;\n};\n\nexport type FloatingListboxSizeResolver = (context: FloatingListboxSizeContext) => FloatingListboxSizeStyle;\n\ntype FloatingListboxStandardSizeProperty = \"width\" | \"minWidth\" | \"maxWidth\" | \"maxHeight\";\n\ntype FloatingListboxAppliedSizeState = {\n\tcustomProperties: Set<`--${string}`>;\n\tstandardProperties: Map<FloatingListboxStandardSizeProperty, string>;\n};\n\n/** Хранит свойства и их исходные значения до императивного применения resolver. */\nconst floatingListboxAppliedSizeState = new WeakMap<HTMLElement, FloatingListboxAppliedSizeState>();\n\ninterface UseFloatingListboxParams<T> {\n\toptions: readonly T[];\n\tselectedIndex: number;\n\topen?: boolean;\n\tonOpenChange?: (open: boolean) => void;\n\tgetOptionDisabled?: (option: T) => boolean;\n\tonSelect?: (option: T) => void;\n\tdisabled?: boolean;\n\tplacement?: Placement;\n\tcloseOnSelect?: boolean;\n\tfocusFloatingOnOpen?: boolean;\n\tallowOpenWithoutOptions?: boolean;\n\trestoreFocusOnClose?: boolean;\n\tresolveFloatingSize?: FloatingListboxSizeResolver;\n}\n\nexport function useFloatingListbox<T>({\n\toptions,\n\tselectedIndex,\n\topen,\n\tonOpenChange,\n\tgetOptionDisabled,\n\tonSelect,\n\tdisabled,\n\tplacement = \"bottom-start\",\n\tcloseOnSelect = true,\n\tfocusFloatingOnOpen = true,\n\tallowOpenWithoutOptions = false,\n\trestoreFocusOnClose = true,\n\tresolveFloatingSize\n}: UseFloatingListboxParams<T>) {\n\tconst optionRefs = useRef<Array<HTMLElement | null>>([]);\n\tconst [internalOpen, setInternalOpen] = useState(false);\n\tconst resolvedOpen = open ?? internalOpen;\n\tconst setResolvedOpen = onOpenChange ?? setInternalOpen;\n\tconst [currentActiveIndex, setActiveIndex] = useState(\n\t\tselectedIndex >= 0 ? selectedIndex : findFirstEnabledIndex(options, getOptionDisabled)\n\t);\n\n\t/**\n\t * Поддерживает активный индекс в валидном состоянии при изменении набора опций\n\t * или выбранного элемента, чтобы `aria-activedescendant` всегда ссылался на\n\t * существующую и доступную опцию.\n\t */\n\tconst resolveActiveIndex = (activeIndex: number) => {\n\t\tif (options.length === 0) {\n\t\t\treturn -1;\n\t\t}\n\n\t\tif (activeIndex >= 0 && activeIndex < options.length && !getOptionDisabled?.(options[activeIndex])) {\n\t\t\treturn activeIndex;\n\t\t}\n\n\t\tif (selectedIndex >= 0 && selectedIndex < options.length && !getOptionDisabled?.(options[selectedIndex])) {\n\t\t\treturn selectedIndex;\n\t\t}\n\n\t\treturn findFirstEnabledIndex(options, getOptionDisabled);\n\t};\n\tconst activeIndex = resolveActiveIndex(currentActiveIndex);\n\n\tconst { refs, floatingStyles, context } = useFloating({\n\t\topen: resolvedOpen,\n\t\tonOpenChange: setResolvedOpen,\n\t\tplacement,\n\t\ttransform: false,\n\t\tstrategy: \"fixed\",\n\t\tmiddleware: [\n\t\t\toffset(4),\n\t\t\tflip({ padding: 8 }),\n\t\t\tshift({ padding: 8 }),\n\t\t\tfloatingSize({\n\t\t\t\tpadding: 8,\n\t\t\t\tapply({ availableWidth, availableHeight, rects, elements }) {\n\t\t\t\t\tconst viewport = elements.floating.ownerDocument.documentElement;\n\t\t\t\t\tconst floatingStyle = elements.floating.style;\n\t\t\t\t\tconst resolvedSize = resolveFloatingSize?.({\n\t\t\t\t\t\tavailableWidth,\n\t\t\t\t\t\tavailableHeight,\n\t\t\t\t\t\tviewportWidth: viewport.clientWidth,\n\t\t\t\t\t\tviewportHeight: viewport.clientHeight,\n\t\t\t\t\t\treferenceWidth: rects.reference.width,\n\t\t\t\t\t\treferenceHeight: rects.reference.height\n\t\t\t\t\t});\n\n\t\t\t\t\t/*\n\t\t\t\t\t * Сначала сбрасываем размеры предыдущего resolver: Floating UI сохраняет\n\t\t\t\t\t * один DOM-узел между режимами, поэтому старые width и CSS-переменные\n\t\t\t\t\t * иначе продолжат влиять на следующий вариант отображения.\n\t\t\t\t\t */\n\t\t\t\t\tconst previousAppliedState = floatingListboxAppliedSizeState.get(elements.floating);\n\t\t\t\t\tfor (const property of previousAppliedState?.customProperties ?? []) {\n\t\t\t\t\t\tfloatingStyle.removeProperty(property);\n\t\t\t\t\t}\n\t\t\t\t\tfor (const [property, previousValue] of previousAppliedState?.standardProperties ?? []) {\n\t\t\t\t\t\tfloatingStyle[property] = previousValue;\n\t\t\t\t\t}\n\n\t\t\t\t\tfloatingStyle.minWidth = `${rects.reference.width}px`;\n\t\t\t\t\tfloatingStyle.maxHeight = `${Math.max(availableHeight, 120)}px`;\n\n\t\t\t\t\tconst nextCustomProperties = new Set<`--${string}`>();\n\t\t\t\t\tconst nextStandardProperties = new Map<FloatingListboxStandardSizeProperty, string>();\n\t\t\t\t\tfor (const [property, value] of Object.entries(resolvedSize ?? {})) {\n\t\t\t\t\t\tif (property.startsWith(\"--\")) {\n\t\t\t\t\t\t\tconst customProperty = property as `--${string}`;\n\t\t\t\t\t\t\tif (value !== undefined) {\n\t\t\t\t\t\t\t\tfloatingStyle.setProperty(customProperty, value);\n\t\t\t\t\t\t\t\tnextCustomProperties.add(customProperty);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (value !== undefined) {\n\t\t\t\t\t\t\tconst standardProperty = property as FloatingListboxStandardSizeProperty;\n\t\t\t\t\t\t\tnextStandardProperties.set(standardProperty, floatingStyle[standardProperty]);\n\t\t\t\t\t\t\tfloatingStyle[standardProperty] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfloatingListboxAppliedSizeState.set(elements.floating, {\n\t\t\t\t\t\tcustomProperties: nextCustomProperties,\n\t\t\t\t\t\tstandardProperties: nextStandardProperties\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t})\n\t\t],\n\t\twhileElementsMounted: autoUpdate\n\t});\n\n\tconst dismiss = useDismiss(context);\n\tconst role = useRole(context, { role: \"listbox\" });\n\tconst { getFloatingProps } = useInteractions([dismiss, role]);\n\n\tconst canOpen = allowOpenWithoutOptions || options.length > 0;\n\n\tuseEffect(() => {\n\t\tif (!resolvedOpen || activeIndex < 0) {\n\t\t\treturn;\n\t\t}\n\n\t\toptionRefs.current[activeIndex]?.scrollIntoView({ block: \"nearest\" });\n\t}, [activeIndex, resolvedOpen]);\n\n\tuseEffect(() => {\n\t\tif (!resolvedOpen || !focusFloatingOnOpen) {\n\t\t\treturn;\n\t\t}\n\n\t\trequestAnimationFrame(() => {\n\t\t\trefs.floating.current?.focus();\n\t\t});\n\t}, [focusFloatingOnOpen, resolvedOpen, refs]);\n\n\tconst close = () => {\n\t\tsetResolvedOpen(false);\n\n\t\tif (restoreFocusOnClose) {\n\t\t\tconst referenceElement = refs.domReference.current;\n\t\t\tif (referenceElement instanceof HTMLElement) {\n\t\t\t\treferenceElement.focus();\n\t\t\t}\n\t\t}\n\t};\n\n\tconst openWithIndex = (nextIndex: number) => {\n\t\tif (disabled || !canOpen) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (options.length > 0) {\n\t\t\tsetActiveIndex(resolveActiveIndex(nextIndex));\n\t\t}\n\n\t\tsetResolvedOpen(true);\n\t};\n\n\tconst openList = () => {\n\t\topenWithIndex(selectedIndex >= 0 ? selectedIndex : findFirstEnabledIndex(options, getOptionDisabled));\n\t};\n\n\tconst toggleOpen = () => {\n\t\tif (resolvedOpen) {\n\t\t\tclose();\n\t\t\treturn;\n\t\t}\n\n\t\topenList();\n\t};\n\n\tconst selectOption = (option: T) => {\n\t\tif (getOptionDisabled?.(option)) {\n\t\t\treturn;\n\t\t}\n\n\t\tonSelect?.(option);\n\n\t\tif (closeOnSelect) {\n\t\t\tclose();\n\t\t}\n\t};\n\n\tconst selectActiveOption = () => {\n\t\tif (activeIndex < 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst activeOption = options[activeIndex];\n\t\tif (activeOption !== undefined) {\n\t\t\tselectOption(activeOption);\n\t\t}\n\t};\n\n\tconst moveActiveToFirst = () => {\n\t\tsetActiveIndex(findFirstEnabledIndex(options, getOptionDisabled));\n\t};\n\n\tconst moveActiveToLast = () => {\n\t\tsetActiveIndex(findLastEnabledIndex(options, getOptionDisabled));\n\t};\n\n\tconst handleReferenceKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {\n\t\tif (disabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowDown\") {\n\t\t\tevent.preventDefault();\n\n\t\t\tif (!resolvedOpen) {\n\t\t\t\topenWithIndex(selectedIndex >= 0 ? selectedIndex : findFirstEnabledIndex(options, getOptionDisabled));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetActiveIndex((currentIndex) => findNextEnabledIndex(options, resolveActiveIndex(currentIndex), 1, getOptionDisabled));\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowUp\") {\n\t\t\tevent.preventDefault();\n\n\t\t\tif (!resolvedOpen) {\n\t\t\t\topenWithIndex(selectedIndex >= 0 ? selectedIndex : findLastEnabledIndex(options, getOptionDisabled));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetActiveIndex((currentIndex) => findNextEnabledIndex(options, resolveActiveIndex(currentIndex), -1, getOptionDisabled));\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Home\" && resolvedOpen) {\n\t\t\tevent.preventDefault();\n\t\t\tmoveActiveToFirst();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"End\" && resolvedOpen) {\n\t\t\tevent.preventDefault();\n\t\t\tmoveActiveToLast();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Escape\" && resolvedOpen) {\n\t\t\tevent.preventDefault();\n\t\t\tclose();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Tab\" && resolvedOpen) {\n\t\t\tclose();\n\t\t}\n\t};\n\n\tconst handleFloatingKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {\n\t\tif (event.target !== event.currentTarget) {\n\t\t\tif (event.key === \"Escape\") {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tclose();\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowDown\") {\n\t\t\tevent.preventDefault();\n\t\t\tsetActiveIndex((currentIndex) => findNextEnabledIndex(options, resolveActiveIndex(currentIndex), 1, getOptionDisabled));\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowUp\") {\n\t\t\tevent.preventDefault();\n\t\t\tsetActiveIndex((currentIndex) => findNextEnabledIndex(options, resolveActiveIndex(currentIndex), -1, getOptionDisabled));\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Home\") {\n\t\t\tevent.preventDefault();\n\t\t\tmoveActiveToFirst();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"End\") {\n\t\t\tevent.preventDefault();\n\t\t\tmoveActiveToLast();\n\t\t\treturn;\n\t\t}\n\n\t\tif (handleKeyboardActivation(event, selectActiveOption)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Escape\") {\n\t\t\tevent.preventDefault();\n\t\t\tclose();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Tab\") {\n\t\t\tclose();\n\t\t}\n\t};\n\n\tconst getOptionId = (listId: string, index: number) => `${listId}-option-${index}`;\n\tconst getActiveOptionId = (listId: string) => (activeIndex >= 0 ? getOptionId(listId, activeIndex) : undefined);\n\n\treturn {\n\t\topen: resolvedOpen,\n\t\tsetOpen: setResolvedOpen,\n\t\tactiveIndex,\n\t\trefs,\n\t\tcontext,\n\t\tfloatingStyles,\n\t\tgetFloatingProps,\n\t\tsetReference: refs.setReference,\n\t\tsetFloating: refs.setFloating,\n\t\tsetOptionRef: (index: number, node: HTMLElement | null) => {\n\t\t\toptionRefs.current[index] = node;\n\t\t},\n\t\tclose,\n\t\topenList,\n\t\topenWithIndex,\n\t\ttoggleOpen,\n\t\tselectOption,\n\t\tselectActiveOption,\n\t\thandleReferenceKeyDown,\n\t\thandleFloatingKeyDown,\n\t\tgetOptionId,\n\t\tgetActiveOptionId\n\t};\n}\n","import { type ComponentType, useMemo } from \"react\";\n\nimport { createLazyComponent } from \"../utils/createLazyComponent\";\n\n/**\n * Хук для создания ленивой компоненты, которая будет загружена только при первом рендере.\n *\n * @example\n *\n * ```tsx\n * const MyComponent = () => {\n * const TextEditor = useLazyComponent(\n * () => import(\"@components/content/article/editor/TextEditor\"),\n * \"TextEditor\"\n * );\n *\n * return (\n * <Suspense fallback={<div>Загрузка...</div>}>\n * <TextEditor />\n * </Suspense>\n * );\n * };\n * ```\n *\n * @param importFn - функция, которая возвращает промис, который резолвится в объект с компонентами\n * @param componentName - имя компонента, который нужно загрузить\n * @returns\n */\nconst useLazyComponent = <TProps extends object>(\n\timportFn: () => Promise<Record<string, ComponentType<TProps>> | null>,\n\tcomponentName: string,\n\tcacheKey?: string\n) => {\n\treturn useMemo(() => createLazyComponent(importFn, componentName, cacheKey), [cacheKey, importFn, componentName]);\n};\n\nexport { useLazyComponent };\n","import { useEffect, useRef } from \"react\";\n\nexport function useReferenceTrace<T>(name: string, value: T) {\n\tconst previousRef = useRef(value);\n\n\tuseEffect(() => {\n\t\tif (!__DEV__) return;\n\n\t\tconst referenceChanged = !Object.is(previousRef.current, value);\n\n\t\tconsole.debug(`[render trace] ${name}`, { referenceChanged, previous: previousRef.current, current: value });\n\n\t\tpreviousRef.current = value;\n\t});\n}\n","import { useLocation } from \"@tanstack/react-router\";\n\nimport { SearchParams } from \"./types\";\n\nexport function useSearchLink<K extends PropertyKey>() {\n\tconst location = useLocation();\n\n\tconst buildLink = (params: SearchParams<K>) => {\n\t\tconst next = new URLSearchParams(location.searchStr);\n\n\t\tparams = params || [];\n\n\t\tfor (const param in params) {\n\t\t\tconst value = params[param];\n\n\t\t\tif (value) {\n\t\t\t\tnext.set(param, String(value));\n\t\t\t} else {\n\t\t\t\tnext.delete(param);\n\t\t\t}\n\t\t}\n\n\t\tconst searchString = next.toString();\n\t\treturn `${location.pathname}${searchString ? `?${searchString}` : \"\"}${location.hash}`;\n\t};\n\n\treturn { buildLink };\n}\n","import { useMemo } from \"react\";\n\nimport { AnyRouter, useNavigate, useSearch } from \"@tanstack/react-router\";\n\nimport { SearchParams, SearchParamsUpdater } from \"./types\";\n\nexport function useSearchParams<K extends PropertyKey>(allowedKeys?: (keyof K)[]) {\n\tconst params = useSearch<AnyRouter, string, false, true, SearchParams<K>>({ strict: false });\n\tconst navigate = useNavigate();\n\n\t// Фильтруем параметры, оставляя только разрешенные ключи\n\tconst filteredParams = useMemo(() => {\n\t\tif (!allowedKeys) return params;\n\n\t\treturn Object.fromEntries(Object.entries(params).filter(([key]) => allowedKeys.includes(key as keyof K))) as SearchParams<K>;\n\t}, [params, allowedKeys]);\n\n\tconst setParams = (next: SearchParamsUpdater<K>) =>\n\t\tnavigate({\n\t\t\tto: \".\",\n\t\t\tsearch: (prev: SearchParams<K>) => ({\n\t\t\t\t...prev,\n\t\t\t\t...next\n\t\t\t}),\n\t\t\treplace: true\n\t\t});\n\n\treturn { params, setParams, filteredParams };\n}\n","import { useCallback, useEffect, useRef } from \"react\";\n\nexport type ThrottledCallback<T> = {\n\t/**\n\t * Основной вход: вызывай на каждом частом событии (например, onNodesChange).\n\t * Колбэк `cb` будет вызываться не чаще, чем 1 раз в `intervalMs`.\n\t *\n\t * Стратегия: last-write-wins — если за интервал пришло много значений,\n\t * по окончании интервала будет применено последнее.\n\t */\n\tcall: (arg: T) => void;\n\n\t/**\n\t * Немедленно применить последнее накопленное значение (если оно есть),\n\t * отменив запланированный вызов (если он был).\n\t * Полезно на:\n\t * - pointerup/mouseup (конец перетаскивания)\n\t * - blur/visibilitychange/beforeunload\n\t * - unmount (если хочешь гарантированно сохранить финальное состояние)\n\t */\n\tflush: () => void;\n\n\t/**\n\t * Отменить запланированный вызов и забыть накопленное значение.\n\t * Полезно, если ты переключаешь редактор/граф и не хочешь “долетов” старых данных.\n\t */\n\tcancel: () => void;\n};\n\n/**\n * useThrottledCallback (React 19 safe)\n *\n * Проблема:\n * - В xyflow onNodesChange/onEdgesChange может сыпаться очень часто.\n * - Если каждый раз писать “сериализуемый снапшот” в zustand → лишние ререндеры/CPU/GC.\n *\n * Решение:\n * - throttle: вызывать cb не чаще, чем 1 раз в intervalMs.\n * - last-write-wins: если за интервал пришло 50 обновлений — применим последнее.\n *\n * React 19 нюанс:\n * - нельзя мутировать ref.current во время render (линтер/правило).\n * - поэтому cbRef обновляем в useEffect.\n */\nexport function useThrottledCallback<T>(\n\tcb: (arg: T) => void,\n\tintervalMs: number,\n\toptions?: { flushOnUnmount?: boolean }\n): ThrottledCallback<T> {\n\t/**\n\t * Актуальная версия cb (обновляется только после commit’а).\n\t * Это решает \"stale closure\": call/flush/cancel стабильны,\n\t * но всегда дергают самый свежий cb.\n\t */\n\tconst cbRef = useRef<(arg: T) => void>(cb);\n\n\tuseEffect(() => {\n\t\tcbRef.current = cb;\n\t}, [cb]);\n\n\t/**\n\t * Таймер отложенного выполнения.\n\t * Он нужен, когда call() пришёл раньше, чем завершился текущий throttle-интервал:\n\t * мы планируем “выполнить в конце окна”.\n\t */\n\tconst tRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n\t/**\n\t * Накопленное “последнее значение”.\n\t * Всегда хранится последний arg, пришедший через call().\n\t */\n\tconst lastRef = useRef<T | null>(null);\n\n\t/**\n\t * Время (timestamp) последнего РЕАЛЬНОГО вызова cb.\n\t * Нужно, чтобы вычислять: можно ли выполнить сейчас или нужно подождать.\n\t */\n\tconst lastInvokeTsRef = useRef<number>(0);\n\n\t/**\n\t * cancel():\n\t * - отменяем отложенный таймер,\n\t * - забываем накопленное значение.\n\t * Важно: это не вызывает cb.\n\t */\n\tconst cancel = useCallback(() => {\n\t\tif (tRef.current) {\n\t\t\tclearTimeout(tRef.current);\n\t\t\ttRef.current = null;\n\t\t}\n\t\tlastRef.current = null;\n\t}, []);\n\n\t/**\n\t * flush():\n\t * - если есть накопленное значение, вызываем cb немедленно,\n\t * - чистим таймер,\n\t * - фиксируем lastInvokeTsRef (чтобы окно throttle считалось от flush тоже).\n\t */\n\tconst flush = useCallback(() => {\n\t\tconst v = lastRef.current;\n\t\tif (v === null) return;\n\n\t\t// Сбрасываем накопленное ДО вызова cb на случай,\n\t\t// если cb внутри синхронно вызовет call() снова.\n\t\tlastRef.current = null;\n\n\t\tif (tRef.current) {\n\t\t\tclearTimeout(tRef.current);\n\t\t\ttRef.current = null;\n\t\t}\n\n\t\tlastInvokeTsRef.current = Date.now();\n\t\tcbRef.current(v);\n\t}, []);\n\n\t/**\n\t * call(arg):\n\t * 1) сохраняем arg как последнее значение (last-write-wins)\n\t * 2) если с момента последнего вызова прошло достаточно времени → вызываем сразу\n\t * 3) иначе — планируем flush ровно в момент, когда throttle-окно закончится\n\t *\n\t * При этом мы гарантируем:\n\t * - не более одного cb вызова за intervalMs\n\t * - и что “последнее значение за интервал” будет применено в конце.\n\t */\n\tconst call = useCallback(\n\t\t(arg: T) => {\n\t\t\tlastRef.current = arg;\n\n\t\t\tconst now = Date.now();\n\t\t\tconst elapsed = now - lastInvokeTsRef.current;\n\n\t\t\t// Если окно уже прошло — можно выполнить немедленно.\n\t\t\tif (elapsed >= intervalMs) {\n\t\t\t\t// Немедленный вызов = “leading edge”.\n\t\t\t\t// Берём последнее значение, очищаем lastRef и вызываем cb.\n\t\t\t\tconst v = lastRef.current;\n\t\t\t\tlastRef.current = null;\n\n\t\t\t\t// На всякий случай прибираем таймер, если он был.\n\t\t\t\tif (tRef.current) {\n\t\t\t\t\tclearTimeout(tRef.current);\n\t\t\t\t\ttRef.current = null;\n\t\t\t\t}\n\n\t\t\t\tlastInvokeTsRef.current = now;\n\t\t\t\tif (v !== null) cbRef.current(v);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Иначе — “trailing edge”: планируем выполнение в конце окна.\n\t\t\t// Важно: если таймер уже запланирован — НЕ пересоздаём,\n\t\t\t// потому что trailing-вызов должен случиться в конкретный момент (конец окна),\n\t\t\t// а значение мы и так обновляем через lastRef.current.\n\t\t\tif (!tRef.current) {\n\t\t\t\tconst wait = intervalMs - elapsed;\n\n\t\t\t\ttRef.current = setTimeout(() => {\n\t\t\t\t\ttRef.current = null;\n\t\t\t\t\t// В конце окна применяем последнее накопленное значение\n\t\t\t\t\tflush();\n\t\t\t\t}, wait);\n\t\t\t}\n\t\t},\n\t\t[intervalMs, flush]\n\t);\n\n\t/**\n\t * Cleanup на unmount:\n\t * - по умолчанию cancel (не делаем побочных эффектов при размонтировании)\n\t * - при flushOnUnmount=true — пытаемся сохранить последнее значение.\n\t *\n\t * Для твоего кейса (сериализация финального snapshot) чаще полезно flushOnUnmount=true.\n\t */\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (options?.flushOnUnmount) flush();\n\t\t\telse cancel();\n\t\t};\n\t}, [cancel, flush, options?.flushOnUnmount]);\n\n\treturn { call, flush, cancel };\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,EAAoB,GAAkB;CACrD,QAAgB;EACf,IAAI,CAAC,GAAS;EAEd,IAAM,KAAW,MAAkB;GAClC,AAAI,EAAE,WACL,EAAE,eAAe;EAEnB;EAGA,OADA,OAAO,iBAAiB,SAAS,GAAS,EAAE,SAAS,GAAM,CAAC,SAC/C,OAAO,oBAAoB,SAAS,CAAO;CACzD,GAAG,CAAC,CAAO,CAAC;AACb;;;AClBA,SAAgB,EAAe,GAAU,GAAkB;CAC1D,IAAM,CAAC,GAAgB,KAAqB,EAAY,CAAK;CAU7D,OARA,QAAgB;EACf,IAAM,IAAY,iBAAiB;GAClC,EAAkB,CAAK;EACxB,GAAG,CAAK;EAER,aAAa,aAAa,CAAS;CACpC,GAAG,CAAC,GAAO,CAAK,CAAC,GAEV;AACR;;;ACEA,SAAgB,EAAwB,GAAsB,GAAiB,GAAwC;CAOtH,IAAM,IAAQ,EAAyB,CAAE;CAKzC,QAAgB;EACf,EAAM,UAAU;CACjB,GAAG,CAAC,CAAE,CAAC;CAKP,IAAM,IAAO,EAA6C,IAAI,GAMxD,IAAU,EAAiB,IAAI,GAO/B,IAAS,QAAkB;EAKhC,AAJA,AAEC,EAAK,aADL,aAAa,EAAK,OAAO,GACV,OAEhB,EAAQ,UAAU;CACnB,GAAG,CAAC,CAAC,GAYC,IAAQ,QAAkB;EAC/B,IAAM,IAAI,EAAQ;EACd,MAAM,SAIV,EAAQ,UAAU,MAElB,AAEC,EAAK,aADL,aAAa,EAAK,OAAO,GACV,OAGhB,EAAM,QAAQ,CAAC;CAChB,GAAG,CAAC,CAAC,GAQC,IAAO,GACX,MAAW;EAMX,AALA,EAAQ,UAAU,GAGd,EAAK,WAAS,aAAa,EAAK,OAAO,GAE3C,EAAK,UAAU,iBAAiB;GAE/B,AADA,EAAK,UAAU,MACf,EAAM;EACP,GAAG,CAAO;CACX,GACA,CAAC,GAAS,CAAK,CAChB;CAiBA,OAVA,cACc;EACZ,AAAI,GAAS,iBACZ,EAAM,IAEN,EAAO;CAET,GACE;EAAC;EAAQ;EAAO,GAAS;CAAc,CAAC,GAEpC;EAAE;EAAM;EAAO;CAAO;AAC9B;;;ACxGA,SAAgB,EAAsB,IAA2D,GAAG;CAGnG,OAAO,EACN,EAAU,GAAe,EAAE,sBAAsB,EAAE,UAHnC,OAAO,KAAsB,WAAW,IAAqB,EAAkB,sBAAsB,EAGzD,EAAE,CAAC,GAC/D,EAAU,GAAgB,EAAE,kBAAkB,EAA4B,CAAC,CAC5E;AACD;;;AC4BA,IAAM,oBAAkC,IAAI,QAAsD;AAkBlG,SAAgB,EAAsB,EACrC,YACA,kBACA,SACA,iBACA,sBACA,aACA,aACA,eAAY,gBACZ,mBAAgB,IAChB,yBAAsB,IACtB,6BAA0B,IAC1B,yBAAsB,IACtB,0BAC+B;CAC/B,IAAM,IAAa,EAAkC,CAAC,CAAC,GACjD,CAAC,GAAc,KAAmB,EAAS,EAAK,GAChD,IAAe,KAAQ,GACvB,IAAkB,KAAgB,GAClC,CAAC,GAAoB,KAAkB,EAC5C,KAAiB,IAAI,IAAgB,EAAsB,GAAS,CAAiB,CACtF,GAOM,KAAsB,MACvB,EAAQ,WAAW,IACf,KAGJ,KAAe,KAAK,IAAc,EAAQ,UAAU,CAAC,IAAoB,EAAQ,EAAY,IACzF,IAGJ,KAAiB,KAAK,IAAgB,EAAQ,UAAU,CAAC,IAAoB,EAAQ,EAAc,IAC/F,IAGD,EAAsB,GAAS,CAAiB,GAElD,IAAc,EAAmB,CAAkB,GAEnD,EAAE,SAAM,mBAAgB,eAAY,EAAY;EACrD,MAAM;EACN,cAAc;EACd;EACA,WAAW;EACX,UAAU;EACV,YAAY;GACX,EAAO,CAAC;GACR,EAAK,EAAE,SAAS,EAAE,CAAC;GACnB,EAAM,EAAE,SAAS,EAAE,CAAC;GACpB,EAAa;IACZ,SAAS;IACT,MAAM,EAAE,mBAAgB,oBAAiB,UAAO,eAAY;KAC3D,IAAM,IAAW,EAAS,SAAS,cAAc,iBAC3C,IAAgB,EAAS,SAAS,OAClC,IAAe,IAAsB;MAC1C;MACA;MACA,eAAe,EAAS;MACxB,gBAAgB,EAAS;MACzB,gBAAgB,EAAM,UAAU;MAChC,iBAAiB,EAAM,UAAU;KAClC,CAAC,GAOK,IAAuB,EAAgC,IAAI,EAAS,QAAQ;KAClF,KAAK,IAAM,KAAY,GAAsB,oBAAoB,CAAC,GACjE,EAAc,eAAe,CAAQ;KAEtC,KAAK,IAAM,CAAC,GAAU,MAAkB,GAAsB,sBAAsB,CAAC,GACpF,EAAc,KAAY;KAI3B,AADA,EAAc,WAAW,GAAG,EAAM,UAAU,MAAM,KAClD,EAAc,YAAY,GAAG,KAAK,IAAI,GAAiB,GAAG,EAAE;KAE5D,IAAM,oBAAuB,IAAI,IAAmB,GAC9C,oBAAyB,IAAI,IAAiD;KACpF,KAAK,IAAM,CAAC,GAAU,MAAU,OAAO,QAAQ,KAAgB,CAAC,CAAC,GAAG;MACnE,IAAI,EAAS,WAAW,IAAI,GAAG;OAC9B,IAAM,IAAiB;OACvB,AAAI,MAAU,KAAA,MACb,EAAc,YAAY,GAAgB,CAAK,GAC/C,EAAqB,IAAI,CAAc;OAExC;MACD;MAEA,IAAI,MAAU,KAAA,GAAW;OACxB,IAAM,IAAmB;OAEzB,AADA,EAAuB,IAAI,GAAkB,EAAc,EAAiB,GAC5E,EAAc,KAAoB;MACnC;KACD;KACA,EAAgC,IAAI,EAAS,UAAU;MACtD,kBAAkB;MAClB,oBAAoB;KACrB,CAAC;IACF;GACD,CAAC;EACF;EACA,sBAAsB;CACvB,CAAC,GAIK,EAAE,wBAAqB,EAAgB,CAF7B,EAAW,CAEmB,GADjC,EAAQ,GAAS,EAAE,MAAM,UAAU,CACO,CAAI,CAAC,GAEtD,IAAU,KAA2B,EAAQ,SAAS;CAU5D,AARA,QAAgB;EACX,CAAC,KAAgB,IAAc,KAInC,EAAW,QAAQ,EAAY,EAAE,eAAe,EAAE,OAAO,UAAU,CAAC;CACrE,GAAG,CAAC,GAAa,CAAY,CAAC,GAE9B,QAAgB;EACX,CAAC,KAAgB,CAAC,KAItB,4BAA4B;GAC3B,EAAK,SAAS,SAAS,MAAM;EAC9B,CAAC;CACF,GAAG;EAAC;EAAqB;EAAc;CAAI,CAAC;CAE5C,IAAM,UAAc;EAGnB,IAFA,EAAgB,EAAK,GAEjB,GAAqB;GACxB,IAAM,IAAmB,EAAK,aAAa;GAC3C,AAAI,aAA4B,eAC/B,EAAiB,MAAM;EAEzB;CACD,GAEM,KAAiB,MAAsB;EACxC,KAAY,CAAC,MAIb,EAAQ,SAAS,KACpB,EAAe,EAAmB,CAAS,CAAC,GAG7C,EAAgB,EAAI;CACrB,GAEM,UAAiB;EACtB,EAAc,KAAiB,IAAI,IAAgB,EAAsB,GAAS,CAAiB,CAAC;CACrG,GAEM,UAAmB;EACxB,IAAI,GAAc;GACjB,EAAM;GACN;EACD;EAEA,EAAS;CACV,GAEM,KAAgB,MAAc;EAC/B,IAAoB,CAAM,MAI9B,IAAW,CAAM,GAEb,KACH,EAAM;CAER,GAEM,UAA2B;EAChC,IAAI,IAAc,GACjB;EAGD,IAAM,IAAe,EAAQ;EAC7B,AAAI,MAAiB,KAAA,KACpB,EAAa,CAAY;CAE3B,GAEM,UAA0B;EAC/B,EAAe,EAAsB,GAAS,CAAiB,CAAC;CACjE,GAEM,UAAyB;EAC9B,EAAe,EAAqB,GAAS,CAAiB,CAAC;CAChE,GAEM,KAA0B,MAA4C;EACvE,QAIJ;OAAI,EAAM,QAAQ,aAAa;IAG9B,IAFA,EAAM,eAAe,GAEjB,CAAC,GAAc;KAClB,EAAc,KAAiB,IAAI,IAAgB,EAAsB,GAAS,CAAiB,CAAC;KACpG;IACD;IAEA,GAAgB,MAAiB,EAAqB,GAAS,EAAmB,CAAY,GAAG,GAAG,CAAiB,CAAC;IACtH;GACD;GAEA,IAAI,EAAM,QAAQ,WAAW;IAG5B,IAFA,EAAM,eAAe,GAEjB,CAAC,GAAc;KAClB,EAAc,KAAiB,IAAI,IAAgB,EAAqB,GAAS,CAAiB,CAAC;KACnG;IACD;IAEA,GAAgB,MAAiB,EAAqB,GAAS,EAAmB,CAAY,GAAG,IAAI,CAAiB,CAAC;IACvH;GACD;GAEA,IAAI,EAAM,QAAQ,UAAU,GAAc;IAEzC,AADA,EAAM,eAAe,GACrB,EAAkB;IAClB;GACD;GAEA,IAAI,EAAM,QAAQ,SAAS,GAAc;IAExC,AADA,EAAM,eAAe,GACrB,EAAiB;IACjB;GACD;GAEA,IAAI,EAAM,QAAQ,YAAY,GAAc;IAE3C,AADA,EAAM,eAAe,GACrB,EAAM;IACN;GACD;GAEA,AAAI,EAAM,QAAQ,SAAS,KAC1B,EAAM;EAjCP;CAmCD,GAEM,MAAyB,MAA4C;EAC1E,IAAI,EAAM,WAAW,EAAM,eAAe;GACzC,AAAI,EAAM,QAAQ,aACjB,EAAM,eAAe,GACrB,EAAM;GAGP;EACD;EAEA,IAAI,EAAM,QAAQ,aAAa;GAE9B,AADA,EAAM,eAAe,GACrB,GAAgB,MAAiB,EAAqB,GAAS,EAAmB,CAAY,GAAG,GAAG,CAAiB,CAAC;GACtH;EACD;EAEA,IAAI,EAAM,QAAQ,WAAW;GAE5B,AADA,EAAM,eAAe,GACrB,GAAgB,MAAiB,EAAqB,GAAS,EAAmB,CAAY,GAAG,IAAI,CAAiB,CAAC;GACvH;EACD;EAEA,IAAI,EAAM,QAAQ,QAAQ;GAEzB,AADA,EAAM,eAAe,GACrB,EAAkB;GAClB;EACD;EAEA,IAAI,EAAM,QAAQ,OAAO;GAExB,AADA,EAAM,eAAe,GACrB,EAAiB;GACjB;EACD;EAEI,OAAyB,GAAO,CAAkB,GAItD;OAAI,EAAM,QAAQ,UAAU;IAE3B,AADA,EAAM,eAAe,GACrB,EAAM;IACN;GACD;GAEA,AAAI,EAAM,QAAQ,SACjB,EAAM;EAHP;CAKD,GAEM,KAAe,GAAgB,MAAkB,GAAG,EAAO,UAAU;CAG3E,OAAO;EACN,MAAM;EACN,SAAS;EACT;EACA;EACA;EACA;EACA;EACA,cAAc,EAAK;EACnB,aAAa,EAAK;EAClB,eAAe,GAAe,MAA6B;GAC1D,EAAW,QAAQ,KAAS;EAC7B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,oBAxB0B,MAAoB,KAAe,IAAI,EAAY,GAAQ,CAAW,IAAI,KAAA;CAyBrG;AACD;;;ACpXA,IAAM,KACL,GACA,GACA,MAEO,QAAc,EAAoB,GAAU,GAAe,CAAQ,GAAG;CAAC;CAAU;CAAU;AAAa,CAAC;;;AC/BjH,SAAgB,EAAqB,GAAc,GAAU;CAC5D,IAAM,IAAc,EAAO,CAAK;CAEhC,QAAgB;EACf,IAAI,CAAC,SAAS;EAEd,IAAM,IAAmB,CAAC,OAAO,GAAG,EAAY,SAAS,CAAK;EAI9D,AAFA,QAAQ,MAAM,kBAAkB,KAAQ;GAAE;GAAkB,UAAU,EAAY;GAAS,SAAS;EAAM,CAAC,GAE3G,EAAY,UAAU;CACvB,CAAC;AACF;;;ACVA,SAAgB,IAAuC;CACtD,IAAM,IAAW,EAAY;CAqB7B,OAAO,EAAE,YAnBU,MAA4B;EAC9C,IAAM,IAAO,IAAI,gBAAgB,EAAS,SAAS;EAEnD,MAAmB,CAAC;EAEpB,KAAK,IAAM,KAAS,GAAQ;GAC3B,IAAM,IAAQ,EAAO;GAErB,AAAI,IACH,EAAK,IAAI,GAAO,OAAO,CAAK,CAAC,IAE7B,EAAK,OAAO,CAAK;EAEnB;EAEA,IAAM,IAAe,EAAK,SAAS;EACnC,OAAO,GAAG,EAAS,WAAW,IAAe,IAAI,MAAiB,KAAK,EAAS;CACjF,EAEmB;AACpB;;;ACrBA,SAAgB,EAAuC,GAA2B;CACjF,IAAM,IAAS,EAA2D,EAAE,QAAQ,GAAM,CAAC,GACrF,IAAW,EAAY;CAmB7B,OAAO;EAAE;EAAQ,YAVE,MAClB,EAAS;GACR,IAAI;GACJ,SAAS,OAA2B;IACnC,GAAG;IACH,GAAG;GACJ;GACA,SAAS;EACV,CAAC;EAE0B,gBAhBL,QACjB,IAEE,OAAO,YAAY,OAAO,QAAQ,CAAM,CAAC,CAAC,QAAQ,CAAC,OAAS,EAAY,SAAS,CAAc,CAAC,CAAC,IAF/E,GAGvB,CAAC,GAAQ,CAAW,CAYK;CAAe;AAC5C;;;ACgBA,SAAgB,EACf,GACA,GACA,GACuB;CAMvB,IAAM,IAAQ,EAAyB,CAAE;CAEzC,QAAgB;EACf,EAAM,UAAU;CACjB,GAAG,CAAC,CAAE,CAAC;CAOP,IAAM,IAAO,EAA6C,IAAI,GAMxD,IAAU,EAAiB,IAAI,GAM/B,IAAkB,EAAe,CAAC,GAQlC,IAAS,QAAkB;EAKhC,AAJA,AAEC,EAAK,aADL,aAAa,EAAK,OAAO,GACV,OAEhB,EAAQ,UAAU;CACnB,GAAG,CAAC,CAAC,GAQC,IAAQ,QAAkB;EAC/B,IAAM,IAAI,EAAQ;EACd,MAAM,SAIV,EAAQ,UAAU,MAElB,AAEC,EAAK,aADL,aAAa,EAAK,OAAO,GACV,OAGhB,EAAgB,UAAU,KAAK,IAAI,GACnC,EAAM,QAAQ,CAAC;CAChB,GAAG,CAAC,CAAC,GAYC,IAAO,GACX,MAAW;EACX,EAAQ,UAAU;EAElB,IAAM,IAAM,KAAK,IAAI,GACf,IAAU,IAAM,EAAgB;EAGtC,IAAI,KAAW,GAAY;GAG1B,IAAM,IAAI,EAAQ;GAUlB,AATA,EAAQ,UAAU,MAGlB,AAEC,EAAK,aADL,aAAa,EAAK,OAAO,GACV,OAGhB,EAAgB,UAAU,GACtB,MAAM,QAAM,EAAM,QAAQ,CAAC;GAC/B;EACD;EAMA,IAAI,CAAC,EAAK,SAAS;GAClB,IAAM,IAAO,IAAa;GAE1B,EAAK,UAAU,iBAAiB;IAG/B,AAFA,EAAK,UAAU,MAEf,EAAM;GACP,GAAG,CAAI;EACR;CACD,GACA,CAAC,GAAY,CAAK,CACnB;CAgBA,OAPA,cACc;EACZ,AAAI,GAAS,iBAAgB,EAAM,IAC9B,EAAO;CACb,GACE;EAAC;EAAQ;EAAO,GAAS;CAAc,CAAC,GAEpC;EAAE;EAAM;EAAO;CAAO;AAC9B"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/hooks/useBlockBrowserZoom.ts","../../src/hooks/useDebounce.ts","../../src/hooks/useDebounceCallback.ts","../../src/hooks/useDndSortableSensors.ts","../../src/hooks/useFloatingListbox.ts","../../src/hooks/useLazyComponent.ts","../../src/hooks/useReferenceTrace.ts","../../src/hooks/useSearchLink.ts","../../src/hooks/useSearchParams.ts","../../src/hooks/useThrottledCallback.ts"],"sourcesContent":["import { useEffect } from \"react\";\n\n/**\n * Глобально отключает браузерный zoom (ctrl+wheel).\n *\n * @param enabled если true — блокируем нативный зум страницы\n */\nexport function useBlockBrowserZoom(enabled: boolean) {\n\tuseEffect(() => {\n\t\tif (!enabled) return;\n\n\t\tconst handler = (e: WheelEvent) => {\n\t\t\tif (e.ctrlKey) {\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener(\"wheel\", handler, { passive: false });\n\t\treturn () => window.removeEventListener(\"wheel\", handler);\n\t}, [enabled]);\n}\n","import { useEffect, useState } from \"react\";\n\nexport function useDebounce<T>(value: T, delay: number): T {\n\tconst [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n\tuseEffect(() => {\n\t\tconst timeoutId = setTimeout(() => {\n\t\t\tsetDebouncedValue(value);\n\t\t}, delay);\n\n\t\treturn () => clearTimeout(timeoutId);\n\t}, [value, delay]);\n\n\treturn debouncedValue;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\n\n/**\n * Дебаунсит вызов колбэка: частые вызовы `call(value)` не вызывают `cb` сразу,\n * а откладывают его на `delayMs` после последнего вызова.\n *\n * Важно:\n * - Всегда сохраняется *последнее* значение (last-write-wins).\n * - `flush()` немедленно вызывает cb с последним сохранённым значением (если оно есть).\n * - `cancel()` отменяет таймер и забывает последнее значение.\n * - На unmount автоматически вызывается `cancel()` чтобы не было setState после размонтирования.\n *\n * Типовой кейс:\n * - onNodesChange -> call(snapshot)\n * - pointerup / blur / unmount -> flush() (или cancel(), если не надо сохранять)\n */\nexport function useDebouncedCallback<T>(cb: (arg: T) => void, delayMs: number, options?: { flushOnUnmount?: boolean }) {\n\t/**\n\t * Храним актуальную версию cb в ref, чтобы:\n\t * - не пересоздавать дебаунсер при каждом рендере,\n\t * - не ловить устаревший замыканием cb (stale closure),\n\t * - при этом всегда вызывать самую свежую функцию.\n\t */\n\tconst cbRef = useRef<(arg: T) => void>(cb);\n\n\t/**\n\t * Обновляем актуальную версию cb после commit'а\n\t */\n\tuseEffect(() => {\n\t\tcbRef.current = cb;\n\t}, [cb]);\n\n\t/**\n\t * id таймера. null означает что таймер не активен.\n\t */\n\tconst tRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n\t/**\n\t * Последнее значение, которое мы хотим \"закоммитить\" в cb.\n\t * Используем стратегию last-write-wins.\n\t */\n\tconst lastRef = useRef<T | null>(null);\n\n\t/**\n\t * cancel():\n\t * - останавливаем таймер, если он был,\n\t * - очищаем последнее значение (ничего не будет вызвано).\n\t */\n\tconst cancel = useCallback(() => {\n\t\tif (tRef.current) {\n\t\t\tclearTimeout(tRef.current);\n\t\t\ttRef.current = null;\n\t\t}\n\t\tlastRef.current = null;\n\t}, []);\n\n\t/**\n\t * flush():\n\t * - если есть отложенное значение, вызываем cb немедленно,\n\t * - сбрасываем таймер и lastRef.\n\t *\n\t * Используется, когда нужно гарантированно сохранить \"последнее\" прямо сейчас:\n\t * - unmount\n\t * - visibilitychange/blur\n\t * - pointerup/mouseup (конец взаимодействия)\n\t */\n\tconst flush = useCallback(() => {\n\t\tconst v = lastRef.current;\n\t\tif (v === null) return;\n\n\t\t// Сбрасываем before-call, чтобы если cb вызовет call() рекурсивно,\n\t\t// мы не держали старое значение.\n\t\tlastRef.current = null;\n\n\t\tif (tRef.current) {\n\t\t\tclearTimeout(tRef.current);\n\t\t\ttRef.current = null;\n\t\t}\n\n\t\tcbRef.current(v);\n\t}, []);\n\n\t/**\n\t * call(arg):\n\t * - сохраняем arg как \"последнее значение\"\n\t * - перезапускаем таймер\n\t * - по истечении delayMs вызываем flush()\n\t */\n\tconst call = useCallback(\n\t\t(arg: T) => {\n\t\t\tlastRef.current = arg;\n\n\t\t\t// Перезапуск таймера -> классический debounce\n\t\t\tif (tRef.current) clearTimeout(tRef.current);\n\n\t\t\ttRef.current = setTimeout(() => {\n\t\t\t\ttRef.current = null;\n\t\t\t\tflush();\n\t\t\t}, delayMs);\n\t\t},\n\t\t[delayMs, flush]\n\t);\n\n\t/**\n\t * Авто-cancel на unmount:\n\t * - убирает pending timeout\n\t * - предотвращает вызовы cb после размонтирования компонента\n\t */\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (options?.flushOnUnmount) {\n\t\t\t\tflush();\n\t\t\t} else {\n\t\t\t\tcancel();\n\t\t\t}\n\t\t};\n\t}, [cancel, flush, options?.flushOnUnmount]);\n\n\treturn { call, flush, cancel };\n}\n","import { KeyboardSensor, PointerSensor, useSensor, useSensors } from \"@dnd-kit/core\";\nimport { sortableKeyboardCoordinates } from \"@dnd-kit/sortable\";\n\nexport interface UseDndSortableSensorsOptions {\n\tactivationDistance?: number;\n}\n\n/**\n * Стандартная конфигурация DnD-сенсоров для сортируемых списков.\n *\n * Зачем: исключить дублирование одинаковой настройки PointerSensor + KeyboardSensor\n * в каждом хуке персонализации (колонки, сортировки, группировки).\n *\n * @param distance — минимальное смещение указателя (px) для начала перетаскивания (по умолчанию 6).\n */\nexport function useDndSortableSensors(distanceOrOptions: number | UseDndSortableSensorsOptions = 6) {\n\tconst distance = typeof distanceOrOptions === \"number\" ? distanceOrOptions : (distanceOrOptions.activationDistance ?? 6);\n\n\treturn useSensors(\n\t\tuseSensor(PointerSensor, { activationConstraint: { distance } }),\n\t\tuseSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })\n\t);\n}\n","import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\n\nimport {\n\tautoPlacement,\n\tautoUpdate,\n\tflip,\n\toffset,\n\tPlacement,\n\tshift,\n\tsize as floatingSize,\n\tuseDismiss,\n\tuseFloating,\n\tuseInteractions,\n\tuseRole\n} from \"@floating-ui/react\";\n\nimport { findFirstEnabledIndex, findLastEnabledIndex, findNextEnabledIndex, handleKeyboardActivation } from \"../utils\";\n\n/** Геометрия, которую Floating UI вычислил для доступной стороны listbox. */\nexport type FloatingListboxSizeContext = {\n\tavailableWidth: number;\n\tavailableHeight: number;\n\tviewportWidth: number;\n\tviewportHeight: number;\n\treferenceWidth: number;\n\treferenceHeight: number;\n};\n\n/**\n * Размеры floating-элемента и CSS custom properties, которые специализированный\n * picker может вычислить из доступного viewport без собственного middleware.\n */\nexport type FloatingListboxSizeStyle = {\n\twidth?: string;\n\tminWidth?: string;\n\tmaxWidth?: string;\n\tmaxHeight?: string;\n} & {\n\t[customProperty: `--${string}`]: string | undefined;\n};\n\nexport type FloatingListboxSizeResolver = (context: FloatingListboxSizeContext) => FloatingListboxSizeStyle;\n\n/** Стратегия выбора стороны для floating-элемента относительно reference. */\nexport type FloatingListboxPlacementStrategy = \"flip\" | \"auto\";\n\ntype FloatingListboxStandardSizeProperty = \"width\" | \"minWidth\" | \"maxWidth\" | \"maxHeight\";\n\ntype FloatingListboxAppliedSizeState = {\n\tcustomProperties: Set<`--${string}`>;\n\tstandardProperties: Map<FloatingListboxStandardSizeProperty, string>;\n};\n\n/** Хранит свойства и их исходные значения до императивного применения resolver. */\nconst floatingListboxAppliedSizeState = new WeakMap<HTMLElement, FloatingListboxAppliedSizeState>();\n\n/** Хранит актуальный resolver отдельно от callback, который Floating UI может переиспользовать. */\nconst floatingListboxSizeResolvers = new WeakMap<object, FloatingListboxSizeResolver>();\n\n/** Полный набор выровненных сторон для поиска наиболее просторного положения. */\nconst FLOATING_LISTBOX_AUTO_PLACEMENTS: Placement[] = [\n\t\"bottom-start\",\n\t\"bottom-end\",\n\t\"top-start\",\n\t\"top-end\",\n\t\"left-start\",\n\t\"left-end\",\n\t\"right-start\",\n\t\"right-end\"\n];\n\ninterface UseFloatingListboxParams<T> {\n\toptions: readonly T[];\n\tselectedIndex: number;\n\topen?: boolean;\n\tonOpenChange?: (open: boolean) => void;\n\tgetOptionDisabled?: (option: T) => boolean;\n\tonSelect?: (option: T) => void;\n\tdisabled?: boolean;\n\tplacement?: Placement;\n\t/** `auto` сравнивает свободное место сверху, снизу, слева и справа. */\n\tplacementStrategy?: FloatingListboxPlacementStrategy;\n\tcloseOnSelect?: boolean;\n\tfocusFloatingOnOpen?: boolean;\n\tallowOpenWithoutOptions?: boolean;\n\trestoreFocusOnClose?: boolean;\n\tresolveFloatingSize?: FloatingListboxSizeResolver;\n}\n\nexport function useFloatingListbox<T>({\n\toptions,\n\tselectedIndex,\n\topen,\n\tonOpenChange,\n\tgetOptionDisabled,\n\tonSelect,\n\tdisabled,\n\tplacement = \"bottom-start\",\n\tplacementStrategy = \"flip\",\n\tcloseOnSelect = true,\n\tfocusFloatingOnOpen = true,\n\tallowOpenWithoutOptions = false,\n\trestoreFocusOnClose = true,\n\tresolveFloatingSize\n}: UseFloatingListboxParams<T>) {\n\tconst optionRefs = useRef<Array<HTMLElement | null>>([]);\n\tconst [internalOpen, setInternalOpen] = useState(false);\n\tconst resolvedOpen = open ?? internalOpen;\n\tconst setResolvedOpen = onOpenChange ?? setInternalOpen;\n\tconst [currentActiveIndex, setActiveIndex] = useState(\n\t\tselectedIndex >= 0 ? selectedIndex : findFirstEnabledIndex(options, getOptionDisabled)\n\t);\n\tconst [floatingSizeResolverOwner] = useState<object>(() => ({}));\n\n\t/**\n\t * Поддерживает активный индекс в валидном состоянии при изменении набора опций\n\t * или выбранного элемента, чтобы `aria-activedescendant` всегда ссылался на\n\t * существующую и доступную опцию.\n\t */\n\tconst resolveActiveIndex = (activeIndex: number) => {\n\t\tif (options.length === 0) {\n\t\t\treturn -1;\n\t\t}\n\n\t\tif (activeIndex >= 0 && activeIndex < options.length && !getOptionDisabled?.(options[activeIndex])) {\n\t\t\treturn activeIndex;\n\t\t}\n\n\t\tif (selectedIndex >= 0 && selectedIndex < options.length && !getOptionDisabled?.(options[selectedIndex])) {\n\t\t\treturn selectedIndex;\n\t\t}\n\n\t\treturn findFirstEnabledIndex(options, getOptionDisabled);\n\t};\n\tconst activeIndex = resolveActiveIndex(currentActiveIndex);\n\tconst placementMiddleware =\n\t\tplacementStrategy === \"auto\"\n\t\t\t? autoPlacement({\n\t\t\t\t\tallowedPlacements: FLOATING_LISTBOX_AUTO_PLACEMENTS,\n\t\t\t\t\t/*\n\t\t\t\t\t * Свободную сторону сравниваем по main axis. Варианты start/end при\n\t\t\t\t\t * этом всё равно исключаются autoPlacement, если не помещаются по\n\t\t\t\t\t * cross axis.\n\t\t\t\t\t */\n\t\t\t\t\tcrossAxis: false,\n\t\t\t\t\tpadding: 8\n\t\t\t\t})\n\t\t\t: flip({ padding: 8 });\n\n\tconst { refs, floatingStyles, context, update } = useFloating({\n\t\topen: resolvedOpen,\n\t\tonOpenChange: setResolvedOpen,\n\t\tplacement,\n\t\ttransform: false,\n\t\tstrategy: \"fixed\",\n\t\tmiddleware: [\n\t\t\toffset(4),\n\t\t\tplacementMiddleware,\n\t\t\tshift({ padding: 8 }),\n\t\t\tfloatingSize({\n\t\t\t\tpadding: 8,\n\t\t\t\tapply({ availableWidth, availableHeight, rects, elements }) {\n\t\t\t\t\tconst viewport = elements.floating.ownerDocument.documentElement;\n\t\t\t\t\tconst floatingStyle = elements.floating.style;\n\t\t\t\t\tconst resolvedSize = floatingListboxSizeResolvers.get(floatingSizeResolverOwner)?.({\n\t\t\t\t\t\tavailableWidth,\n\t\t\t\t\t\tavailableHeight,\n\t\t\t\t\t\tviewportWidth: viewport.clientWidth,\n\t\t\t\t\t\tviewportHeight: viewport.clientHeight,\n\t\t\t\t\t\treferenceWidth: rects.reference.width,\n\t\t\t\t\t\treferenceHeight: rects.reference.height\n\t\t\t\t\t});\n\n\t\t\t\t\t/*\n\t\t\t\t\t * Сначала сбрасываем размеры предыдущего resolver: Floating UI сохраняет\n\t\t\t\t\t * один DOM-узел между режимами, поэтому старые width и CSS-переменные\n\t\t\t\t\t * иначе продолжат влиять на следующий вариант отображения.\n\t\t\t\t\t */\n\t\t\t\t\tconst previousAppliedState = floatingListboxAppliedSizeState.get(elements.floating);\n\t\t\t\t\tfor (const property of previousAppliedState?.customProperties ?? []) {\n\t\t\t\t\t\tfloatingStyle.removeProperty(property);\n\t\t\t\t\t}\n\t\t\t\t\tfor (const [property, previousValue] of previousAppliedState?.standardProperties ?? []) {\n\t\t\t\t\t\tfloatingStyle[property] = previousValue;\n\t\t\t\t\t}\n\n\t\t\t\t\tfloatingStyle.minWidth = `${rects.reference.width}px`;\n\t\t\t\t\tfloatingStyle.maxHeight = `${Math.max(availableHeight, 120)}px`;\n\n\t\t\t\t\tconst nextCustomProperties = new Set<`--${string}`>();\n\t\t\t\t\tconst nextStandardProperties = new Map<FloatingListboxStandardSizeProperty, string>();\n\t\t\t\t\tfor (const [property, value] of Object.entries(resolvedSize ?? {})) {\n\t\t\t\t\t\tif (property.startsWith(\"--\")) {\n\t\t\t\t\t\t\tconst customProperty = property as `--${string}`;\n\t\t\t\t\t\t\tif (value !== undefined) {\n\t\t\t\t\t\t\t\tfloatingStyle.setProperty(customProperty, value);\n\t\t\t\t\t\t\t\tnextCustomProperties.add(customProperty);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (value !== undefined) {\n\t\t\t\t\t\t\tconst standardProperty = property as FloatingListboxStandardSizeProperty;\n\t\t\t\t\t\t\tnextStandardProperties.set(standardProperty, floatingStyle[standardProperty]);\n\t\t\t\t\t\t\tfloatingStyle[standardProperty] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfloatingListboxAppliedSizeState.set(elements.floating, {\n\t\t\t\t\t\tcustomProperties: nextCustomProperties,\n\t\t\t\t\t\tstandardProperties: nextStandardProperties\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t})\n\t\t],\n\t\twhileElementsMounted: autoUpdate\n\t});\n\tconst hasFloatingSizeResolver = resolveFloatingSize !== undefined;\n\n\t/*\n\t * Floating UI сравнивает middleware структурно и может сохранить первый\n\t * size.apply. WeakMap позволяет этому callback читать актуальный resolver после\n\t * загрузки OData-узлов, не пересоздавая конкурирующие middleware.\n\t */\n\tuseLayoutEffect(() => {\n\t\tif (resolveFloatingSize) {\n\t\t\tfloatingListboxSizeResolvers.set(floatingSizeResolverOwner, resolveFloatingSize);\n\t\t} else {\n\t\t\tfloatingListboxSizeResolvers.delete(floatingSizeResolverOwner);\n\t\t}\n\n\t\treturn () => {\n\t\t\tfloatingListboxSizeResolvers.delete(floatingSizeResolverOwner);\n\t\t};\n\t}, [floatingSizeResolverOwner, resolveFloatingSize]);\n\n\t/**\n\t * Асинхронно загруженные или отфильтрованные опции могут не изменить внешний\n\t * rect popup: grid с прежним числом строк остаётся того же размера. Явный\n\t * update повторно запускает placement и size middleware после commit списка.\n\t */\n\tuseLayoutEffect(() => {\n\t\tif (!resolvedOpen || !hasFloatingSizeResolver) {\n\t\t\treturn;\n\t\t}\n\n\t\tvoid update();\n\t}, [hasFloatingSizeResolver, options.length, resolvedOpen, update]);\n\n\tconst dismiss = useDismiss(context);\n\tconst role = useRole(context, { role: \"listbox\" });\n\tconst { getFloatingProps } = useInteractions([dismiss, role]);\n\n\tconst canOpen = allowOpenWithoutOptions || options.length > 0;\n\n\tuseEffect(() => {\n\t\tif (!resolvedOpen || activeIndex < 0) {\n\t\t\treturn;\n\t\t}\n\n\t\toptionRefs.current[activeIndex]?.scrollIntoView({ block: \"nearest\" });\n\t}, [activeIndex, resolvedOpen]);\n\n\tuseEffect(() => {\n\t\tif (!resolvedOpen || !focusFloatingOnOpen) {\n\t\t\treturn;\n\t\t}\n\n\t\trequestAnimationFrame(() => {\n\t\t\trefs.floating.current?.focus();\n\t\t});\n\t}, [focusFloatingOnOpen, resolvedOpen, refs]);\n\n\tconst close = () => {\n\t\tsetResolvedOpen(false);\n\n\t\tif (restoreFocusOnClose) {\n\t\t\tconst referenceElement = refs.domReference.current;\n\t\t\tif (referenceElement instanceof HTMLElement) {\n\t\t\t\treferenceElement.focus();\n\t\t\t}\n\t\t}\n\t};\n\n\tconst openWithIndex = (nextIndex: number) => {\n\t\tif (disabled || !canOpen) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (options.length > 0) {\n\t\t\tsetActiveIndex(resolveActiveIndex(nextIndex));\n\t\t}\n\n\t\tsetResolvedOpen(true);\n\t};\n\n\tconst openList = () => {\n\t\topenWithIndex(selectedIndex >= 0 ? selectedIndex : findFirstEnabledIndex(options, getOptionDisabled));\n\t};\n\n\tconst toggleOpen = () => {\n\t\tif (resolvedOpen) {\n\t\t\tclose();\n\t\t\treturn;\n\t\t}\n\n\t\topenList();\n\t};\n\n\tconst selectOption = (option: T) => {\n\t\tif (getOptionDisabled?.(option)) {\n\t\t\treturn;\n\t\t}\n\n\t\tonSelect?.(option);\n\n\t\tif (closeOnSelect) {\n\t\t\tclose();\n\t\t}\n\t};\n\n\tconst selectActiveOption = () => {\n\t\tif (activeIndex < 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst activeOption = options[activeIndex];\n\t\tif (activeOption !== undefined) {\n\t\t\tselectOption(activeOption);\n\t\t}\n\t};\n\n\tconst moveActiveToFirst = () => {\n\t\tsetActiveIndex(findFirstEnabledIndex(options, getOptionDisabled));\n\t};\n\n\tconst moveActiveToLast = () => {\n\t\tsetActiveIndex(findLastEnabledIndex(options, getOptionDisabled));\n\t};\n\n\tconst handleReferenceKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {\n\t\tif (disabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowDown\") {\n\t\t\tevent.preventDefault();\n\n\t\t\tif (!resolvedOpen) {\n\t\t\t\topenWithIndex(selectedIndex >= 0 ? selectedIndex : findFirstEnabledIndex(options, getOptionDisabled));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetActiveIndex((currentIndex) => findNextEnabledIndex(options, resolveActiveIndex(currentIndex), 1, getOptionDisabled));\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowUp\") {\n\t\t\tevent.preventDefault();\n\n\t\t\tif (!resolvedOpen) {\n\t\t\t\topenWithIndex(selectedIndex >= 0 ? selectedIndex : findLastEnabledIndex(options, getOptionDisabled));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetActiveIndex((currentIndex) => findNextEnabledIndex(options, resolveActiveIndex(currentIndex), -1, getOptionDisabled));\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Home\" && resolvedOpen) {\n\t\t\tevent.preventDefault();\n\t\t\tmoveActiveToFirst();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"End\" && resolvedOpen) {\n\t\t\tevent.preventDefault();\n\t\t\tmoveActiveToLast();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Escape\" && resolvedOpen) {\n\t\t\tevent.preventDefault();\n\t\t\tclose();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Tab\" && resolvedOpen) {\n\t\t\tclose();\n\t\t}\n\t};\n\n\tconst handleFloatingKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {\n\t\tif (event.target !== event.currentTarget) {\n\t\t\tif (event.key === \"Escape\") {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tclose();\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowDown\") {\n\t\t\tevent.preventDefault();\n\t\t\tsetActiveIndex((currentIndex) => findNextEnabledIndex(options, resolveActiveIndex(currentIndex), 1, getOptionDisabled));\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowUp\") {\n\t\t\tevent.preventDefault();\n\t\t\tsetActiveIndex((currentIndex) => findNextEnabledIndex(options, resolveActiveIndex(currentIndex), -1, getOptionDisabled));\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Home\") {\n\t\t\tevent.preventDefault();\n\t\t\tmoveActiveToFirst();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"End\") {\n\t\t\tevent.preventDefault();\n\t\t\tmoveActiveToLast();\n\t\t\treturn;\n\t\t}\n\n\t\tif (handleKeyboardActivation(event, selectActiveOption)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Escape\") {\n\t\t\tevent.preventDefault();\n\t\t\tclose();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"Tab\") {\n\t\t\tclose();\n\t\t}\n\t};\n\n\tconst getOptionId = (listId: string, index: number) => `${listId}-option-${index}`;\n\tconst getActiveOptionId = (listId: string) => (activeIndex >= 0 ? getOptionId(listId, activeIndex) : undefined);\n\n\treturn {\n\t\topen: resolvedOpen,\n\t\tsetOpen: setResolvedOpen,\n\t\tactiveIndex,\n\t\trefs,\n\t\tcontext,\n\t\tfloatingStyles,\n\t\tgetFloatingProps,\n\t\tsetReference: refs.setReference,\n\t\tsetFloating: refs.setFloating,\n\t\tsetOptionRef: (index: number, node: HTMLElement | null) => {\n\t\t\toptionRefs.current[index] = node;\n\t\t},\n\t\tclose,\n\t\topenList,\n\t\topenWithIndex,\n\t\ttoggleOpen,\n\t\tselectOption,\n\t\tselectActiveOption,\n\t\thandleReferenceKeyDown,\n\t\thandleFloatingKeyDown,\n\t\tgetOptionId,\n\t\tgetActiveOptionId\n\t};\n}\n","import { type ComponentType, useMemo } from \"react\";\n\nimport { createLazyComponent } from \"../utils/createLazyComponent\";\n\n/**\n * Хук для создания ленивой компоненты, которая будет загружена только при первом рендере.\n *\n * @example\n *\n * ```tsx\n * const MyComponent = () => {\n * const TextEditor = useLazyComponent(\n * () => import(\"@components/content/article/editor/TextEditor\"),\n * \"TextEditor\"\n * );\n *\n * return (\n * <Suspense fallback={<div>Загрузка...</div>}>\n * <TextEditor />\n * </Suspense>\n * );\n * };\n * ```\n *\n * @param importFn - функция, которая возвращает промис, который резолвится в объект с компонентами\n * @param componentName - имя компонента, который нужно загрузить\n * @returns\n */\nconst useLazyComponent = <TProps extends object>(\n\timportFn: () => Promise<Record<string, ComponentType<TProps>> | null>,\n\tcomponentName: string,\n\tcacheKey?: string\n) => {\n\treturn useMemo(() => createLazyComponent(importFn, componentName, cacheKey), [cacheKey, importFn, componentName]);\n};\n\nexport { useLazyComponent };\n","import { useEffect, useRef } from \"react\";\n\nexport function useReferenceTrace<T>(name: string, value: T) {\n\tconst previousRef = useRef(value);\n\n\tuseEffect(() => {\n\t\tif (!__DEV__) return;\n\n\t\tconst referenceChanged = !Object.is(previousRef.current, value);\n\n\t\tconsole.debug(`[render trace] ${name}`, { referenceChanged, previous: previousRef.current, current: value });\n\n\t\tpreviousRef.current = value;\n\t});\n}\n","import { useLocation } from \"@tanstack/react-router\";\n\nimport { SearchParams } from \"./types\";\n\nexport function useSearchLink<K extends PropertyKey>() {\n\tconst location = useLocation();\n\n\tconst buildLink = (params: SearchParams<K>) => {\n\t\tconst next = new URLSearchParams(location.searchStr);\n\n\t\tparams = params || [];\n\n\t\tfor (const param in params) {\n\t\t\tconst value = params[param];\n\n\t\t\tif (value) {\n\t\t\t\tnext.set(param, String(value));\n\t\t\t} else {\n\t\t\t\tnext.delete(param);\n\t\t\t}\n\t\t}\n\n\t\tconst searchString = next.toString();\n\t\treturn `${location.pathname}${searchString ? `?${searchString}` : \"\"}${location.hash}`;\n\t};\n\n\treturn { buildLink };\n}\n","import { useMemo } from \"react\";\n\nimport { AnyRouter, useNavigate, useSearch } from \"@tanstack/react-router\";\n\nimport { SearchParams, SearchParamsUpdater } from \"./types\";\n\nexport function useSearchParams<K extends PropertyKey>(allowedKeys?: (keyof K)[]) {\n\tconst params = useSearch<AnyRouter, string, false, true, SearchParams<K>>({ strict: false });\n\tconst navigate = useNavigate();\n\n\t// Фильтруем параметры, оставляя только разрешенные ключи\n\tconst filteredParams = useMemo(() => {\n\t\tif (!allowedKeys) return params;\n\n\t\treturn Object.fromEntries(Object.entries(params).filter(([key]) => allowedKeys.includes(key as keyof K))) as SearchParams<K>;\n\t}, [params, allowedKeys]);\n\n\tconst setParams = (next: SearchParamsUpdater<K>) =>\n\t\tnavigate({\n\t\t\tto: \".\",\n\t\t\tsearch: (prev: SearchParams<K>) => ({\n\t\t\t\t...prev,\n\t\t\t\t...next\n\t\t\t}),\n\t\t\treplace: true\n\t\t});\n\n\treturn { params, setParams, filteredParams };\n}\n","import { useCallback, useEffect, useRef } from \"react\";\n\nexport type ThrottledCallback<T> = {\n\t/**\n\t * Основной вход: вызывай на каждом частом событии (например, onNodesChange).\n\t * Колбэк `cb` будет вызываться не чаще, чем 1 раз в `intervalMs`.\n\t *\n\t * Стратегия: last-write-wins — если за интервал пришло много значений,\n\t * по окончании интервала будет применено последнее.\n\t */\n\tcall: (arg: T) => void;\n\n\t/**\n\t * Немедленно применить последнее накопленное значение (если оно есть),\n\t * отменив запланированный вызов (если он был).\n\t * Полезно на:\n\t * - pointerup/mouseup (конец перетаскивания)\n\t * - blur/visibilitychange/beforeunload\n\t * - unmount (если хочешь гарантированно сохранить финальное состояние)\n\t */\n\tflush: () => void;\n\n\t/**\n\t * Отменить запланированный вызов и забыть накопленное значение.\n\t * Полезно, если ты переключаешь редактор/граф и не хочешь “долетов” старых данных.\n\t */\n\tcancel: () => void;\n};\n\n/**\n * useThrottledCallback (React 19 safe)\n *\n * Проблема:\n * - В xyflow onNodesChange/onEdgesChange может сыпаться очень часто.\n * - Если каждый раз писать “сериализуемый снапшот” в zustand → лишние ререндеры/CPU/GC.\n *\n * Решение:\n * - throttle: вызывать cb не чаще, чем 1 раз в intervalMs.\n * - last-write-wins: если за интервал пришло 50 обновлений — применим последнее.\n *\n * React 19 нюанс:\n * - нельзя мутировать ref.current во время render (линтер/правило).\n * - поэтому cbRef обновляем в useEffect.\n */\nexport function useThrottledCallback<T>(\n\tcb: (arg: T) => void,\n\tintervalMs: number,\n\toptions?: { flushOnUnmount?: boolean }\n): ThrottledCallback<T> {\n\t/**\n\t * Актуальная версия cb (обновляется только после commit’а).\n\t * Это решает \"stale closure\": call/flush/cancel стабильны,\n\t * но всегда дергают самый свежий cb.\n\t */\n\tconst cbRef = useRef<(arg: T) => void>(cb);\n\n\tuseEffect(() => {\n\t\tcbRef.current = cb;\n\t}, [cb]);\n\n\t/**\n\t * Таймер отложенного выполнения.\n\t * Он нужен, когда call() пришёл раньше, чем завершился текущий throttle-интервал:\n\t * мы планируем “выполнить в конце окна”.\n\t */\n\tconst tRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n\t/**\n\t * Накопленное “последнее значение”.\n\t * Всегда хранится последний arg, пришедший через call().\n\t */\n\tconst lastRef = useRef<T | null>(null);\n\n\t/**\n\t * Время (timestamp) последнего РЕАЛЬНОГО вызова cb.\n\t * Нужно, чтобы вычислять: можно ли выполнить сейчас или нужно подождать.\n\t */\n\tconst lastInvokeTsRef = useRef<number>(0);\n\n\t/**\n\t * cancel():\n\t * - отменяем отложенный таймер,\n\t * - забываем накопленное значение.\n\t * Важно: это не вызывает cb.\n\t */\n\tconst cancel = useCallback(() => {\n\t\tif (tRef.current) {\n\t\t\tclearTimeout(tRef.current);\n\t\t\ttRef.current = null;\n\t\t}\n\t\tlastRef.current = null;\n\t}, []);\n\n\t/**\n\t * flush():\n\t * - если есть накопленное значение, вызываем cb немедленно,\n\t * - чистим таймер,\n\t * - фиксируем lastInvokeTsRef (чтобы окно throttle считалось от flush тоже).\n\t */\n\tconst flush = useCallback(() => {\n\t\tconst v = lastRef.current;\n\t\tif (v === null) return;\n\n\t\t// Сбрасываем накопленное ДО вызова cb на случай,\n\t\t// если cb внутри синхронно вызовет call() снова.\n\t\tlastRef.current = null;\n\n\t\tif (tRef.current) {\n\t\t\tclearTimeout(tRef.current);\n\t\t\ttRef.current = null;\n\t\t}\n\n\t\tlastInvokeTsRef.current = Date.now();\n\t\tcbRef.current(v);\n\t}, []);\n\n\t/**\n\t * call(arg):\n\t * 1) сохраняем arg как последнее значение (last-write-wins)\n\t * 2) если с момента последнего вызова прошло достаточно времени → вызываем сразу\n\t * 3) иначе — планируем flush ровно в момент, когда throttle-окно закончится\n\t *\n\t * При этом мы гарантируем:\n\t * - не более одного cb вызова за intervalMs\n\t * - и что “последнее значение за интервал” будет применено в конце.\n\t */\n\tconst call = useCallback(\n\t\t(arg: T) => {\n\t\t\tlastRef.current = arg;\n\n\t\t\tconst now = Date.now();\n\t\t\tconst elapsed = now - lastInvokeTsRef.current;\n\n\t\t\t// Если окно уже прошло — можно выполнить немедленно.\n\t\t\tif (elapsed >= intervalMs) {\n\t\t\t\t// Немедленный вызов = “leading edge”.\n\t\t\t\t// Берём последнее значение, очищаем lastRef и вызываем cb.\n\t\t\t\tconst v = lastRef.current;\n\t\t\t\tlastRef.current = null;\n\n\t\t\t\t// На всякий случай прибираем таймер, если он был.\n\t\t\t\tif (tRef.current) {\n\t\t\t\t\tclearTimeout(tRef.current);\n\t\t\t\t\ttRef.current = null;\n\t\t\t\t}\n\n\t\t\t\tlastInvokeTsRef.current = now;\n\t\t\t\tif (v !== null) cbRef.current(v);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Иначе — “trailing edge”: планируем выполнение в конце окна.\n\t\t\t// Важно: если таймер уже запланирован — НЕ пересоздаём,\n\t\t\t// потому что trailing-вызов должен случиться в конкретный момент (конец окна),\n\t\t\t// а значение мы и так обновляем через lastRef.current.\n\t\t\tif (!tRef.current) {\n\t\t\t\tconst wait = intervalMs - elapsed;\n\n\t\t\t\ttRef.current = setTimeout(() => {\n\t\t\t\t\ttRef.current = null;\n\t\t\t\t\t// В конце окна применяем последнее накопленное значение\n\t\t\t\t\tflush();\n\t\t\t\t}, wait);\n\t\t\t}\n\t\t},\n\t\t[intervalMs, flush]\n\t);\n\n\t/**\n\t * Cleanup на unmount:\n\t * - по умолчанию cancel (не делаем побочных эффектов при размонтировании)\n\t * - при flushOnUnmount=true — пытаемся сохранить последнее значение.\n\t *\n\t * Для твоего кейса (сериализация финального snapshot) чаще полезно flushOnUnmount=true.\n\t */\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (options?.flushOnUnmount) flush();\n\t\t\telse cancel();\n\t\t};\n\t}, [cancel, flush, options?.flushOnUnmount]);\n\n\treturn { call, flush, cancel };\n}\n"],"mappings":"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"}
@@ -21,6 +21,8 @@ export type FloatingListboxSizeStyle = {
21
21
  [customProperty: `--${string}`]: string | undefined;
22
22
  };
23
23
  export type FloatingListboxSizeResolver = (context: FloatingListboxSizeContext) => FloatingListboxSizeStyle;
24
+ /** Стратегия выбора стороны для floating-элемента относительно reference. */
25
+ export type FloatingListboxPlacementStrategy = "flip" | "auto";
24
26
  interface UseFloatingListboxParams<T> {
25
27
  options: readonly T[];
26
28
  selectedIndex: number;
@@ -30,13 +32,15 @@ interface UseFloatingListboxParams<T> {
30
32
  onSelect?: (option: T) => void;
31
33
  disabled?: boolean;
32
34
  placement?: Placement;
35
+ /** `auto` сравнивает свободное место сверху, снизу, слева и справа. */
36
+ placementStrategy?: FloatingListboxPlacementStrategy;
33
37
  closeOnSelect?: boolean;
34
38
  focusFloatingOnOpen?: boolean;
35
39
  allowOpenWithoutOptions?: boolean;
36
40
  restoreFocusOnClose?: boolean;
37
41
  resolveFloatingSize?: FloatingListboxSizeResolver;
38
42
  }
39
- export declare function useFloatingListbox<T>({ options, selectedIndex, open, onOpenChange, getOptionDisabled, onSelect, disabled, placement, closeOnSelect, focusFloatingOnOpen, allowOpenWithoutOptions, restoreFocusOnClose, resolveFloatingSize }: UseFloatingListboxParams<T>): {
43
+ export declare function useFloatingListbox<T>({ options, selectedIndex, open, onOpenChange, getOptionDisabled, onSelect, disabled, placement, placementStrategy, closeOnSelect, focusFloatingOnOpen, allowOpenWithoutOptions, restoreFocusOnClose, resolveFloatingSize }: UseFloatingListboxParams<T>): {
40
44
  open: boolean;
41
45
  setOpen: (open: boolean) => void;
42
46
  activeIndex: number;
@@ -1 +1 @@
1
- {"version":3,"file":"useFloatingListbox.d.ts","sourceRoot":"","sources":["../../src/hooks/useFloatingListbox.ts"],"names":[],"mappings":"AAEA,OAAO,EAKN,SAAS,EAMT,MAAM,oBAAoB,CAAC;AAI5B,6EAA6E;AAC7E,MAAM,MAAM,0BAA0B,GAAG;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG;IACH,CAAC,cAAc,EAAE,KAAK,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,CAAC,OAAO,EAAE,0BAA0B,KAAK,wBAAwB,CAAC;AAY5G,UAAU,wBAAwB,CAAC,CAAC;IACnC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC;IAC3C,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;CAClD;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,EACrC,OAAO,EACP,aAAa,EACb,IAAI,EACJ,YAAY,EACZ,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,SAA0B,EAC1B,aAAoB,EACpB,mBAA0B,EAC1B,uBAA+B,EAC/B,mBAA0B,EAC1B,mBAAmB,EACnB,EAAE,wBAAwB,CAAC,CAAC,CAAC;;oBA1BP,OAAO,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BA0Uf,MAAM,QAAQ,WAAW,GAAG,IAAI;;;+BA1KrB,MAAM;;2BAyBV,CAAC;;oCA+BQ,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC;mCAoDjC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC;0BAiDzC,MAAM,SAAS,MAAM;gCACf,MAAM;EA0BzC"}
1
+ {"version":3,"file":"useFloatingListbox.d.ts","sourceRoot":"","sources":["../../src/hooks/useFloatingListbox.ts"],"names":[],"mappings":"AAEA,OAAO,EAKN,SAAS,EAOT,MAAM,oBAAoB,CAAC;AAI5B,6EAA6E;AAC7E,MAAM,MAAM,0BAA0B,GAAG;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG;IACH,CAAC,cAAc,EAAE,KAAK,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,CAAC,OAAO,EAAE,0BAA0B,KAAK,wBAAwB,CAAC;AAE5G,6EAA6E;AAC7E,MAAM,MAAM,gCAAgC,GAAG,MAAM,GAAG,MAAM,CAAC;AA2B/D,UAAU,wBAAwB,CAAC,CAAC;IACnC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC;IAC3C,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,gCAAgC,CAAC;IACrD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;CAClD;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,EACrC,OAAO,EACP,aAAa,EACb,IAAI,EACJ,YAAY,EACZ,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,SAA0B,EAC1B,iBAA0B,EAC1B,aAAoB,EACpB,mBAA0B,EAC1B,uBAA+B,EAC/B,mBAA0B,EAC1B,mBAAmB,EACnB,EAAE,wBAAwB,CAAC,CAAC,CAAC;;oBA7BP,OAAO,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BA0Xf,MAAM,QAAQ,WAAW,GAAG,IAAI;;;+BA1KrB,MAAM;;2BAyBV,CAAC;;oCA+BQ,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC;mCAoDjC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC;0BAiDzC,MAAM,SAAS,MAAM;gCACf,MAAM;EA0BzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"filterDefinitions.d.ts","sourceRoot":"","sources":["../../src/odata-service/filterDefinitions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"filterDefinitions.d.ts","sourceRoot":"","sources":["../../src/odata-service/filterDefinitions.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { $ as e, A as t, B as n, C as r, Ct as i, D as a, Dt as o, E as s, Et as c, F as l, G as u, H as d, I as f, J as p, K as m, L as h, M as g, N as _, O as v, Ot as y, P as b, Q as x, R as S, S as C, St as w, T, Tt as E, U as D, V as O, W as k, X as A, Y as j, Z as M, _ as N, _t as P, a as F, at as I, b as L, bt as R, c as z, ct as B, d as V, dt as H, et as U, f as W, ft as G, g as K, gt as q, h as J, ht as Y, i as X, it as Z, j as Q, k as $, kt as ee, l as te, lt as ne, m as re, mt as ie, n as ae, nt as oe, o as se, ot as ce, p as le, pt as ue, q as de, r as fe, rt as pe, s as me, st as he, t as ge, tt as _e, u as ve, ut as ye, v as be, vt as xe, w as Se, wt as Ce, x as we, xt as Te, y as Ee, yt as De, z as Oe } from "../chunks/odata-service-DNcNP2RM.js";
1
+ import { $ as e, A as t, B as n, C as r, Ct as i, D as a, Dt as o, E as s, Et as c, F as l, G as u, H as d, I as f, J as p, K as m, L as h, M as g, N as _, O as v, Ot as y, P as b, Q as x, R as S, S as C, St as w, T, Tt as E, U as D, V as O, W as k, X as A, Y as j, Z as M, _ as N, _t as P, a as F, at as I, b as L, bt as R, c as z, ct as B, d as V, dt as H, et as U, f as W, ft as G, g as K, gt as q, h as J, ht as Y, i as X, it as Z, j as Q, k as $, kt as ee, l as te, lt as ne, m as re, mt as ie, n as ae, nt as oe, o as se, ot as ce, p as le, pt as ue, q as de, r as fe, rt as pe, s as me, st as he, t as ge, tt as _e, u as ve, ut as ye, v as be, vt as xe, w as Se, wt as Ce, x as we, xt as Te, y as Ee, yt as De, z as Oe } from "../chunks/odata-service-CEfjPsY9.js";
2
2
  export { c as BASE_META_TYPES, o as BASE_META_TYPE_LABELS, n as FILTER_OPERATIONS, C as FORCED_CODE_TEXT_IDS, O as FilterOperation, V as assertSqlFilterFieldId, U as buildEntityOperationPath, _e as buildEntityParameters, oe as buildEntityPath, pe as buildFunctionImportParameters, Z as buildFunctionImportPath, d as buildODataFilter, D as buildODataFilterRecursive, K as buildODataOrder, N as buildODataOrderBy, I as buildParameterEntries, W as buildSqlFilter, a as collapseChainedODataSegmentFilterValues, x as collectFilterableColumns, e as collectFilterableColumnsIds, v as compileFiltersToExpression, ce as createBooleanFormatter, he as createDateFormatter, k as createFilter, u as createFilterBetween, m as createFilterContains, de as createFilterEqual, p as createFilterEqualFalsy, B as createFormatter, ne as createNumberFormatter, le as createSqlFilterEqual, re as createSqlFilterIn, ye as createStringFormatter, H as defaultControlTypeValue, G as defaultODataTypeValue, $ as flattenFilterValuesToODataDependencies, ue as getBaseTypeFromODataType, ie as getFormatter, Y as getFormatterForBaseType, q as getFormattersFor, P as getFormattersForBaseType, be as getSortIndex, Ee as getSortIndicator, y as isBaseMetaType, fe as isBaseValue, Te as isBooleanSafe, w as isDateSafe, t as isFilterLocalComponentId, j as isFilterOperation, r as isForcedCodeTextFamilyId, Se as isForcedCodeTextId, i as isNumberSafe, me as isODataBooleanType, z as isODataDateType, te as isODataIntegerType, ve as isODataNumericType, J as isSqlFilterScalarValue, Ce as isStringSafe, A as mergeFilterExpressions, Q as mergeFilterValuePatch, X as normalizeBaseValue, g as normalizeDictionaryCodeKey, F as normalizeRangeValue, xe as odataFormatValue, De as odataParseValue, R as odataParseValueByMetadata, E as odataTypeSchemas, T as parseServiceMetadata, ee as resolveBaseTypeLabel, L as resolveEffectiveSorts, s as resolveMetadataColumnLabel, _ as resolveODataFilterDefinitionActiveColumnIds, b as resolveODataFilterDefinitionColumnIds, M as resolveOperationLabel, l as sanitizeFilterBinding, f as sanitizeFilterConditionGroup, h as sanitizeFilterDefinitions, S as sanitizeFilterValue, Oe as sanitizeFilterValues, we as toggleSort, ge as unwrapODataParams, se as unwrapODataQueryResult, ae as wrapODataParams };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryuzaki13/react-foundation-lib",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
4
4
  "description": "Reusable React and TypeScript foundation utilities, hooks, and primitives.",
5
5
  "license": "MIT",
6
6
  "author": "Ryuzaki13",
@@ -1 +0,0 @@
1
- {"version":3,"file":"odata-service-DNcNP2RM.js","names":[],"sources":["../../src/formatters/boolean/parseAbapBoolean.ts","../../src/formatters/number/parseNumber.ts","../../src/odata-service/baseTypes.ts","../../src/odata-service/schema.ts","../../src/odata-service/formatters.ts","../../src/odata-service/builder.ts","../../src/odata-service/columns.ts","../../src/odata-service/filters.ts","../../src/odata-service/filterDefinitions.ts","../../src/odata-service/parser.ts","../../src/odata-service/sorts.ts","../../src/odata-service/sqlFilters.ts","../../src/odata-service/typesValidation.ts","../../src/odata-service/unwrapODataQueryResult.ts","../../src/odata-service/utils.ts","../../src/odata-service/wrapParams.ts"],"sourcesContent":["export function parseAbapBoolean(value: unknown): boolean {\n\tif (value && typeof value === \"string\" && value === \"X\") return true;\n\treturn false;\n}\n\nexport function parseBoolean(value: unknown): boolean {\n\tif (!value) return false;\n\tif (typeof value === \"string\") {\n\t\treturn [\"true\", \"x\", \"1\"].includes(value.toLowerCase());\n\t}\n\treturn Boolean(value);\n}\n","/**\n * SAP-like парсер: пробелы/NBSP как группировка, ',' как десятичный.\n * Возвращает только finite number или undefined.\n */\nexport function toFiniteNumber(v: unknown): number | undefined {\n\tif (typeof v === \"number\") return Number.isFinite(v) ? v : undefined;\n\tif (typeof v !== \"string\") return undefined;\n\n\tconst trimmed = v.trim();\n\tif (!trimmed) return undefined;\n\n\tconst parsed = Number(trimmed);\n\tif (Number.isFinite(parsed)) return parsed;\n\n\t// SAP-like: убираем пробелы/NBSP/NNBSP, поддерживаем ',' как decimal\n\n\tlet s = \"\";\n\tfor (let i = 0; i < trimmed.length; i++) {\n\t\tconst c = trimmed.charCodeAt(i);\n\t\tif (c === 32 || c === 160 || c === 8239 || c === 39 /*'*/) continue;\n\t\ts += trimmed[i];\n\t}\n\n\tconst hasComma = s.indexOf(\",\") !== -1;\n\tconst hasDot = s.indexOf(\".\") !== -1;\n\n\tif (hasComma && hasDot) {\n\t\ts = s.replace(/,/g, \"\"); // 1,234.56 -> 1234.56\n\t} else if (hasComma) {\n\t\ts = s.replace(/,/g, \".\"); // 1234,56 -> 1234.56\n\t}\n\n\tconst n = Number(s);\n\treturn Number.isFinite(n) ? n : undefined;\n}\n\nexport function parseNumber(v: unknown): number {\n\treturn toFiniteNumber(v) ?? 0;\n}\n\nexport function isPositiveValue(value: unknown): boolean {\n\tconst normalizedValue = toFiniteNumber(value);\n\tif (normalizedValue) {\n\t\treturn normalizedValue > 0;\n\t}\n\n\treturn false;\n}\n\n/**\n * Читает положительное целое число из неизвестного значения.\n */\nexport function toPositiveInteger(value: unknown): number | undefined {\n\tconst normalizedValue = toFiniteNumber(value);\n\tif (normalizedValue === undefined || !Number.isInteger(normalizedValue) || normalizedValue <= 0) {\n\t\treturn undefined;\n\t}\n\n\treturn normalizedValue;\n}\n","import type { BaseMetaType } from \"./types\";\n\nexport const BASE_META_TYPES = Object.freeze([\"string\", \"number\", \"boolean\", \"date\"] as const) satisfies readonly BaseMetaType[];\n\nconst BASE_META_TYPE_SET: ReadonlySet<string> = new Set(BASE_META_TYPES);\n\nexport const BASE_META_TYPE_LABELS: Readonly<Record<BaseMetaType, string>> = Object.freeze({\n\tstring: \"строка\",\n\tnumber: \"число\",\n\tboolean: \"boolean\",\n\tdate: \"дата\"\n});\n\nexport function isBaseMetaType(type: unknown): type is BaseMetaType {\n\treturn typeof type === \"string\" && BASE_META_TYPE_SET.has(type);\n}\n\nexport function resolveBaseTypeLabel(type: BaseMetaType): string {\n\treturn BASE_META_TYPE_LABELS[type];\n}\n","import { z } from \"zod\";\n\nimport type { ODataMetaType } from \"./types\";\n\nexport const odataTypeSchemas: Record<ODataMetaType, z.ZodTypeAny> = {\n\tstring: z.string(),\n\tguid: z.uuid().or(z.string().regex(/^[0-9a-fA-F-]+$/, \"Invalid GUID\")),\n\tboolean: z.boolean(),\n\tint: z.number().int(),\n\tlong: z.number().int(),\n\tfloat: z.number(),\n\tdecimal: z.number(),\n\tdouble: z.number(),\n\tdatetime: z.date(),\n\tdatetimeOffset: z.date(),\n\ttime: z.date(),\n\tbinary: z.string(),\n\tbyte: z.number().int().min(0).max(255)\n};\n\n// Type Guards на основе Zod\nfunction isType<T>(value: unknown, schema: z.ZodType<T>): value is T {\n\treturn schema.safeParse(value).success;\n}\n\n// Специфичные Type Guards\nexport function isStringSafe(value: unknown): value is string {\n\treturn isType(value, odataTypeSchemas.string);\n}\n\nexport function isNumberSafe(value: unknown): value is number {\n\treturn isType(value, odataTypeSchemas.float); // используем float как базовый числовой тип\n}\n\nexport function isBooleanSafe(value: unknown): value is boolean {\n\treturn isType(value, odataTypeSchemas.boolean);\n}\n\nexport function isDateSafe(value: unknown): value is Date {\n\treturn isType(value, odataTypeSchemas.datetime);\n}\n","import { z } from \"zod\";\n\nimport { parseAbapBoolean } from \"../formatters/boolean/parseAbapBoolean\";\nimport { formatDateAsAbapDate } from \"../formatters/date/formatDate\";\nimport { parseDate } from \"../formatters/date/parseDate\";\nimport { parseNumber } from \"../formatters/number/parseNumber\";\nimport { ODataDateFormat } from \"../odata/dateUtils\";\n\nimport { odataTypeSchemas } from \"./schema\";\n\nimport type {\n\tBaseMetaType,\n\tEntityParameterProperty,\n\tODataBooleanType,\n\tODataDateType,\n\tODataFormatterDescription,\n\tODataMetaType,\n\tODataNumericType,\n\tODataStringType\n} from \"./types\";\n\n/**\n * NOTE: Запрещено экспортировать!\n */\nfunction formatValidValue(type: ODataMetaType, validValue: unknown) {\n\tswitch (type) {\n\t\tcase \"string\":\n\t\t\treturn `'${String(validValue).replace(/'/g, \"''\")}'`;\n\t\tcase \"guid\":\n\t\t\treturn `guid'${String(validValue)}'`;\n\t\tcase \"boolean\":\n\t\t\treturn validValue ? \"'X'\" : \"' '\";\n\t\tcase \"long\":\n\t\t\treturn `${String(validValue)}L`;\n\t\tcase \"float\":\n\t\t\treturn `${String(validValue)}F`;\n\t\tcase \"decimal\":\n\t\t\treturn `${String(validValue)}M`;\n\t\tcase \"double\":\n\t\t\treturn `${String(validValue)}D`;\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\tif (!(validValue instanceof Date)) {\n\t\t\t\tthrow new Error(`Неверная дата для типа '${type}': ${validValue}`);\n\t\t\t}\n\t\t\treturn ODataDateFormat[type](validValue);\n\t\tcase \"binary\":\n\t\t\treturn `binary'${validValue}'`;\n\t\tcase \"byte\":\n\t\tcase \"int\":\n\t\t\treturn `${String(validValue)}`;\n\n\t\tdefault:\n\t\t\tthrow new Error(`Неподдерживаемый тип: ${type satisfies never}`);\n\t}\n}\n\n/**\n * Форматирует значение для использования в URL в соответствии с типом OData\n * @param type Тип данных\n * @param value Значение\n * @returns Отформатированная строка\n */\nexport function odataFormatValue(type: ODataMetaType, value: unknown): string {\n\tconst schema = odataTypeSchemas[type];\n\tconst result = schema.safeParse(value);\n\tif (!result.success) {\n\t\tthrow new Error(`Некорректное значение для типа '${type}': ${result.error.issues[0]?.message ?? value}`);\n\t}\n\n\treturn formatValidValue(type, result.data);\n}\n\ntype ODataMetadataValueDescriptor = Pick<EntityParameterProperty, \"type\" | \"abapBooleanLike\">;\n\nfunction tryParseBooleanValue(value: unknown): boolean | undefined {\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"number\") {\n\t\tif (value === 1) return true;\n\t\tif (value === 0) return false;\n\t\treturn undefined;\n\t}\n\tif (typeof value !== \"string\") return undefined;\n\n\tif (value === \"X\") return true;\n\tif (value === \" \" || value === \"\") return false;\n\n\tconst normalized = value.trim().toLowerCase();\n\tif (normalized === \"true\" || normalized === \"1\") return true;\n\tif (normalized === \"false\" || normalized === \"0\") return false;\n\n\treturn undefined;\n}\n\nfunction tryParseAbapBooleanLikeValue(value: unknown): boolean | undefined {\n\tif (value == null) return false;\n\tif (typeof value !== \"string\") return undefined;\n\tif (value === \"X\" || value === \" \" || value === \"\") {\n\t\treturn parseAbapBoolean(value);\n\t}\n\treturn undefined;\n}\n\nexport function odataParseValue(type: ODataBooleanType, value: unknown): boolean | unknown;\nexport function odataParseValue(type: ODataNumericType, value: unknown): number | unknown;\nexport function odataParseValue(type: ODataDateType, value: unknown): Date | null | unknown;\nexport function odataParseValue(type: ODataStringType, value: unknown): string | unknown;\nexport function odataParseValue(type: ODataMetaType, value: unknown): string | unknown;\nexport function odataParseValue(type: ODataMetaType, value: unknown) {\n\tswitch (type) {\n\t\tcase \"boolean\": {\n\t\t\tconst parsed = tryParseBooleanValue(value);\n\t\t\treturn parsed ?? value;\n\t\t}\n\n\t\tcase \"int\":\n\t\tcase \"long\":\n\t\tcase \"float\":\n\t\tcase \"decimal\":\n\t\tcase \"double\":\n\t\tcase \"byte\":\n\t\t\treturn parseNumber(value);\n\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\treturn parseDate(value);\n\n\t\tdefault:\n\t\t\treturn String(value);\n\t}\n}\n\nexport function odataParseValueByMetadata(descriptor: ODataMetadataValueDescriptor, value: unknown) {\n\tif (descriptor.abapBooleanLike) {\n\t\tconst parsedBoolean = tryParseAbapBooleanLikeValue(value);\n\t\tif (parsedBoolean !== undefined) {\n\t\t\treturn parsedBoolean;\n\t\t}\n\t}\n\n\treturn odataParseValue(descriptor.type, value);\n}\n\nexport function defaultODataTypeValue(type: ODataMetaType) {\n\tswitch (type) {\n\t\tcase \"boolean\":\n\t\t\treturn false;\n\n\t\tcase \"int\":\n\t\tcase \"long\":\n\t\tcase \"float\":\n\t\tcase \"decimal\":\n\t\tcase \"double\":\n\t\tcase \"byte\":\n\t\t\treturn 0;\n\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\treturn new Date();\n\n\t\tdefault:\n\t\t\treturn \"\";\n\t}\n}\n\nexport function defaultControlTypeValue(type: BaseMetaType) {\n\tswitch (type) {\n\t\tcase \"boolean\":\n\t\t\treturn false;\n\t\tcase \"number\":\n\t\t\treturn 0;\n\t\tcase \"date\":\n\t\t\treturn new Date();\n\t\tdefault:\n\t\t\treturn \"\";\n\t}\n}\n\nexport function createFormatter<S extends z.ZodArray>(schema: S, fn: (...args: [...z.infer<S>]) => string) {\n\treturn (...args: unknown[]) => {\n\t\tconst result = schema.safeParse(args);\n\t\tif (!result.success) {\n\t\t\tthrow new Error(`Validation failed: ${result.error.message}`);\n\t\t}\n\t\treturn fn(...result.data);\n\t};\n}\n\nexport function createBooleanFormatter(fn: (...args: boolean[]) => string) {\n\treturn createFormatter(z.array(z.boolean()), fn);\n}\n\nexport function createStringFormatter(fn: (...args: string[]) => string) {\n\treturn createFormatter(z.array(z.string()), fn);\n}\n\nexport function createNumberFormatter(fn: (...args: number[]) => string) {\n\treturn createFormatter(z.array(z.number()), fn);\n}\n\nexport function createDateFormatter(fn: (...args: Date[]) => string) {\n\treturn createFormatter(z.array(z.date()), fn);\n}\n\ntype FormatterRecord = {\n\t[K in BaseMetaType]?: {\n\t\t/**\n\t\t * Базовый форматтер для типа (по умолчанию)\n\t\t */\n\t\tbase: Omit<ODataFormatterDescription, \"id\">;\n\t\t/**\n\t\t * Кастомные варианты форматтеров для типа\n\t\t */\n\t\t[key: string]: Omit<ODataFormatterDescription, \"id\">;\n\t};\n};\n\n/*export*/ const formatODataDatetime = createDateFormatter(ODataDateFormat.datetime);\n/*export*/ const formatODataDatetimeOffset = createDateFormatter(ODataDateFormat.datetimeOffset);\n/*export*/ const formatODataTime = createDateFormatter(ODataDateFormat.time);\n/*export*/ const formatODataAbapDate = createDateFormatter((value) => formatValidValue(\"string\", formatDateAsAbapDate(value)));\n\n/*export*/ const formatODataBoolean = createBooleanFormatter((value) => formatValidValue(\"boolean\", value));\n/*export*/ const formatODataBooleanAsChar = createBooleanFormatter((value) => formatValidValue(\"string\", Number(value)));\n/*export*/ const formatODataBooleanAsByte = createBooleanFormatter((value) => formatValidValue(\"byte\", Number(value)));\n\n/*export*/ const formatODataString = createStringFormatter((value) => formatValidValue(\"string\", value));\n\n/**\n * Форматтеры формируются только по базовым типам, по которым работают UI контролы.\n */\nconst formatters: FormatterRecord = {\n\tdate: {\n\t\tbase: {\n\t\t\tlabel: \"Базовый datetime\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных datetime\",\n\t\t\tfn: formatODataDatetime\n\t\t},\n\t\tdatetimeOffset: {\n\t\t\tlabel: \"Базовый datetimeoffset\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных datetimeoffset\",\n\t\t\tfn: formatODataDatetimeOffset\n\t\t},\n\t\ttime: {\n\t\t\tlabel: \"Базовый time\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных time\",\n\t\t\tfn: formatODataTime\n\t\t},\n\t\tstringAbapDate: {\n\t\t\tlabel: \"Дата ABAP YYYYMMDD\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных string(8)\",\n\t\t\tfn: formatODataAbapDate\n\t\t}\n\t},\n\tboolean: {\n\t\tbase: {\n\t\t\tlabel: \"Базовое ABAP булево\",\n\t\t\tdescription: \"Стандартный формат abap_bool со значением 'X' для true и '' для false\",\n\t\t\tfn: formatODataBoolean\n\t\t},\n\t\tasChar: {\n\t\t\tlabel: \"Как символ\",\n\t\t\tdescription: \"Преобразование булево в символы '0' или '1'\",\n\t\t\tfn: formatODataBooleanAsChar\n\t\t},\n\t\tasByte: {\n\t\t\tlabel: \"Как цифра\",\n\t\t\tdescription: \"Преобразование булево в цифру 0 или 1\",\n\t\t\tfn: formatODataBooleanAsByte\n\t\t}\n\t},\n\tstring: {\n\t\tbase: {\n\t\t\tlabel: \"Базовая строка\",\n\t\t\tdescription: \"\",\n\t\t\tfn: formatODataString\n\t\t}\n\t}\n};\n\nexport function getBaseTypeFromODataType<T extends ODataMetaType>(type: T): BaseMetaType {\n\tswitch (type) {\n\t\tcase \"boolean\":\n\t\t\treturn \"boolean\";\n\n\t\tcase \"int\":\n\t\tcase \"long\":\n\t\tcase \"float\":\n\t\tcase \"decimal\":\n\t\tcase \"double\":\n\t\tcase \"byte\":\n\t\t\treturn \"number\";\n\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\treturn \"date\";\n\n\t\tdefault:\n\t\t\treturn \"string\";\n\t}\n}\n\nexport function getFormattersFor<T extends ODataMetaType>(type: T): ODataFormatterDescription[] {\n\tconst group = formatters[getBaseTypeFromODataType(type)];\n\tif (!group) return [];\n\n\treturn Object.entries(group).map(([id, fmt]) => ({\n\t\tid,\n\t\t...fmt\n\t}));\n}\n\n/**\n * Возвращает форматтеры напрямую по базовому типу UI-контрола.\n */\nexport function getFormattersForBaseType<T extends BaseMetaType>(type: T): ODataFormatterDescription[] {\n\tconst group = formatters[type];\n\tif (!group) return [];\n\n\treturn Object.entries(group).map(([id, fmt]) => ({\n\t\tid,\n\t\t...fmt\n\t}));\n}\n\nexport function getFormatter<T extends ODataMetaType>(type: T, id: string) {\n\treturn formatters[getBaseTypeFromODataType(type)]?.[id];\n}\n\nexport function getFormatterForBaseType<T extends BaseMetaType>(type: T, id: string) {\n\treturn formatters[type]?.[id];\n}\n","/**\n * Построитель URL для OData сущностей на основе метаданных\n */\n\nimport { odataFormatValue } from \"./formatters\";\nimport {\n\tEntityMetadata,\n\tEntityParameterProperty,\n\tFunctionImportMetadata,\n\tODataOperationMethod,\n\tODataServiceConfig,\n\tODataValue,\n\tWrappedODataParameters\n} from \"./types\";\n\ntype ParameterizedMetadata = {\n\tparameters?: EntityParameterProperty[];\n};\n\n/**\n * Валидирует длину отформатированного значения\n * @param formattedValue Отформатированное значение\n * @param maxLength Максимальная длина\n */\nfunction validateFormattedLength(formattedValue: string, maxLength?: number): void {\n\tif (!maxLength || typeof maxLength !== \"number\") return;\n\n\t// Проверяем что значение в кавычках и содержимое не превышает maxLength\n\tconst match = formattedValue.match(/^'(.*)'$/s);\n\tif (!match) {\n\t\tthrow new Error(`Значение должно быть заключено в одинарные кавычки: ${formattedValue}`);\n\t}\n\n\tconst content = match[1];\n\tif (content.length > maxLength) {\n\t\tthrow new Error(\n\t\t\t`Значение слишком длинное для maxLength=${maxLength}: '${formattedValue}' (${content.length} символов внутри кавычек)`\n\t\t);\n\t}\n}\n\n/**\n * Собирает строку параметров запроса к сущности на основе метаданных\n *\n * @param metadata Метаданные сущности\n * @param params Значения параметров\n */\nexport function buildParameterEntries(metadata: ParameterizedMetadata, params: WrappedODataParameters): Array<[string, string]> {\n\tif (!metadata.parameters) return [];\n\n\tconst parts = metadata.parameters.map<[string, string] | null>((param) => {\n\t\tconst { id, type, maxLength, mandatory } = param;\n\n\t\tconst odataValue = (params[id] ?? {}) as ODataValue;\n\t\tconst value = odataValue.value;\n\t\tconst formatter = odataValue.formatter;\n\n\t\tif (mandatory && (value === undefined || value === null)) {\n\t\t\tthrow new Error(`Отсутствует обязательный параметр: ${id}`);\n\t\t}\n\n\t\t// Пропускаем необязательные параметры без значений\n\t\tif (value === undefined || value === null) return null;\n\n\t\ttry {\n\t\t\tconst formattedValue = formatter ? formatter(value) : odataFormatValue(type, value);\n\n\t\t\tvalidateFormattedLength(formattedValue, maxLength);\n\n\t\t\treturn [id, formattedValue];\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Ошибка форматирования параметра ${id}: ${String(error)}`);\n\t\t}\n\t});\n\n\treturn parts.filter((part): part is [string, string] => part !== null);\n}\n\n/**\n * Собирает строку параметров запроса к сущности на основе metadata.\n */\nexport function buildEntityParameters(metadata: EntityMetadata, params: WrappedODataParameters): string {\n\tconst parts = buildParameterEntries(metadata, params);\n\treturn parts.length ? `(${parts.map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join(\",\")})` : \"\";\n}\n\n/**\n * Собирает query string-параметры для FunctionImport.\n */\nexport function buildFunctionImportParameters(metadata: FunctionImportMetadata, params: WrappedODataParameters): URLSearchParams {\n\tconst searchParams = new URLSearchParams();\n\n\tfor (const [key, value] of buildParameterEntries(metadata, params)) {\n\t\tsearchParams.set(key, value);\n\t}\n\n\treturn searchParams;\n}\n\nexport function buildEntityOperationPath(\n\tmetadata: EntityMetadata,\n\tconfig: ODataServiceConfig,\n\tparams: WrappedODataParameters,\n\tmethod: Exclude<ODataOperationMethod, \"fi\">\n): string {\n\tconst basePath = `/${config.service}/${config.target}`;\n\n\tif (method === \"create\") {\n\t\treturn basePath;\n\t}\n\n\tif (method === \"query\") {\n\t\tif (!metadata.result) {\n\t\t\tif (__DEV__) {\n\t\t\t\tif (Object.keys(params).length > 0) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Параметры для query-запроса '/${config.service}/${config.target}' проигнорированы: target не поддерживает parameterized query.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn basePath;\n\t\t}\n\n\t\treturn buildEntityPath(metadata, config, params);\n\t}\n\n\tconst parameters = buildEntityParameters(metadata, params);\n\treturn `${basePath}${parameters}`;\n}\n\n/**\n * Собирает строку запроса к FunctionImport.\n */\nexport function buildFunctionImportPath(\n\tmetadata: FunctionImportMetadata,\n\tconfig: ODataServiceConfig,\n\tparams: WrappedODataParameters\n): string {\n\tconst searchParams = buildFunctionImportParameters(metadata, params);\n\tconst queryString = searchParams.toString();\n\tconst path = `/${config.service}/${config.target}`;\n\n\treturn queryString ? `${path}?${queryString}` : path;\n}\n\n/**\n * Собирает строку запроса к EntitySet\n */\nexport function buildEntityPath(metadata: EntityMetadata, config: ODataServiceConfig, params: WrappedODataParameters): string {\n\tconst parameters = buildEntityParameters(metadata, params);\n\tconst navigation = metadata.result ? `/${metadata.result}` : \"\";\n\n\treturn `/${config.service}/${config.target}${parameters}${navigation}`;\n}\n","import { EntityColumnProperty } from \"./types\";\n\n/**\n * Возвращает code-like filterable-колонки.\n */\nexport function collectFilterableColumns(columns: readonly Readonly<EntityColumnProperty>[]): Readonly<EntityColumnProperty>[] {\n\treturn columns.filter((column) => column.semanticType === \"code\" && column.filterable);\n}\n\n/**\n * Возвращает идентификаторы code-like filterable-колонок.\n */\nexport function collectFilterableColumnsIds(columns: readonly Readonly<EntityColumnProperty>[]): Readonly<Set<string>> {\n\treturn new Set(collectFilterableColumns(columns).map((c) => c.id));\n}\n","import { odataFormatValue } from \"./formatters\";\n\nimport type { BaseType, RowRecord } from \"../types\";\nimport type { ODataMetaType } from \"./types\";\n\nexport const FilterOperation = Object.freeze({\n\teq: \"eq\",\n\tne: \"ne\",\n\tgt: \"gt\",\n\tge: \"ge\",\n\tlt: \"lt\",\n\tle: \"le\",\n\tstartswith: \"startswith\",\n\tendswith: \"endswith\",\n\tcontains: \"contains\"\n} as const);\n\nexport type FilterOperation = (typeof FilterOperation)[keyof typeof FilterOperation];\n\nexport const FILTER_OPERATIONS = Object.freeze(Object.values(FilterOperation)) as readonly FilterOperation[];\n\nconst FILTER_OPERATION_LABELS: Readonly<Record<FilterOperation, string>> = Object.freeze({\n\teq: \"равно\",\n\tne: \"не равно\",\n\tgt: \"больше\",\n\tge: \"больше или равно\",\n\tlt: \"меньше\",\n\tle: \"меньше или равно\",\n\tstartswith: \"начинается с\",\n\tendswith: \"заканчивается на\",\n\tcontains: \"содержит\"\n});\n\nconst FILTER_OPERATION_SET: ReadonlySet<string> = new Set(FILTER_OPERATIONS);\n\nexport function isFilterOperation(value: unknown): value is FilterOperation {\n\treturn typeof value === \"string\" && FILTER_OPERATION_SET.has(value);\n}\n\nexport function resolveOperationLabel(operation: FilterOperation): string {\n\treturn FILTER_OPERATION_LABELS[operation];\n}\n\nexport interface FilterCondition<T> {\n\tkey: keyof T;\n\tvalue: BaseType;\n\toperation?: FilterOperation;\n\ttype?: ODataMetaType;\n}\n\n// Базовый интерфейс для выражения\nexport interface BaseFilterExpression {\n\t/**\n\t * @default false (or)\n\t */\n\tand?: boolean;\n}\n\n// Выражение с условиями (лист дерева)\nexport interface FilterConditionExpression<T> extends BaseFilterExpression {\n\tconditions: FilterCondition<T>[];\n\tfilters?: never; // Делаем явно недоступным\n}\n\n// Выражение с вложенными фильтрами (узел дерева)\nexport interface FilterNestedExpression<T> extends BaseFilterExpression {\n\tfilters: FilterExpression<T>[];\n\tconditions?: never; // Делаем явно недоступным\n}\n\n// Объединенный тип\nexport type FilterExpression<T> = FilterConditionExpression<T> | FilterNestedExpression<T>;\n\nfunction getODataTypeFromValue(value: unknown): ODataMetaType {\n\tswitch (typeof value) {\n\t\tcase \"bigint\":\n\t\tcase \"number\":\n\t\t\t// NOTE: тут теперь может возникнуть проблема, когда нужен будет long\n\t\t\treturn \"int\";\n\t\tcase \"boolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"object\":\n\t\t\tif (value instanceof Date) {\n\t\t\t\treturn \"datetime\";\n\t\t\t}\n\t}\n\n\treturn \"string\";\n}\n\n// Функция для построения условия\nfunction buildCondition<T>(condition: FilterCondition<T>): string {\n\tconst { key, operation = \"eq\", value, type } = condition;\n\tconst odataType = type ?? getODataTypeFromValue(value);\n\tconst escapedValue = odataFormatValue(odataType, value);\n\n\t// Специальные операторы для строк\n\tif (operation === \"contains\") {\n\t\treturn `substringof(${escapedValue},${String(key)})`;\n\t}\n\n\tif (operation === \"startswith\" || operation === \"endswith\") {\n\t\treturn `${operation}(${String(key)}, ${escapedValue})`;\n\t}\n\n\t// Стандартные операторы\n\treturn `${String(key)} ${operation} ${escapedValue}`;\n}\n\n// Type guards\nfunction isConditionExpression<T>(expr: FilterExpression<T>): expr is FilterConditionExpression<T> {\n\treturn \"conditions\" in expr && expr.conditions !== undefined;\n}\n\nfunction isNestedExpression<T>(expr: FilterExpression<T>): expr is FilterNestedExpression<T> {\n\treturn \"filters\" in expr && expr.filters !== undefined;\n}\n\nfunction compactExpressionStrings<T>(filters: FilterExpression<T>[], build: (expression: FilterExpression<T>) => string): string[] {\n\t// return filters.map((filter) => build(filter)).filter(Boolean);\n\tconst result: string[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst value = build(filter);\n\t\tif (value) {\n\t\t\tresult.push(value);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// Основная функция\nexport function buildODataFilter<T>(expression: FilterExpression<T> | undefined): string {\n\tif (!expression) return \"\";\n\n\tif (isConditionExpression(expression)) {\n\t\t// Обработка выражения с условиями\n\t\tconst { conditions, and = false } = expression;\n\n\t\tif (conditions.length === 0) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (conditions.length === 1) {\n\t\t\treturn buildCondition(conditions[0]);\n\t\t}\n\n\t\tconst operator = and ? \"and\" : \"or\";\n\t\tconst conditionsString = conditions.map(buildCondition).join(` ${operator} `);\n\t\treturn `(${conditionsString})`;\n\t}\n\n\tif (isNestedExpression(expression)) {\n\t\t// Обработка вложенного выражения\n\t\tconst { filters, and = false } = expression;\n\n\t\tif (filters.length === 0) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (filters.length === 1) {\n\t\t\treturn buildODataFilter(filters[0]);\n\t\t}\n\n\t\tconst operator = and ? \"and\" : \"or\";\n\t\tconst filterStrings = compactExpressionStrings(filters, buildODataFilter);\n\n\t\tif (filterStrings.length === 0) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (filterStrings.length === 1) {\n\t\t\treturn filterStrings[0];\n\t\t}\n\n\t\treturn `(${filterStrings.join(` ${operator} `)})`;\n\t}\n\n\tthrow new Error(\"Некорректное выражение фильтра\");\n}\n\n// Альтернативная версия с рекурсивной обработкой\nexport function buildODataFilterRecursive<T>(expression: FilterExpression<T> | undefined): string {\n\tconst processExpression = (expr: FilterExpression<T> | undefined): string => {\n\t\tif (!expr) return \"\";\n\n\t\tif (isConditionExpression(expr)) {\n\t\t\tconst { conditions, and = false } = expr;\n\n\t\t\tif (conditions.length === 0) return \"\";\n\t\t\tif (conditions.length === 1) return buildCondition(conditions[0]);\n\n\t\t\tconst operator = and ? \"and\" : \"or\";\n\t\t\treturn `(${conditions.map(buildCondition).join(` ${operator} `)})`;\n\t\t}\n\n\t\tif (isNestedExpression(expr)) {\n\t\t\tconst { filters, and = false } = expr;\n\n\t\t\tif (filters.length === 0) return \"\";\n\t\t\tif (filters.length === 1) return processExpression(filters[0]);\n\n\t\t\tconst operator = and ? \"and\" : \"or\";\n\t\t\tconst filterStrings = compactExpressionStrings(filters, processExpression).map((result) => {\n\t\t\t\treturn result.includes(\" \") ? `(${result})` : result;\n\t\t\t});\n\n\t\t\tif (filterStrings.length === 0) return \"\";\n\t\t\tif (filterStrings.length === 1) return filterStrings[0];\n\n\t\t\treturn `(${filterStrings.join(` ${operator} `)})`;\n\t\t}\n\n\t\treturn \"\";\n\t};\n\n\treturn processExpression(expression);\n}\n\nexport function createFilter<T, V extends BaseType>(\n\tkey: keyof T,\n\tvalue: (V | V[]) | null | undefined,\n\toperation: FilterOperation\n): FilterExpression<T> {\n\tif (value === null || value === undefined) return { conditions: [] };\n\n\tif (Array.isArray(value)) {\n\t\t// return {\n\t\t// \tconditions: value.filter((item) => item !== null || item !== undefined).map((item) => ({ key, value: item, operation }))\n\t\t// };\n\t\tconst conditions: FilterCondition<T>[] = [];\n\n\t\tfor (const item of value) {\n\t\t\tif (item !== null && item !== undefined) {\n\t\t\t\tconditions.push({ key, value: item, operation });\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tconditions\n\t\t};\n\t}\n\n\treturn {\n\t\tconditions: [{ key, value, operation }]\n\t};\n}\n\n/**\n * Создает выражение фильтра (`FilterExpression`)\n *\n * Пример конечного выражения:\n *\n * * псевдокод `(key ge odataFormatValue(value[0]) and key le odataFormatValue(value[1]))`\n * * результат `(COST eq 2000 and COST eq 5000)`\n */\nexport function createFilterBetween<T, V extends BaseType>(key: keyof T, values: readonly [V, V] | null | undefined): FilterExpression<T> {\n\tif (!values) return { conditions: [] };\n\n\tconst value1 = values[0];\n\tconst value2 = values[1];\n\n\tif (value1 === null || value1 === undefined || value2 === null || value2 === undefined) {\n\t\tif (value1) {\n\t\t\treturn {\n\t\t\t\tconditions: [{ key, value: value1, operation: \"ge\" }]\n\t\t\t};\n\t\t}\n\t\tif (value2) {\n\t\t\treturn {\n\t\t\t\tconditions: [{ key, value: value2, operation: \"le\" }]\n\t\t\t};\n\t\t}\n\t\treturn { conditions: [] };\n\t}\n\n\treturn {\n\t\tand: true,\n\t\tconditions: [\n\t\t\t{ key, value: value1, operation: \"ge\" },\n\t\t\t{ key, value: value2, operation: \"le\" }\n\t\t]\n\t};\n}\n\n/**\n * Создает выражение фильтра (`FilterExpression`)\n *\n * Пример конечного выражения:\n *\n * * псевдокод `key eq odataFormatValue(value)`\n * * результат `CUSTOMER eq '005417554'`\n *\n * Если `value` массив, то выражение формируется с оператором `or`: `(E1 or E2 or E3)`\n */\nexport function createFilterEqual<T, V extends BaseType>(key: keyof T, value: (V | V[]) | null | undefined): FilterExpression<T> {\n\treturn createFilter(key, value, \"eq\");\n}\n\nexport function createFilterEqualFalsy<T, V extends BaseType>(key: keyof T, value: (V | V[]) | null | undefined): FilterExpression<T> {\n\treturn createFilter(key, Array.isArray(value) ? value.map((v) => v || null) : value || null, \"eq\");\n}\n\n/**\n * Создает выражение фильтра (`FilterExpression`)\n *\n * Пример конечного выражения:\n *\n * * псевдокод `substringof(odataFormatValue(value), key)`\n * * результат `substringof('сталь', CUSTOMER)`\n *\n * Если `value` массив, то выражение формируется с оператором `or`: `(E1 or E2 or E3)`\n */\nexport function createFilterContains<T, V extends BaseType>(key: keyof T, value: (V | V[]) | null | undefined): FilterExpression<T> {\n\treturn createFilter(key, value, \"contains\");\n}\n\nexport function mergeFilterExpressions(\n\tleft?: FilterExpression<RowRecord>,\n\tright?: FilterExpression<RowRecord>\n): FilterExpression<RowRecord> | undefined {\n\tif (!left) return right;\n\tif (!right) return left;\n\n\treturn {\n\t\tand: true,\n\t\tfilters: [left, right]\n\t};\n}\n","import { compareStrings } from \"../string-comparison\";\nimport { BaseType, InputType } from \"../types\";\n\nimport { createFilterEqual, type FilterCondition, type FilterExpression, type FilterOperation } from \"./filters\";\n\nimport type { BaseMetaType, ODataChainsMap } from \"./types\";\n\ntype RowRecord = Record<string, unknown>;\ntype TreeFilterValue = Record<string, string[]>;\n\nexport type ODataFilterValue = InputType | TreeFilterValue;\nexport type ODataFilterValues = Record<string, ODataFilterValue>;\n\n/**\n * Одно условие OData-фильтра, которое может применяться не только к owner-колонке\n * фильтра, но и к явно выбранной колонке. Это нужно для локальных Select/MultiSelect:\n * один runtime-контрол выбирает option, а option уже знает, какую колонку таблицы\n * фильтровать и каким значением.\n */\nexport type ODataFilterCondition = {\n\t/**\n\t * Целевая колонка условия. Если не задана, компилятор использует ownerColumnId\n\t * фильтра, что сохраняет простую модель для обычных локальных value/boolean\n\t * фильтров и OData-сегментов.\n\t */\n\tcolumnId?: string;\n\toperation: FilterOperation;\n\tvalueSource: \"static\" | \"input\";\n\tvalue?: BaseType;\n};\n\nexport type ODataFilterConditionGroup = {\n\tand?: boolean;\n\tconditions: ODataFilterCondition[];\n};\n\nexport type ODataFilterOption = {\n\tkey: string;\n\tlabel: string;\n\tfilter?: ODataFilterConditionGroup;\n};\n\nexport type ODataFilterBinding =\n\t| {\n\t\t\tkind: \"list\";\n\t\t\toptions: ODataFilterOption[];\n\t }\n\t| {\n\t\t\tkind: \"boolean\";\n\t\t\ttrueFilter?: ODataFilterConditionGroup;\n\t }\n\t| {\n\t\t\tkind: \"value\";\n\t\t\tvalueFilter?: ODataFilterConditionGroup;\n\t };\n\nexport type FilterDefinitionKind = \"segment\" | \"tree\" | \"advanced\" | \"local\" | \"column\";\n\nexport type FilterSegmentComponentId = \"multi-select\" | \"select\";\nexport type FilterTreeComponentId = \"tree-select\" | \"tree-multi-select\";\nexport type FilterLocalComponentId = \"select\" | \"multi-select\" | \"checkbox\" | \"text-input\" | \"number-input\";\nexport type FilterAdvancedComponentId = \"advanced-search-select\";\nexport type FilterComponentId = FilterSegmentComponentId | FilterTreeComponentId | FilterLocalComponentId | FilterAdvancedComponentId;\n\n// TODO: переименовать, теперь это не только odata\nexport type ODataCompiledFilterDefinition =\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tcolumnIds: string[];\n\t\t\tkind: Extract<FilterDefinitionKind, \"segment\">;\n\t\t\tcomponentId: FilterSegmentComponentId;\n\t\t\tcontrolType: BaseMetaType;\n\t\t\tdictionaryCodeKey?: string;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tcolumnIds: string[];\n\t\t\tkind: Extract<FilterDefinitionKind, \"tree\">;\n\t\t\tcomponentId: FilterTreeComponentId;\n\t\t\tcontrolType: BaseMetaType;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tcolumnIds: string[];\n\t\t\tkind: Extract<FilterDefinitionKind, \"local\">;\n\t\t\tcomponentId: FilterLocalComponentId;\n\t\t\tcontrolType: BaseMetaType;\n\t\t\tbinding: ODataFilterBinding;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tkind: Extract<FilterDefinitionKind, \"advanced\">;\n\t\t\tcomponentId: FilterAdvancedComponentId;\n\t\t\tconfigId: string;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tkind: Extract<FilterDefinitionKind, \"column\">;\n\t };\n\nexport function isFilterLocalComponentId(value: unknown): value is FilterLocalComponentId {\n\treturn value === \"select\" || value === \"multi-select\" || value === \"checkbox\" || value === \"text-input\" || value === \"number-input\";\n}\n\n/**\n * Собирает физические колонки, которые реально затрагивает группа условий.\n * Для conditions без columnId берём fallback owner-колонку: это важно для старого\n * поведения value/boolean-фильтров и для conditions, где колонка не выбирается явно.\n */\nfunction collectConditionGroupColumnIds(group: ODataFilterConditionGroup | undefined, fallbackColumnId: string) {\n\tif (!group?.conditions.length) return [];\n\n\treturn group.conditions.map((condition) => condition.columnId?.trim() || fallbackColumnId).filter((columnId) => Boolean(columnId));\n}\n\n/**\n * Выводит `columnIds` локального фильтра из его binding. Раньше local-фильтр всегда\n * владел только ownerColumnId, но list-option теперь может фильтровать любую\n * доступную visible/data колонку, поэтому runtime и конфликты фильтров должны\n * видеть полный набор затронутых колонок.\n */\nfunction collectBindingColumnIds(binding: ODataFilterBinding, fallbackColumnId: string) {\n\tconst columnIds =\n\t\tbinding.kind === \"list\"\n\t\t\t? binding.options.flatMap((option) => collectConditionGroupColumnIds(option.filter, fallbackColumnId))\n\t\t\t: binding.kind === \"boolean\"\n\t\t\t\t? collectConditionGroupColumnIds(binding.trueFilter, fallbackColumnId)\n\t\t\t\t: collectConditionGroupColumnIds(binding.valueFilter, fallbackColumnId);\n\n\treturn [...new Set(columnIds.length ? columnIds : [fallbackColumnId])];\n}\n\nfunction resolveConditionGroupColumnIds(group: ODataFilterConditionGroup | undefined, fallbackColumnId: string) {\n\tconst columnIds = collectConditionGroupColumnIds(group, fallbackColumnId);\n\treturn columnIds.length ? columnIds : [fallbackColumnId];\n}\n\nfunction resolveListFilterSelectedKeys(definition: Extract<ODataCompiledFilterDefinition, { kind: \"local\" }>, value: ODataFilterValue) {\n\tif (definition.componentId === \"multi-select\") {\n\t\treturn sanitizeStringArray(value) ?? [];\n\t}\n\n\tconst selectedValue = sanitizeScalarValue(value);\n\treturn typeof selectedValue === \"string\" && selectedValue ? [selectedValue] : [];\n}\n\n/**\n * Возвращает все физические колонки, которые потенциально затрагивает filter definition.\n *\n * Helper нужен runtime-проекциям, где важно понять совместимость фильтра с\n * конкретным OData target без повторной реализации правил compiler-а.\n */\nexport function resolveODataFilterDefinitionColumnIds(definition: ODataCompiledFilterDefinition): string[] {\n\tconst normalizedDefinition = sanitizeFilterDefinitions([definition])[0];\n\tif (!normalizedDefinition) return [];\n\n\tif (normalizedDefinition.kind === \"segment\" || normalizedDefinition.kind === \"column\" || normalizedDefinition.kind === \"advanced\") {\n\t\treturn [normalizedDefinition.ownerColumnId];\n\t}\n\n\treturn [...normalizedDefinition.columnIds];\n}\n\n/**\n * Возвращает физические колонки, которые реально затрагивает текущее значение фильтра.\n *\n * Для local list учитываются только выбранные option-ы, поэтому фильтр с\n * несколькими потенциальными колонками не блокирует target, если активный выбор\n * обращается только к доступным колонкам.\n */\nexport function resolveODataFilterDefinitionActiveColumnIds(\n\tdefinition: ODataCompiledFilterDefinition,\n\tvalue: ODataFilterValue | undefined\n): string[] {\n\tconst normalizedDefinition = sanitizeFilterDefinitions([definition])[0];\n\tconst normalizedValue = sanitizeFilterValue(value);\n\tif (!normalizedDefinition || normalizedValue === undefined) return [];\n\n\tswitch (normalizedDefinition.kind) {\n\t\tcase \"segment\":\n\t\tcase \"column\":\n\t\tcase \"advanced\": {\n\t\t\treturn [normalizedDefinition.ownerColumnId];\n\t\t}\n\n\t\tcase \"tree\": {\n\t\t\tconst treeValue = sanitizeTreeFilterValue(normalizedValue);\n\t\t\tif (!treeValue) return [];\n\t\t\treturn Object.keys(treeValue).filter((columnId) => normalizedDefinition.columnIds.includes(columnId));\n\t\t}\n\n\t\tcase \"local\": {\n\t\t\tif (normalizedDefinition.binding.kind === \"list\") {\n\t\t\t\tconst selectedKeys = resolveListFilterSelectedKeys(normalizedDefinition, normalizedValue);\n\t\t\t\treturn [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tselectedKeys.flatMap((selectedKey) => {\n\t\t\t\t\t\t\tconst option =\n\t\t\t\t\t\t\t\tnormalizedDefinition.binding.kind === \"list\"\n\t\t\t\t\t\t\t\t\t? normalizedDefinition.binding.options.find((item) => item.key === selectedKey)\n\t\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\tif (!option) return [];\n\t\t\t\t\t\t\treturn resolveConditionGroupColumnIds(option.filter, normalizedDefinition.ownerColumnId);\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t];\n\t\t\t}\n\n\t\t\tif (normalizedDefinition.binding.kind === \"boolean\") {\n\t\t\t\treturn normalizedValue === true\n\t\t\t\t\t? resolveConditionGroupColumnIds(normalizedDefinition.binding.trueFilter, normalizedDefinition.ownerColumnId)\n\t\t\t\t\t: [];\n\t\t\t}\n\n\t\t\treturn resolveConditionGroupColumnIds(normalizedDefinition.binding.valueFilter, normalizedDefinition.ownerColumnId);\n\t\t}\n\n\t\tdefault: {\n\t\t\tconst _checker: never = normalizedDefinition;\n\t\t\tvoid _checker;\n\t\t\treturn [];\n\t\t}\n\t}\n}\n\nexport function normalizeDictionaryCodeKey(value: string | undefined, ownerColumnId: string) {\n\tconst normalized = value?.trim();\n\treturn normalized && normalized !== ownerColumnId ? normalized : undefined;\n}\n\nfunction sanitizeScalarValue(value: unknown): BaseType | undefined {\n\tif (value instanceof Date) {\n\t\treturn Number.isFinite(value.getTime()) ? value : undefined;\n\t}\n\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim();\n\t\t// NOTE: 08.06.2026 разрешаем в фильтр передавать пустую строку\n\t\t// return normalized ? normalized : undefined;\n\t\treturn normalized;\n\t}\n\n\tif (typeof value === \"number\") {\n\t\treturn Number.isFinite(value) ? value : undefined;\n\t}\n\n\tif (typeof value === \"boolean\") {\n\t\treturn value;\n\t}\n\n\treturn undefined;\n}\n\nfunction serializeBaseValue(value: BaseType) {\n\tif (value instanceof Date) {\n\t\treturn `date:${value.toISOString()}`;\n\t}\n\n\treturn `${typeof value}:${String(value)}`;\n}\n\nfunction sanitizeArrayValue(value: unknown): BaseType[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\n\tconst seen = new Set<string>();\n\tconst normalized: BaseType[] = [];\n\n\tfor (const item of value) {\n\t\tconst nextValue = sanitizeScalarValue(item);\n\t\tif (nextValue === undefined) continue;\n\n\t\tconst key = serializeBaseValue(nextValue);\n\t\tif (seen.has(key)) continue;\n\t\tseen.add(key);\n\t\tnormalized.push(nextValue);\n\t}\n\n\tnormalized.sort((left, right) => compareStrings(serializeBaseValue(left), serializeBaseValue(right)));\n\n\treturn normalized.length ? normalized : undefined;\n}\n\nfunction sanitizeStringArray(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\n\tconst normalized = [\n\t\t...new Set(\n\t\t\tvalue\n\t\t\t\t.filter((item): item is string => typeof item === \"string\")\n\t\t\t\t.map((item) => item.trim())\n\t\t\t\t.filter(Boolean)\n\t\t)\n\t]; // .sort();\n\treturn normalized.length ? normalized : undefined;\n}\n\nfunction sanitizeTreeFilterValue(value: unknown): TreeFilterValue | undefined {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value) || value instanceof Date) return undefined;\n\n\tconst normalized = Object.fromEntries(\n\t\tObject.entries(value)\n\t\t\t.map(([columnId, rawValues]) => [columnId.trim(), sanitizeStringArray(rawValues)] as const)\n\t\t\t.filter((entry): entry is [string, string[]] => Boolean(entry[0]) && Boolean(entry[1]?.length))\n\t);\n\n\treturn Object.keys(normalized).length ? normalized : undefined;\n}\n\nexport function sanitizeFilterConditionGroup(group: ODataFilterConditionGroup | undefined): ODataFilterConditionGroup | undefined {\n\tif (!group?.conditions?.length) return undefined;\n\n\tconst conditions: ODataFilterCondition[] = [];\n\n\tfor (const condition of group.conditions) {\n\t\tconst value = sanitizeScalarValue(condition.value);\n\t\tif (condition.valueSource === \"static\" && value === undefined) continue;\n\n\t\tconditions.push({\n\t\t\tcolumnId: condition.columnId?.trim() || undefined,\n\t\t\toperation: condition.operation,\n\t\t\tvalueSource: condition.valueSource,\n\t\t\tvalue\n\t\t});\n\t}\n\n\tif (!conditions.length) return undefined;\n\n\treturn {\n\t\tand: group.and === false ? false : group.and ? true : undefined,\n\t\tconditions\n\t};\n}\n\nexport function sanitizeFilterBinding(binding: ODataFilterBinding | undefined): ODataFilterBinding | undefined {\n\tif (!binding) return undefined;\n\n\tif (binding.kind === \"list\") {\n\t\tconst options: ODataFilterOption[] = [];\n\t\t// const keysSet = new Set<string>();\n\n\t\tfor (const option of binding.options ?? []) {\n\t\t\tconst key = option.key.trim();\n\t\t\t// NOTE: пустой ключ разрешаем\n\t\t\t// TODO: подумать, допустимо ли дублирование\n\t\t\t// if (keysSet.has(key)) continue;\n\t\t\t// keysSet.add(key);\n\n\t\t\toptions.push({\n\t\t\t\tkey,\n\t\t\t\tlabel: option.label.trim() || key,\n\t\t\t\tfilter: sanitizeFilterConditionGroup(option.filter)\n\t\t\t});\n\t\t}\n\n\t\treturn options.length ? { kind: \"list\", options } : undefined;\n\t}\n\n\tif (binding.kind === \"boolean\") {\n\t\treturn {\n\t\t\tkind: \"boolean\",\n\t\t\ttrueFilter: sanitizeFilterConditionGroup(binding.trueFilter)\n\t\t};\n\t}\n\n\treturn {\n\t\tkind: \"value\",\n\t\tvalueFilter: sanitizeFilterConditionGroup(binding.valueFilter)\n\t};\n}\n\nexport function sanitizeFilterDefinitions<T extends ODataCompiledFilterDefinition>(definitions?: readonly T[]): T[] {\n\tif (!definitions?.length) return [];\n\n\tconst normalized: T[] = [];\n\n\tfor (const definition of definitions) {\n\t\tconst id = definition.id.trim();\n\t\tconst ownerColumnId = definition.ownerColumnId.trim();\n\t\tif (!id || !ownerColumnId) continue;\n\n\t\t// HACK: на период пересохранения всех конфигов\n\t\tif ((definition.kind as string) === \"odata-segment\") {\n\t\t\tdefinition.kind = \"segment\";\n\t\t}\n\t\tif ((definition.kind as string) === \"odata-tree\") {\n\t\t\tdefinition.kind = \"tree\";\n\t\t}\n\n\t\tswitch (definition.kind) {\n\t\t\tcase \"segment\": {\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...definition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId,\n\t\t\t\t\tcolumnIds: [ownerColumnId],\n\t\t\t\t\tcomponentId: definition.componentId === \"select\" ? \"select\" : \"multi-select\",\n\t\t\t\t\tdictionaryCodeKey: normalizeDictionaryCodeKey(definition.dictionaryCodeKey, ownerColumnId)\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"tree\": {\n\t\t\t\tconst columnIds = [...new Set(definition.columnIds.map((columnId) => columnId.trim()).filter(Boolean))];\n\t\t\t\tif (columnIds.length < 2) break;\n\n\t\t\t\t// HACK: на период пересохранения всех конфигов\n\t\t\t\tdefinition.componentId = (definition.componentId as string) === \"treeSelect\" ? \"tree-select\" : \"tree-multi-select\";\n\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...definition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId: columnIds.includes(ownerColumnId) ? ownerColumnId : columnIds[0],\n\t\t\t\t\tcolumnIds,\n\t\t\t\t\tcomponentId: definition.componentId === \"tree-select\" ? \"tree-select\" : \"tree-multi-select\"\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"local\": {\n\t\t\t\tconst binding = sanitizeFilterBinding(definition.binding);\n\t\t\t\tif (!binding) break;\n\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...definition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId,\n\t\t\t\t\t// Для local-фильтров список колонок является производным от conditions.\n\t\t\t\t\t// Это делает Select/MultiSelect с option -> columnId частью общего\n\t\t\t\t\t// контракта фильтров без отдельной runtime-модели.\n\t\t\t\t\tcolumnIds: collectBindingColumnIds(binding, ownerColumnId),\n\t\t\t\t\tbinding\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"advanced\": {\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...definition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"column\": {\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...definition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst _checker: never = definition;\n\t\t\t\tvoid _checker;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn normalized;\n}\n\nexport function sanitizeFilterValue(value: ODataFilterValue | undefined): ODataFilterValue | undefined {\n\tif (value === null || value === undefined) return undefined;\n\n\tconst scalarValue = sanitizeScalarValue(value);\n\tif (scalarValue !== undefined) return scalarValue;\n\n\tconst arrayValue = sanitizeArrayValue(value);\n\tif (arrayValue) return arrayValue;\n\n\treturn sanitizeTreeFilterValue(value);\n}\n\nexport function sanitizeFilterValues(values?: ODataFilterValues): ODataFilterValues {\n\tif (!values) return {};\n\n\tconst normalized: ODataFilterValues = {};\n\n\tfor (const [key, value] of Object.entries(values)) {\n\t\tconst filterId = key.trim();\n\t\tif (!filterId) continue;\n\n\t\tconst nextValue = sanitizeFilterValue(value);\n\t\tif (nextValue === undefined) continue;\n\t\tnormalized[filterId] = nextValue;\n\t}\n\n\treturn normalized;\n}\n\nexport function mergeFilterValuePatch(values: ODataFilterValues | undefined, filterId: string, value: ODataFilterValue | undefined) {\n\tconst normalizedValues = sanitizeFilterValues(values);\n\tconst nextValues = { ...normalizedValues };\n\tconst nextValue = sanitizeFilterValue(value);\n\n\tif (nextValue === undefined) {\n\t\tdelete nextValues[filterId];\n\t\treturn nextValues;\n\t}\n\n\tnextValues[filterId] = nextValue;\n\treturn nextValues;\n}\n\nexport function collapseChainedODataSegmentFilterValues(\n\tvalues: ODataFilterValues,\n\todataSegmentIds: readonly string[],\n\tchains: ODataChainsMap\n): ODataFilterValues {\n\tif (!values || Object.keys(values).length === 0) return {};\n\n\tconst result: ODataFilterValues = {};\n\tconst codeToChain: Record<string, string> = {};\n\n\tfor (const [chainKey, chainItems] of Object.entries(chains)) {\n\t\tfor (const item of chainItems) {\n\t\t\tcodeToChain[item.codeKey] = chainKey;\n\t\t}\n\t}\n\n\tconst groupedByChain: Record<string, string[]> = {};\n\tconst odataSegmentIdSet = new Set(odataSegmentIds);\n\n\tfor (const [filterId, value] of Object.entries(values)) {\n\t\tconst chainKey = codeToChain[filterId];\n\t\tconst isODataSegment = odataSegmentIdSet.has(filterId);\n\t\tconst isListValue = Array.isArray(value) || typeof value === \"string\";\n\n\t\tif (chainKey && isODataSegment && isListValue) {\n\t\t\tgroupedByChain[chainKey] = groupedByChain[chainKey] ?? [];\n\t\t\tgroupedByChain[chainKey].push(filterId);\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult[filterId] = value;\n\t}\n\n\tfor (const [chainKey, filterIds] of Object.entries(groupedByChain)) {\n\t\tconst chain = chains[chainKey];\n\t\tif (!chain) continue;\n\n\t\tlet deepestFilterId: string | null = null;\n\t\tfor (const { codeKey } of [...chain].reverse()) {\n\t\t\tif (filterIds.includes(codeKey)) {\n\t\t\t\tdeepestFilterId = codeKey;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (deepestFilterId && values[deepestFilterId] !== undefined) {\n\t\t\tresult[deepestFilterId] = values[deepestFilterId];\n\t\t}\n\t}\n\n\treturn result;\n}\n\nfunction resolveExpressionValue(valueSource: \"static\" | \"input\", value: ODataFilterValue | BaseType | undefined) {\n\tif (valueSource === \"static\") {\n\t\treturn sanitizeScalarValue(value);\n\t}\n\n\treturn sanitizeScalarValue(value);\n}\n\nfunction compileCondition(\n\townerColumnId: string,\n\tcondition: ODataFilterCondition,\n\tinputValue?: ODataFilterValue\n): FilterCondition<RowRecord> | undefined {\n\tconst value = resolveExpressionValue(condition.valueSource, condition.valueSource === \"input\" ? inputValue : condition.value);\n\tif (value === undefined) return undefined;\n\n\treturn {\n\t\t// columnId позволяет одному локальному list-контролу генерировать условия\n\t\t// по разным колонкам; ownerColumnId остаётся безопасным fallback для\n\t\t// простых фильтров и ранее созданных groups без явной колонки.\n\t\tkey: condition.columnId?.trim() || ownerColumnId,\n\t\toperation: condition.operation,\n\t\tvalue\n\t};\n}\n\nfunction compileConditionGroup(\n\townerColumnId: string,\n\tgroup: ODataFilterConditionGroup | undefined,\n\tinputValue?: ODataFilterValue\n): FilterExpression<RowRecord> | undefined {\n\tif (!group?.conditions.length) return undefined;\n\n\tconst conditions = group.conditions\n\t\t.map((condition) => compileCondition(ownerColumnId, condition, inputValue))\n\t\t.filter((condition): condition is FilterCondition<RowRecord> => Boolean(condition));\n\n\tif (!conditions.length) return undefined;\n\n\treturn {\n\t\tand: group.and === false ? undefined : true,\n\t\tconditions\n\t};\n}\n\nfunction compileDefaultBooleanFilter(ownerColumnId: string) {\n\treturn createFilterEqual<RowRecord, true>(ownerColumnId, true);\n}\n\nfunction compileDefaultValueFilter(ownerColumnId: string, value: BaseType | BaseType[]) {\n\treturn createFilterEqual<RowRecord, BaseType>(ownerColumnId, value);\n}\n\nfunction compileTreeFilter(definition: Extract<ODataCompiledFilterDefinition, { kind: \"tree\" }>, value: ODataFilterValue | undefined) {\n\tconst treeValue = sanitizeTreeFilterValue(value);\n\tif (!treeValue) return undefined;\n\n\tconst filters = definition.columnIds\n\t\t.map((columnId) => {\n\t\t\tconst selectedValues = treeValue[columnId];\n\t\t\tif (!selectedValues?.length) return undefined;\n\n\t\t\treturn createFilterEqual<RowRecord, string>(columnId, selectedValues);\n\t\t})\n\t\t.filter((filter): filter is FilterExpression<RowRecord> => Boolean(filter));\n\n\tif (!filters.length) return undefined;\n\tif (filters.length === 1) return filters[0];\n\n\treturn {\n\t\tand: true,\n\t\tfilters\n\t};\n}\n\nfunction compileListFilter(\n\tdefinition: Extract<ODataCompiledFilterDefinition, { kind: \"local\" }>,\n\tvalue: ODataFilterValue | undefined\n): FilterExpression<RowRecord> | undefined {\n\tif (definition.binding.kind !== \"list\") return undefined;\n\tconst binding = definition.binding;\n\n\tif (definition.componentId === \"multi-select\") {\n\t\tconst values = sanitizeStringArray(value);\n\t\tif (!values?.length) return undefined;\n\n\t\tconst filters = values\n\t\t\t.map((selectedKey) => {\n\t\t\t\tconst option = binding.options.find((item: ODataFilterOption) => item.key === selectedKey);\n\t\t\t\tif (!option) return undefined;\n\n\t\t\t\treturn (\n\t\t\t\t\tcompileConditionGroup(definition.ownerColumnId, option.filter) ??\n\t\t\t\t\tcompileDefaultValueFilter(definition.ownerColumnId, option.key)\n\t\t\t\t);\n\t\t\t})\n\t\t\t.filter((filter): filter is FilterExpression<RowRecord> => Boolean(filter));\n\n\t\tif (!filters.length) return undefined;\n\t\tif (filters.length === 1) return filters[0];\n\n\t\treturn {\n\t\t\tfilters\n\t\t};\n\t}\n\n\tconst selectedValue = sanitizeScalarValue(value);\n\tif (typeof selectedValue !== \"string\" || !selectedValue) return undefined;\n\n\tconst option = binding.options.find((item: ODataFilterOption) => item.key === selectedValue);\n\tif (!option) return undefined;\n\n\treturn (\n\t\tcompileConditionGroup(definition.ownerColumnId, option.filter) ?? compileDefaultValueFilter(definition.ownerColumnId, option.key)\n\t);\n}\n\nfunction compileDefinitionFilter(\n\tdefinition: ODataCompiledFilterDefinition,\n\tvalue: ODataFilterValue | undefined\n): FilterExpression<RowRecord> | undefined {\n\tif (value === undefined) return undefined;\n\n\tswitch (definition.kind) {\n\t\tcase \"segment\": {\n\t\t\tif (definition.componentId === \"select\") {\n\t\t\t\tconst scalarValue = sanitizeScalarValue(value);\n\t\t\t\treturn scalarValue !== undefined ? compileDefaultValueFilter(definition.ownerColumnId, scalarValue) : undefined;\n\t\t\t}\n\n\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\treturn arrayValue?.length ? compileDefaultValueFilter(definition.ownerColumnId, arrayValue) : undefined;\n\t\t}\n\n\t\tcase \"tree\": {\n\t\t\treturn compileTreeFilter(definition, value);\n\t\t}\n\n\t\tcase \"local\": {\n\t\t\tif (definition.binding.kind === \"list\") {\n\t\t\t\treturn compileListFilter(definition, value);\n\t\t\t}\n\n\t\t\tif (definition.binding.kind === \"boolean\") {\n\t\t\t\tif (value !== true) return undefined;\n\t\t\t\treturn (\n\t\t\t\t\tcompileConditionGroup(definition.ownerColumnId, definition.binding.trueFilter) ??\n\t\t\t\t\tcompileDefaultBooleanFilter(definition.ownerColumnId)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\tcompileConditionGroup(definition.ownerColumnId, definition.binding.valueFilter, value) ??\n\t\t\t\t(() => {\n\t\t\t\t\tconst scalarValue = sanitizeScalarValue(value);\n\t\t\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\t\t\tconst defaultValue = scalarValue ?? arrayValue;\n\t\t\t\t\treturn defaultValue !== undefined ? compileDefaultValueFilter(definition.ownerColumnId, defaultValue) : undefined;\n\t\t\t\t})()\n\t\t\t);\n\t\t}\n\n\t\tcase \"column\": {\n\t\t\tconst scalarValue = sanitizeScalarValue(value);\n\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\tconst defaultValue = scalarValue ?? arrayValue;\n\t\t\treturn defaultValue !== undefined ? compileDefaultValueFilter(definition.ownerColumnId, defaultValue) : undefined;\n\t\t}\n\n\t\tcase \"advanced\": {\n\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\treturn arrayValue?.length ? compileDefaultValueFilter(definition.ownerColumnId, arrayValue) : undefined;\n\t\t}\n\n\t\tdefault: {\n\t\t\tconst _checker: never = definition;\n\t\t\tvoid _checker;\n\t\t}\n\t}\n}\n\nexport function compileFiltersToExpression(\n\tdefinitions?: readonly ODataCompiledFilterDefinition[],\n\tvalues?: ODataFilterValues\n): FilterExpression<RowRecord> | undefined {\n\tconst normalizedDefinitions = sanitizeFilterDefinitions(definitions);\n\tconst normalizedValues = sanitizeFilterValues(values);\n\tif (!normalizedDefinitions.length || !Object.keys(normalizedValues).length) return undefined;\n\n\tconst filters = normalizedDefinitions\n\t\t.map((definition) => compileDefinitionFilter(definition, normalizedValues[definition.id]))\n\t\t.filter((filter): filter is FilterExpression<RowRecord> => Boolean(filter));\n\n\tif (!filters.length) return undefined;\n\tif (filters.length === 1) return filters[0];\n\n\treturn {\n\t\tand: true,\n\t\tfilters\n\t};\n}\n\nexport function flattenFilterValuesToODataDependencies(\n\tdefinitions?: readonly ODataCompiledFilterDefinition[],\n\tvalues?: ODataFilterValues\n): Record<string, string[]> {\n\tconst normalizedDefinitions = sanitizeFilterDefinitions(definitions);\n\tconst normalizedValues = sanitizeFilterValues(values);\n\tconst dependencies: Record<string, string[]> = {};\n\n\tfor (const definition of normalizedDefinitions) {\n\t\tif (definition.kind !== \"segment\" && definition.kind !== \"tree\") continue;\n\n\t\tconst value = normalizedValues[definition.id];\n\t\tif (value === undefined) continue;\n\n\t\tif (definition.kind === \"segment\") {\n\t\t\tconst scalarValue = typeof value === \"string\" ? value : undefined;\n\t\t\tconst arrayValue = sanitizeStringArray(value);\n\t\t\tconst selectedValues = scalarValue ? [scalarValue] : arrayValue;\n\t\t\tif (!selectedValues?.length) continue;\n\n\t\t\tdependencies[definition.dictionaryCodeKey ?? definition.ownerColumnId] = selectedValues;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst treeValue = sanitizeTreeFilterValue(value);\n\t\tif (!treeValue) continue;\n\n\t\tfor (const [columnId, selectedValues] of Object.entries(treeValue)) {\n\t\t\tif (!selectedValues.length) continue;\n\t\t\tdependencies[columnId] = selectedValues;\n\t\t}\n\t}\n\n\treturn dependencies;\n}\n","/**\n * Парсер метаданных OData V2\n */\n\nimport {\n\tEntityColumnProperty,\n\tEntityMetadata,\n\tEntityParameterProperty,\n\tFunctionImportMetadata,\n\tODataMetaType,\n\tServiceMetadata\n} from \"./types\";\n\nconst TEXT_SUFFIX_REGEXP = /^(.+)(_txt|_text|_t)$/i;\nexport const FORCED_CODE_TEXT_IDS: ReadonlySet<string> = new Set([\"ZDIV\", \"ZCFO1\"]);\n\ntype AssociationSetEndpoint = {\n\trole: string;\n\tentitySet: string;\n};\n\ntype AssociationSetMetadata = {\n\tends: AssociationSetEndpoint[];\n};\n\ntype ResultNavigationMetadata = {\n\tname: \"Set\" | \"Results\";\n\ttargetEntitySet?: string;\n};\n\n/** Возвращает label metadata-колонки с fallback на технический id. */\nexport function resolveMetadataColumnLabel(column: Pick<EntityColumnProperty, \"id\" | \"label\">): string {\n\treturn column.label || column.id;\n}\n\nexport function isForcedCodeTextId(columnId?: string): boolean {\n\tif (!columnId) return false;\n\treturn FORCED_CODE_TEXT_IDS.has(columnId.toUpperCase());\n}\n\nexport function isForcedCodeTextFamilyId(columnId?: string): boolean {\n\tif (!columnId) return false;\n\n\tconst normalizedId = columnId.toUpperCase();\n\tif (FORCED_CODE_TEXT_IDS.has(normalizedId)) return true;\n\n\tconst match = normalizedId.match(/^(.+)(_TXT|_TEXT|_T)$/);\n\tif (!match) return false;\n\n\treturn FORCED_CODE_TEXT_IDS.has(match[1]!);\n}\n\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Возвращает `true`, если свойство описано скалярным EDM-типом и может быть\n * представлено в нашей метамодели без отдельной поддержки complex type.\n */\nfunction isScalarEdmPropertyType(typeName: string): boolean {\n\treturn typeName.startsWith(\"Edm.\");\n}\n\nfunction resolveColumnIdByCaseInsensitive(columnsByIdUpper: Record<string, string>, columnId?: string): string | undefined {\n\tif (!columnId) return undefined;\n\treturn columnsByIdUpper[columnId.toUpperCase()];\n}\n\nfunction findTextColumnForCodeId(\n\tcodeId: string,\n\tcolumns: EntityColumnProperty[],\n\tcolumnsByIdUpper: Record<string, string>\n): string | undefined {\n\tconst normalizedCodeId = resolveColumnIdByCaseInsensitive(columnsByIdUpper, codeId);\n\tif (!normalizedCodeId) return undefined;\n\n\tconst textColumnRegExp = new RegExp(`^${escapeRegExp(normalizedCodeId)}(_txt|_text|_t)$`, \"i\");\n\n\tfor (const column of columns) {\n\t\tif (textColumnRegExp.test(column.id)) {\n\t\t\treturn column.id;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\nfunction normalizeColumns(columns: EntityColumnProperty[]): EntityColumnProperty[] {\n\tconst columnsById: Record<string, EntityColumnProperty> = {};\n\tconst columnsByIdUpper: Record<string, string> = {};\n\n\tfor (const column of columns) {\n\t\tcolumnsById[column.id] = column;\n\t\tcolumnsByIdUpper[column.id.toUpperCase()] = column.id;\n\t}\n\n\tfor (const column of columns) {\n\t\tif (column.role === \"measure\") {\n\t\t\tcolumn.semanticType = \"none\";\n\t\t\tcolumn.linkedColumnId = undefined;\n\t\t\tcontinue;\n\t\t}\n\n\t\tcolumn.role = \"dimension\";\n\t\tcolumn.sortable = true;\n\t\tcolumn.filterable = true;\n\t\tcolumn.semanticType = TEXT_SUFFIX_REGEXP.test(column.id) ? \"text\" : \"code\";\n\n\t\tconst linkedColumnId = resolveColumnIdByCaseInsensitive(columnsByIdUpper, column.linkedColumnId);\n\t\tcolumn.linkedColumnId = linkedColumnId && linkedColumnId !== column.id ? linkedColumnId : undefined;\n\t}\n\n\tfor (const column of columns) {\n\t\tif (column.role !== \"dimension\" || column.semanticType !== \"code\") continue;\n\n\t\tlet textColumnId = column.linkedColumnId;\n\t\tif (textColumnId) {\n\t\t\tconst linkedColumn = columnsById[textColumnId];\n\t\t\tif (!linkedColumn || linkedColumn.role !== \"dimension\") {\n\t\t\t\ttextColumnId = undefined;\n\t\t\t} else {\n\t\t\t\tlinkedColumn.semanticType = \"text\";\n\t\t\t}\n\t\t}\n\n\t\tif (!textColumnId) {\n\t\t\ttextColumnId = findTextColumnForCodeId(column.id, columns, columnsByIdUpper);\n\t\t}\n\n\t\t// Часто эти пары не описаны в metadata, поэтому пробуем восстановить их по суффиксу.\n\t\tif (!textColumnId && isForcedCodeTextId(column.id)) {\n\t\t\ttextColumnId = findTextColumnForCodeId(column.id, columns, columnsByIdUpper);\n\t\t}\n\n\t\tcolumn.linkedColumnId = textColumnId;\n\n\t\tif (textColumnId) {\n\t\t\tconst textColumn = columnsById[textColumnId];\n\t\t\tif (textColumn && textColumn.role === \"dimension\") {\n\t\t\t\ttextColumn.semanticType = \"text\";\n\t\t\t\ttextColumn.linkedColumnId = column.id;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const column of columns) {\n\t\tif (column.role !== \"dimension\" || column.semanticType !== \"text\") continue;\n\n\t\tlet codeColumnId = column.linkedColumnId;\n\t\tif (codeColumnId) {\n\t\t\tconst linkedColumn = columnsById[codeColumnId];\n\t\t\tif (!linkedColumn || linkedColumn.role !== \"dimension\") {\n\t\t\t\tcodeColumnId = undefined;\n\t\t\t} else {\n\t\t\t\tlinkedColumn.semanticType = \"code\";\n\t\t\t}\n\t\t}\n\n\t\tif (!codeColumnId) {\n\t\t\tconst match = column.id.match(TEXT_SUFFIX_REGEXP);\n\t\t\tconst bySuffixCodeId = resolveColumnIdByCaseInsensitive(columnsByIdUpper, match?.[1]);\n\t\t\tif (bySuffixCodeId && columnsById[bySuffixCodeId]?.role === \"dimension\") {\n\t\t\t\tcodeColumnId = bySuffixCodeId;\n\t\t\t}\n\t\t}\n\n\t\tcolumn.linkedColumnId = codeColumnId;\n\n\t\tif (codeColumnId) {\n\t\t\tconst codeColumn = columnsById[codeColumnId];\n\t\t\tif (codeColumn && codeColumn.role === \"dimension\") {\n\t\t\t\tcodeColumn.semanticType = \"code\";\n\t\t\t\tif (!codeColumn.linkedColumnId) {\n\t\t\t\t\tcodeColumn.linkedColumnId = column.id;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn columns;\n}\n\n/**\n * Преобразует EDM-тип во внутренний тип системы.\n */\nfunction mapEdmToServiceType(edm: string): ODataMetaType {\n\tswitch (edm) {\n\t\tcase \"Edm.String\":\n\t\t\treturn \"string\";\n\t\tcase \"Edm.Guid\":\n\t\t\treturn \"guid\";\n\t\tcase \"Edm.Boolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"Edm.Int16\":\n\t\tcase \"Edm.Int32\":\n\t\t\treturn \"int\";\n\t\tcase \"Edm.Int64\":\n\t\t\treturn \"long\";\n\t\tcase \"Edm.Single\":\n\t\t\treturn \"float\";\n\t\tcase \"Edm.Decimal\":\n\t\t\treturn \"decimal\";\n\t\tcase \"Edm.Double\":\n\t\t\treturn \"double\";\n\t\tcase \"Edm.DateTime\":\n\t\t\treturn \"datetime\";\n\t\tcase \"Edm.DateTimeOffset\":\n\t\t\treturn \"datetimeOffset\";\n\t\tcase \"Edm.Time\":\n\t\t\treturn \"time\";\n\t\tcase \"Edm.Binary\":\n\t\t\treturn \"binary\";\n\t\tcase \"Edm.Byte\":\n\t\t\treturn \"byte\";\n\t\tdefault:\n\t\t\tthrow new Error(`Неподдерживаемый тип данных ${edm}`);\n\t}\n}\n\n/**\n * Создает свойство параметра из XML-элемента.\n */\nfunction createParameterProperty(element: Element): EntityParameterProperty {\n\tconst name = element.getAttribute(\"Name\")!;\n\tconst edmType = element.getAttribute(\"Type\") || \"\";\n\tconst mapped = mapEdmToServiceType(edmType);\n\n\tconst maxLength = element.hasAttribute(\"MaxLength\") ? Number(element.getAttribute(\"MaxLength\")) : undefined;\n\tconst precision = element.hasAttribute(\"Precision\") ? Number(element.getAttribute(\"Precision\")) : undefined;\n\tconst scale = element.hasAttribute(\"Scale\") ? Number(element.getAttribute(\"Scale\")) : undefined;\n\tconst label = element.getAttribute(\"sap:label\") || undefined;\n\tconst parameter = element.getAttribute(\"sap:parameter\") || undefined;\n\tconst nullable = element.getAttribute(\"Nullable\") !== \"false\" ? true : undefined;\n\n\treturn {\n\t\tid: name,\n\t\tlabel: label ?? name,\n\t\ttype: mapped,\n\t\toriginalType: edmType,\n\t\t...(mapped === \"string\" && maxLength === 1 ? { abapBooleanLike: true } : {}),\n\t\t...(maxLength !== undefined && { maxLength }),\n\t\t...(precision !== undefined && { precision }),\n\t\t...(scale !== undefined && { scale }),\n\t\t...(parameter !== undefined && { parameter }),\n\t\t...(nullable !== undefined && { nullable: true }),\n\t\t...(parameter === \"mandatory\" && { mandatory: true })\n\t};\n}\n\n/**\n * Создает свойство колонки из XML-элемента.\n */\nfunction createColumnProperty(element: Element): EntityColumnProperty {\n\tconst baseProps = createParameterProperty(element);\n\n\tconst linkedColumnId = element.getAttribute(\"sap:text\") || undefined;\n\tconst sortable = element.getAttribute(\"sap:sortable\") !== \"false\";\n\tconst filterable = element.getAttribute(\"sap:filterable\") !== \"false\";\n\tconst role = element.getAttribute(\"sap:aggregation-role\") === \"measure\" ? \"measure\" : \"dimension\";\n\tconst label = element.getAttribute(\"sap:label\") || undefined;\n\n\t// Убираем свойства, специфичные только для параметров.\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tconst { nullable, mandatory, ...columnProps } = baseProps;\n\n\treturn {\n\t\t...columnProps,\n\t\t...(linkedColumnId !== undefined && { linkedColumnId }),\n\t\t...(label !== undefined && { label }),\n\t\tsemanticType: \"none\",\n\t\tsortable,\n\t\tfilterable,\n\t\trole\n\t};\n}\n\n/**\n * Фильтрует свойства, исключая служебные.\n */\nfunction propertyFilter(element: Element): boolean {\n\tconst name = element.getAttribute(\"Name\");\n\tconst typeName = element.getAttribute(\"Type\") || \"\";\n\n\tif (!name) return false;\n\tif (!isScalarEdmPropertyType(typeName)) return false;\n\n\treturn !([/*\"ID\", \"Id\", \"id\",*/ \"CNT\", \"cnt\"].includes(name) || /_F$/i.test(name));\n}\n\n/**\n * Фильтрует свойства для колонок, исключая служебные.\n */\nfunction columnPropertyFilter(element: Element): boolean {\n\tconst name = element.getAttribute(\"Name\");\n\tconst typeName = element.getAttribute(\"Type\") || \"\";\n\n\tif (!name) return false;\n\tif (!isScalarEdmPropertyType(typeName)) return false;\n\n\treturn !([\"CNT\", \"cnt\"].includes(name) || /_F$/i.test(name));\n}\n\nfunction getProperties(element: Element): Element[] {\n\treturn Array.from(element.getElementsByTagName(\"Property\"));\n}\n\nfunction getKeys(element: Element): Element[] {\n\treturn Array.from(element.getElementsByTagName(\"PropertyRef\"));\n}\n\nfunction getNavigationProperties(element: Element): Element[] {\n\treturn Array.from(element.getElementsByTagName(\"NavigationProperty\"));\n}\n\n/**\n * Получает параметры из EntityType.\n */\nfunction getParametersProperties(entity: Element): EntityParameterProperty[] {\n\tconst properties = getProperties(entity).filter(propertyFilter);\n\treturn properties.map(createParameterProperty);\n}\n\n/**\n * Получает параметры из EntityType с учетом ключей.\n */\nfunction getParametersPropertiesWithKey(entity: Element): EntityParameterProperty[] {\n\tconst properties = getProperties(entity).filter(propertyFilter);\n\tconst keys = getKeys(entity);\n\n\treturn properties.map((property) => {\n\t\tconst param = createParameterProperty(property);\n\t\tif (keys.find((key) => key.getAttribute(\"Name\") === param.id)) {\n\t\t\tparam.mandatory = true;\n\t\t}\n\t\treturn param;\n\t});\n}\n\n/**\n * Получает колонки из EntityType.\n */\nfunction getColumnsProperties(entity: Element): EntityColumnProperty[] {\n\tconst properties = getProperties(entity).filter(columnPropertyFilter);\n\tconst columns = properties.map(createColumnProperty);\n\treturn normalizeColumns(columns);\n}\n\nfunction extractQualifiedNameShortName(value?: string | null): string | undefined {\n\tif (!value) return undefined;\n\tconst parts = value.split(\".\");\n\treturn parts[parts.length - 1] || undefined;\n}\n\nfunction createFunctionImportParameterProperty(element: Element): EntityParameterProperty {\n\tconst mode = element.getAttribute(\"Mode\");\n\tif (mode && mode !== \"In\") {\n\t\tconst name = element.getAttribute(\"Name\") || \"(unknown)\";\n\t\tthrow new Error(`FunctionImport parameter '${name}' uses unsupported Mode='${mode}'`);\n\t}\n\n\tconst typeName = element.getAttribute(\"Type\") || \"\";\n\tif (!isScalarEdmPropertyType(typeName)) {\n\t\tconst name = element.getAttribute(\"Name\") || \"(unknown)\";\n\t\tthrow new Error(`FunctionImport parameter '${name}' uses unsupported Type='${typeName}'`);\n\t}\n\n\tconst parameter = createParameterProperty(element);\n\tif (element.getAttribute(\"Nullable\") === \"false\") {\n\t\tparameter.mandatory = true;\n\t}\n\n\treturn parameter;\n}\n\nfunction buildEntityTypeByName(entityNodes: Element[]): Record<string, Element> {\n\treturn entityNodes.reduce<Record<string, Element>>((acc, entity) => {\n\t\tconst entityName = entity.getAttribute(\"Name\");\n\t\tif (entityName) {\n\t\t\tacc[entityName] = entity;\n\t\t}\n\t\treturn acc;\n\t}, {});\n}\n\nfunction buildEntitySetToEntityTypeMap(xml: Document): Record<string, string> {\n\tconst entitySets = Array.from(xml.getElementsByTagName(\"EntitySet\"));\n\n\treturn entitySets.reduce<Record<string, string>>((acc, entitySet) => {\n\t\tconst entitySetName = entitySet.getAttribute(\"Name\");\n\t\tconst entityType = extractQualifiedNameShortName(entitySet.getAttribute(\"EntityType\"));\n\t\tif (!entitySetName || !entityType) return acc;\n\n\t\tacc[entitySetName] = entityType;\n\t\treturn acc;\n\t}, {});\n}\n\nfunction buildAssociationSetByName(xml: Document): Record<string, AssociationSetMetadata> {\n\tconst associationSetNodes = Array.from(xml.getElementsByTagName(\"AssociationSet\"));\n\n\treturn associationSetNodes.reduce<Record<string, AssociationSetMetadata>>((acc, associationSet) => {\n\t\tconst associationName = associationSet.getAttribute(\"Association\");\n\t\tif (!associationName) return acc;\n\n\t\tconst ends = Array.from(associationSet.getElementsByTagName(\"End\"))\n\t\t\t.map((end) => {\n\t\t\t\tconst role = end.getAttribute(\"Role\");\n\t\t\t\tconst entitySet = end.getAttribute(\"EntitySet\");\n\t\t\t\tif (!role || !entitySet) return undefined;\n\t\t\t\treturn { role, entitySet };\n\t\t\t})\n\t\t\t.filter((end): end is AssociationSetEndpoint => Boolean(end));\n\n\t\tconst metadata = { ends };\n\t\tacc[associationName] = metadata;\n\n\t\tconst shortName = extractQualifiedNameShortName(associationName);\n\t\tif (shortName) {\n\t\t\tacc[shortName] = metadata;\n\t\t}\n\n\t\treturn acc;\n\t}, {});\n}\n\nfunction findResultNavigation(\n\tentityType: Element,\n\tassociationSetByName: Record<string, AssociationSetMetadata>\n): ResultNavigationMetadata | undefined {\n\tfor (const navigationProperty of getNavigationProperties(entityType)) {\n\t\tconst navigationName = navigationProperty.getAttribute(\"Name\");\n\t\tif (navigationName !== \"Set\" && navigationName !== \"Results\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst relationship = navigationProperty.getAttribute(\"Relationship\");\n\t\tconst associationSet = relationship ? associationSetByName[relationship] : undefined;\n\t\tconst toRole = navigationProperty.getAttribute(\"ToRole\");\n\t\tconst fromRole = navigationProperty.getAttribute(\"FromRole\");\n\n\t\tlet targetEntitySet = associationSet?.ends.find((end) => end.role === toRole)?.entitySet;\n\t\tif (!targetEntitySet && associationSet) {\n\t\t\ttargetEntitySet = associationSet.ends.find((end) => end.role !== fromRole)?.entitySet;\n\t\t}\n\n\t\treturn {\n\t\t\tname: navigationName,\n\t\t\ttargetEntitySet\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\nfunction buildInternalEntitySetNames(\n\tentitySetToEntityTypeMap: Record<string, string>,\n\tentityTypeByName: Record<string, Element>,\n\tassociationSetByName: Record<string, AssociationSetMetadata>\n): Set<string> {\n\tconst internalEntitySets = new Set<string>();\n\n\tfor (const [entitySetName, entityTypeName] of Object.entries(entitySetToEntityTypeMap)) {\n\t\tconst entityType = entityTypeByName[entityTypeName];\n\t\tif (!entityType) continue;\n\n\t\tconst resultNavigation = findResultNavigation(entityType, associationSetByName);\n\t\tif (!resultNavigation?.targetEntitySet) continue;\n\t\tif (resultNavigation.targetEntitySet === entitySetName) continue;\n\n\t\tinternalEntitySets.add(resultNavigation.targetEntitySet);\n\t}\n\n\treturn internalEntitySets;\n}\n\nfunction resolveColumnsEntityType(\n\tentityType: Element,\n\tresultNavigation: ResultNavigationMetadata | undefined,\n\tentitySetToEntityTypeMap: Record<string, string>,\n\tentityTypeByName: Record<string, Element>\n): Element {\n\tconst resultEntityTypeName = resultNavigation?.targetEntitySet ? entitySetToEntityTypeMap[resultNavigation.targetEntitySet] : undefined;\n\treturn (resultEntityTypeName && entityTypeByName[resultEntityTypeName]) || entityType;\n}\n\nfunction resolveEntityParameters(entityType: Element, entityTypeName: string, resultNavigation: ResultNavigationMetadata | undefined) {\n\tif (resultNavigation) {\n\t\treturn getParametersProperties(entityType);\n\t}\n\n\tif (entityTypeName.endsWith(\"Type\")) {\n\t\treturn undefined;\n\t}\n\n\treturn getParametersPropertiesWithKey(entityType);\n}\n\nfunction getActionForKeyIds(actionFor: string | undefined, entityTypeByName: Record<string, Element>): Set<string> {\n\tif (!actionFor) return new Set<string>();\n\n\tconst entityTypeName = extractQualifiedNameShortName(actionFor);\n\tif (!entityTypeName) return new Set<string>();\n\n\tconst entityType = entityTypeByName[entityTypeName];\n\tif (!entityType) return new Set<string>();\n\n\treturn new Set(\n\t\tgetKeys(entityType)\n\t\t\t.map((key) => key.getAttribute(\"Name\"))\n\t\t\t.filter((value): value is string => Boolean(value))\n\t);\n}\n\nfunction parseFunctionImport(\n\telement: Element,\n\tentitySetToEntityTypeMap: Record<string, string>,\n\tentityTypeByName: Record<string, Element>\n): FunctionImportMetadata {\n\tconst name = element.getAttribute(\"Name\") || \"\";\n\tconst entitySet = element.getAttribute(\"EntitySet\") || undefined;\n\tconst actionFor = element.getAttribute(\"sap:action-for\") || undefined;\n\tconst actionForKeyIds = getActionForKeyIds(actionFor, entityTypeByName);\n\tconst parameters = Array.from(element.getElementsByTagName(\"Parameter\")).map((parameterElement) => {\n\t\tconst parameter = createFunctionImportParameterProperty(parameterElement);\n\t\tif (actionForKeyIds.has(parameter.id)) {\n\t\t\tparameter.mandatory = true;\n\t\t}\n\t\treturn parameter;\n\t});\n\n\treturn {\n\t\tname,\n\t\ttitle: element.getAttribute(\"sap:label\") || \"\",\n\t\thttpMethod: (element.getAttribute(\"m:HttpMethod\") as FunctionImportMetadata[\"httpMethod\"] | null) || undefined,\n\t\tparameters: parameters.length ? parameters : undefined,\n\t\treturnType: element.getAttribute(\"ReturnType\") || \"\",\n\t\t...(entitySet !== undefined && { entitySet }),\n\t\t...(actionFor !== undefined && { actionFor }),\n\t\t...(entitySet && entitySetToEntityTypeMap[entitySet] ? { resultEntity: entitySet } : {})\n\t};\n}\n\n/**\n * Парсит метаданные OData V2 из XML.\n */\nexport function parseServiceMetadata(xmlText: string): ServiceMetadata {\n\tconst parser = new DOMParser();\n\tconst xml = parser.parseFromString(xmlText, \"application/xml\");\n\tconst entityNodes = Array.from(xml.getElementsByTagName(\"EntityType\"));\n\tconst functionImportNodes = Array.from(xml.getElementsByTagName(\"FunctionImport\"));\n\tconst entitySetToEntityTypeMap = buildEntitySetToEntityTypeMap(xml);\n\tconst entityTypeByName = buildEntityTypeByName(entityNodes);\n\tconst associationSetByName = buildAssociationSetByName(xml);\n\tconst internalEntitySets = buildInternalEntitySetNames(entitySetToEntityTypeMap, entityTypeByName, associationSetByName);\n\n\tconst entities: Record<string, EntityMetadata> = {};\n\tconst functionImports: Record<string, FunctionImportMetadata> = {};\n\n\tfor (const [entitySetName, entityTypeName] of Object.entries(entitySetToEntityTypeMap)) {\n\t\tif (internalEntitySets.has(entitySetName)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst entityType = entityTypeByName[entityTypeName];\n\t\tif (!entityType) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst resultNavigation = findResultNavigation(entityType, associationSetByName);\n\t\tconst columnsEntityType = resolveColumnsEntityType(entityType, resultNavigation, entitySetToEntityTypeMap, entityTypeByName);\n\t\tconst title = entityType.getAttribute(\"sap:label\") || columnsEntityType.getAttribute(\"sap:label\") || \"\";\n\t\tconst columns = getColumnsProperties(columnsEntityType);\n\t\tconst parameters = resolveEntityParameters(entityType, entityTypeName, resultNavigation);\n\n\t\tentities[entitySetName] = {\n\t\t\ttitle,\n\t\t\tcolumns,\n\t\t\t...(parameters?.length ? { parameters } : {}),\n\t\t\t...(resultNavigation ? { result: resultNavigation.name } : {})\n\t\t};\n\t}\n\n\tfor (const functionImport of functionImportNodes) {\n\t\tconst parsed = parseFunctionImport(functionImport, entitySetToEntityTypeMap, entityTypeByName);\n\t\tfunctionImports[parsed.name] = parsed;\n\t}\n\n\treturn { entities, functionImports };\n}\n","export interface Sort<T> {\n\tkey: T;\n\t/**\n\t * @default false (asc)\n\t */\n\tdesc?: true;\n}\n\nexport function getSortIndex<T>(sorting: Sort<keyof T>[], key: keyof T): number {\n\treturn sorting.findIndex((s) => s.key === key);\n}\n\nexport function buildODataOrder<T>(sorting: Sort<keyof T>[]): string {\n\treturn sorting.map((s) => `${String(s.key)} ${s.desc ? \"desc\" : \"asc\"}`).join(\",\");\n}\n\nexport function toggleSort<T>(sorting: Sort<keyof T>[], key: keyof T, multi: boolean): Sort<keyof T>[] {\n\tconst idx = getSortIndex(sorting, key);\n\n\t// single-sort: начинаем с чистого массива (кроме клика по уже существующему — тоже можно сбрасывать)\n\tconst base = multi ? [...sorting] : [...sorting.filter((s) => s.key === key)];\n\n\tif (idx === -1) {\n\t\tbase.push({ key });\n\t\treturn base;\n\t}\n\n\tconst current = sorting[idx]!;\n\tif (!current.desc) {\n\t\t// asc -> desc\n\t\treturn base.map((s) => (s.key === key ? { key, desc: true } : s));\n\t}\n\n\t// desc -> remove\n\treturn base.filter((s) => s.key !== key);\n}\n\n/**\n * Возвращает эффективный набор сортировок для аналитической таблицы.\n *\n * Правило:\n * - при наличии пользовательской сортировки используется только она;\n * - если пользовательская сортировка отсутствует, используется сортировка по полям группировки (asc).\n */\nexport function resolveEffectiveSorts<TKey extends PropertyKey>(grouping: TKey[], sorting: Sort<TKey>[]): Sort<TKey>[] {\n\tif (sorting.length > 0) {\n\t\treturn sorting.map((item) => ({ key: item.key, desc: item.desc }));\n\t}\n\n\treturn grouping.map((key) => ({ key }));\n}\n\nexport function buildODataOrderBy<T>(grouping: (keyof T)[], sorting: Sort<keyof T>[]): string | undefined {\n\tconst effectiveSorting = resolveEffectiveSorts(grouping, sorting);\n\tconst parts = effectiveSorting.map((item) => `${String(item.key)} ${item.desc ? \"desc\" : \"asc\"}`);\n\n\treturn parts.length ? parts.join(\",\") : undefined;\n}\n\nexport function getSortIndicator<T>(\n\tgrouping: (keyof T)[],\n\tsorting: Sort<keyof T>[],\n\tcolId: keyof T\n): { active: boolean; desc?: boolean; order?: number; lockedByGrouping?: boolean } {\n\tconst hasUserSorting = sorting.length > 0;\n\tconst gIdx = grouping.indexOf(colId);\n\tif (!hasUserSorting && gIdx !== -1) {\n\t\treturn { active: true, order: gIdx + 1, lockedByGrouping: true };\n\t}\n\n\tconst sIdx = sorting.findIndex((s) => s.key === colId);\n\tif (sIdx === -1) return { active: false };\n\n\treturn { active: true, desc: sorting[sIdx]?.desc, order: sIdx + 1 };\n}\n","export type SqlFilterScalarValue = string | number | boolean;\n\nexport type SqlFilterOperation = \"eq\" | \"in\";\n\nexport type SqlFilterEqualCondition = {\n\t/** Имя SQL-поля после всех доменных маппингов. */\n\tfieldId: string;\n\t/** Оператор строгого равенства. */\n\toperation: \"eq\";\n\t/** Исходное значение фильтра. Неподдерживаемые и пустые значения не сериализуются. */\n\tvalue: unknown;\n};\n\nexport type SqlFilterInCondition = {\n\t/** Имя SQL-поля после всех доменных маппингов. */\n\tfieldId: string;\n\t/** Оператор включения в список значений. */\n\toperation: \"in\";\n\t/** Исходные значения фильтра. Неподдерживаемые и пустые значения не сериализуются. */\n\tvalues: readonly unknown[] | null | undefined;\n};\n\nexport type SqlFilterCondition = SqlFilterEqualCondition | SqlFilterInCondition;\n\nconst SQL_FILTER_FIELD_ID_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport function isSqlFilterScalarValue(value: unknown): value is SqlFilterScalarValue {\n\treturn typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\";\n}\n\nexport function assertSqlFilterFieldId(fieldId: string): void {\n\tif (!SQL_FILTER_FIELD_ID_PATTERN.test(fieldId)) {\n\t\tthrow new Error(`Некорректное имя поля SQL-фильтра: ${fieldId}`);\n\t}\n}\n\nexport function createSqlFilterEqual(fieldId: string, value: unknown): SqlFilterEqualCondition {\n\treturn { fieldId, operation: \"eq\", value };\n}\n\nexport function createSqlFilterIn(fieldId: string, values: readonly unknown[] | null | undefined): SqlFilterInCondition {\n\treturn { fieldId, operation: \"in\", values };\n}\n\nfunction normalizeSqlFilterValue(value: unknown): string | undefined {\n\tif (value instanceof Date) {\n\t\tthrow new Error(\"Дата должна быть отформатирована вызывающей стороной до формирования SQL-фильтра\");\n\t}\n\n\tif (!isSqlFilterScalarValue(value)) return undefined;\n\n\tif (typeof value === \"number\" && !Number.isFinite(value)) return undefined;\n\n\tconst rawValue = String(value);\n\tif (!rawValue || rawValue.trim() === \"\") return undefined;\n\n\treturn `'${rawValue.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction buildSqlFilterCondition(condition: SqlFilterCondition): string | undefined {\n\tif (condition.operation === \"eq\") {\n\t\tconst formattedValue = normalizeSqlFilterValue(condition.value);\n\t\tif (!formattedValue) return undefined;\n\n\t\tassertSqlFilterFieldId(condition.fieldId);\n\t\treturn `${condition.fieldId}=${formattedValue}`;\n\t}\n\n\tconst formattedValues = (condition.values ?? [])\n\t\t.map((value) => normalizeSqlFilterValue(value))\n\t\t.filter((value): value is string => Boolean(value));\n\tif (formattedValues.length === 0) return undefined;\n\n\tassertSqlFilterFieldId(condition.fieldId);\n\treturn `${condition.fieldId} IN (${formattedValues.join(\", \")})`;\n}\n\n/**\n * Формирует SQL-подобный фильтр для legacy payload, который backend вставляет в dynamic WHERE.\n *\n * Это не OData `$filter`: оператор `IN` здесь допустим только потому, что строка уходит в тело запроса,\n * а не в SAP Gateway URL. Для защиты от падения dynamic WHERE builder намеренно разрешает только\n * простые имена полей и строковые литералы с экранированными одинарными кавычками.\n */\nexport function buildSqlFilter(conditions: readonly SqlFilterCondition[] | undefined): string {\n\tif (!conditions) return \"\";\n\n\treturn conditions\n\t\t.map((condition) => buildSqlFilterCondition(condition))\n\t\t.filter((condition): condition is string => Boolean(condition))\n\t\t.join(\" AND \");\n}\n","import { type ODataBooleanType, type ODataDateType, type ODataIntegerType, type ODataMetaType, type ODataNumericType } from \"./types\";\n\nexport function isODataBooleanType(type: ODataMetaType | undefined): type is ODataBooleanType {\n\treturn type === \"boolean\";\n}\n\nexport function isODataNumericType(type: ODataMetaType | undefined): type is ODataNumericType {\n\treturn type === \"byte\" || type === \"int\" || type === \"long\" || type === \"float\" || type === \"decimal\" || type === \"double\";\n}\n\nexport function isODataIntegerType(type: ODataMetaType | undefined): type is ODataIntegerType {\n\treturn type === \"byte\" || type === \"int\" || type === \"long\";\n}\n\nexport function isODataDateType(type: ODataMetaType | undefined): type is ODataDateType {\n\treturn type === \"datetime\" || type === \"datetimeOffset\" || type === \"time\";\n}\n","import type { UseQueryResult } from \"@tanstack/react-query\";\n\n/**\n * Стандартный ответ `odataQueryFn` после трансформации данных.\n */\ninterface ODataQueryResultEnvelope<T> {\n\tdata: T;\n\ttotalCount?: number;\n}\n\n/**\n * Результат query-хука с уже распакованным полем `data`.\n */\nexport type UnwrappedODataQueryResult<T> = Omit<UseQueryResult<ODataQueryResultEnvelope<T>>, \"data\"> & {\n\tdata: T | undefined;\n\ttotalCount?: number;\n};\n\n/**\n * Приводит результат `useQuery` с `odataQueryFn` к привычному виду:\n * данные доступны сразу в `data`, а `totalCount` вынесен отдельно.\n */\nexport function unwrapODataQueryResult<T>(query: UseQueryResult<ODataQueryResultEnvelope<T>>): UnwrappedODataQueryResult<T> {\n\tconst data = query.data?.data;\n\tconst totalCount = query.data?.totalCount;\n\n\treturn { ...query, data, totalCount };\n}\n","import { BaseType, InputType, RangeType } from \"../types\";\nimport { isObject } from \"../validators\";\n\nexport function normalizeRangeValue(value: InputType): RangeType {\n\tif (Array.isArray(value)) {\n\t\treturn [value[0] ?? null, value[1] ?? null];\n\t}\n\n\treturn [isBaseValue(value) ? (value ?? null) : null, null];\n}\n\nexport function normalizeBaseValue(value: InputType): BaseType {\n\tif (value instanceof Date) {\n\t\treturn value;\n\t}\n\n\tif (Array.isArray(value) || isObject(value)) {\n\t\treturn null;\n\t}\n\n\treturn value;\n}\n\nexport function isBaseValue(value: unknown): value is BaseType {\n\treturn value == null || typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" || value instanceof Date;\n}\n","import { UnwrappedODataParameters, WrapODataParameters, WrappedODataParameters } from \"./types\";\n\n// export function wrapODataParams(data: Record<string, unknown>): Record<string, ODataValue> {\n// \tif (!data) return {};\n// \treturn Object.entries(data).reduce(\n// \t\t(acc, [key, value]) => {\n// \t\t\t// NOTE: пропускаем пустые строки и 0\n// \t\t\tif (value != null) {\n// \t\t\t\tacc[key] = { value };\n// \t\t\t}\n// \t\t\treturn acc;\n// \t\t},\n// \t\t{} as Record<string, ODataValue>\n// \t);\n// }\n\n/**\n * Типизированный хелпер для преобразования плоской структуры в wrapped.\n */\nexport function wrapODataParams<T extends UnwrappedODataParameters>(params: T | undefined | null): WrapODataParameters<T> {\n\tif (!params) return {} as WrapODataParameters<T>;\n\n\tconst result = {} as WrapODataParameters<T>;\n\tfor (const key in params) {\n\t\tresult[key] = { value: params[key] };\n\t}\n\n\treturn result;\n}\n\nexport function unwrapODataParams(params?: WrappedODataParameters): UnwrappedODataParameters | undefined {\n\tif (!params) return undefined;\n\n\tconst normalized: UnwrappedODataParameters = {};\n\tfor (const key of Object.keys(params).sort()) {\n\t\tnormalized[key] = params[key]?.value ?? null;\n\t}\n\n\treturn normalized;\n}\n"],"mappings":"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"}