diff --git a/ordinis-admin-ui/src/components/geo/AoiPickerDialog.tsx b/ordinis-admin-ui/src/components/geo/AoiPickerDialog.tsx index 7548822..8c06e46 100644 --- a/ordinis-admin-ui/src/components/geo/AoiPickerDialog.tsx +++ b/ordinis-admin-ui/src/components/geo/AoiPickerDialog.tsx @@ -62,14 +62,21 @@ export const AoiPickerDialog = ({ isOpen, onClose, onApply, initial }: Props) => const tryInit = () => { if (cancelled) return + if (mapRef.current) return // уже init'нут const div = mapDivRef.current - if (!div || mapRef.current) return - // Defer пока container не имеет реальный размер — RAF до 100 кадров - // (~1.6s @ 60fps), потом сдаёмся и init'им как есть (fallback). - if ((div.clientWidth === 0 || div.clientHeight === 0) && rafId < 100) { - rafId += 1 - requestAnimationFrame(tryInit) + // Modal от @nstart/ui рендерит children только после useAnimatedPresence + // флипает isMounted=true (на след. рендер после isOpen=true). Наш useEffect + // фаерится РАНЬШЕ — div ещё не в DOM. Plus modal transform animation + // изначально даёт 0×0 размер. Poll'им RAF до тех пор пока: + // - div существует (ref populated на render когда modal mounted'нул его) + // - clientWidth и clientHeight > 0 (после layout & transform settled) + // Cap на 100 кадров (~1.6s) — fallback если что-то совсем странное. + if (!div || div.clientWidth === 0 || div.clientHeight === 0) { + if (rafId < 100) { + rafId += 1 + requestAnimationFrame(tryInit) + } return } @@ -180,12 +187,12 @@ export const AoiPickerDialog = ({ isOpen, onClose, onApply, initial }: Props) =>