function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
var _excluded = ["x", "y", "zIndex", "width", "height"];
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
/**
 * 平面图编辑态：草稿配置、画布 Tab、选中、放置模式、落点、侧栏更新/删除/保存记录
 */
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { message } from 'antd';
import { locales } from '@pisell/utils';
import useEngineContext from "../../../hooks/useEngineContext";
import { createTranslationText } from "../../translation/utils";
import { mergeCanvasItems } from "../utils/floorMapConfigMerge";
import { STAGE_DECO_DEFAULT } from "../utils/floorMapStageDefaults";
import { floorMapViewConfigsEqual, normalizeFloorMapViewConfigFromProp } from "../utils/floorMapViewConfigDiff";
import { getElementKindConfig, resolveDataBindingPolicy, isFloorMapImageElementKind } from "../utils/floorMapElementKindUtils";
import { DEFAULT_CELL_SIZE } from "../utils/layoutMeasurements";
import { initFloorMapLayoutLocales } from "../utils/floorMapCanvasDisplay";
import { FLOOR_MAP_STAGE_ELEMENT_KIND } from "../types";
var IMAGE_PLACE_DEFAULT = {
  width: 400,
  height: 240
};
var I18N_PLACEMENT_FALLBACK_IMAGE = 'pisell-floor-map-layout.placement.fallback-image-name';
var GRID_VIS_STORAGE_PREFIX = 'pisell-floor-map-layout.grid-visible';
function getGridVisStorageKey(canvasId) {
  return "".concat(GRID_VIS_STORAGE_PREFIX, ":").concat(canvasId);
}
function readStoredGridVisible(canvasId) {
  try {
    var raw = localStorage.getItem(getGridVisStorageKey(canvasId));
    if (raw == null) return null;
    if (raw === '1') return true;
    if (raw === '0') return false;
    return null;
  } catch (_unused) {
    return null;
  }
}
function writeStoredGridVisible(canvasId, visible) {
  try {
    localStorage.setItem(getGridVisStorageKey(canvasId), visible ? '1' : '0');
  } catch (_unused2) {
    // ignore localStorage failure (private mode / quota / sandbox)
  }
}

/** 批量落位时每条相对上一条的偏移（内容坐标） */
var BATCH_PLACE_OFFSET = 16;
function newInstanceId() {
  return "elm_".concat(Date.now(), "_").concat(Math.random().toString(36).slice(2, 9));
}
function duplicateBinding(elements, binding, exceptInstanceId) {
  return (elements !== null && elements !== void 0 ? elements : []).some(function (e) {
    var _e$dataBinding, _e$dataBinding2;
    return e.instanceId !== exceptInstanceId && ((_e$dataBinding = e.dataBinding) === null || _e$dataBinding === void 0 ? void 0 : _e$dataBinding.dataSourceKey) === binding.dataSourceKey && ((_e$dataBinding2 = e.dataBinding) === null || _e$dataBinding2 === void 0 ? void 0 : _e$dataBinding2.recordId) === binding.recordId;
  });
}
export function useFloorMapEditState(params) {
  var _engineCtx$engine, _selectedItem$_sceneE;
  var floorMapConfigProp = params.floorMapConfigProp,
    isFloorMapView = params.isFloorMapView,
    itemsProp = params.itemsProp,
    cellSizeProp = params.cellSizeProp,
    dataSources = params.dataSources,
    onSave = params.onSave,
    onDataSourceRecordSave = params.onDataSourceRecordSave,
    dataSourceFormColumns = params.dataSourceFormColumns,
    dataSourceRecordForm = params.dataSourceRecordForm,
    dataSourceLabels = params.dataSourceLabels,
    layoutPrefix = params.layoutPrefix,
    contentOffsetRef = params.contentOffsetRef,
    showDataSourceRecordFormBlock = params.showDataSourceRecordFormBlock;
  var engineCtx = useEngineContext();
  var engineLocale = (engineCtx === null || engineCtx === void 0 || (_engineCtx$engine = engineCtx.engine) === null || _engineCtx$engine === void 0 || (_engineCtx$engine = _engineCtx$engine.props) === null || _engineCtx$engine === void 0 ? void 0 : _engineCtx$engine.locale) || 'zh-CN';
  var _useState = useState(null),
    _useState2 = _slicedToArray(_useState, 2),
    draftConfig = _useState2[0],
    setDraftConfig = _useState2[1];
  var _useState3 = useState(null),
    _useState4 = _slicedToArray(_useState3, 2),
    currentCanvasId = _useState4[0],
    setCurrentCanvasId = _useState4[1];
  var _useState5 = useState(null),
    _useState6 = _slicedToArray(_useState5, 2),
    selectedId = _useState6[0],
    setSelectedId = _useState6[1];
  var _useState7 = useState(null),
    _useState8 = _slicedToArray(_useState7, 2),
    placeMode = _useState8[0],
    setPlaceMode = _useState8[1];
  var _useState9 = useState(false),
    _useState10 = _slicedToArray(_useState9, 2),
    saving = _useState10[0],
    setSaving = _useState10[1];
  var _useState11 = useState(false),
    _useState12 = _slicedToArray(_useState11, 2),
    savingRecord = _useState12[0],
    setSavingRecord = _useState12[1];
  /**
   * 本地“已提交保存”的基线快照：
   * - 点击「完成编辑/保存」后立即置为当前 draft，避免等待上游 props 回写期间仍显示“未持久化”提示；
   * - 用户后续再改动 draft 时，dirty 会再次为 true。
   */
  var _useState13 = useState(null),
    _useState14 = _slicedToArray(_useState13, 2),
    savedBaselineConfig = _useState14[0],
    setSavedBaselineConfig = _useState14[1];
  var config = isFloorMapView ? draftConfig !== null && draftConfig !== void 0 ? draftConfig : floorMapConfigProp : null;
  var configRef = useRef(config);
  configRef.current = config;
  useEffect(function () {
    if (!floorMapConfigProp) return;
    var baseConfig = normalizeFloorMapViewConfigFromProp(floorMapConfigProp);
    var nextConfig = _objectSpread(_objectSpread({}, baseConfig), {}, {
      canvases: baseConfig.canvases.map(function (canvas) {
        var _canvas$mapLayer;
        var stored = readStoredGridVisible(canvas.id);
        if (stored == null) return canvas;
        return _objectSpread(_objectSpread({}, canvas), {}, {
          mapLayer: _objectSpread(_objectSpread({}, (_canvas$mapLayer = canvas.mapLayer) !== null && _canvas$mapLayer !== void 0 ? _canvas$mapLayer : {}), {}, {
            showGrid: stored
          })
        });
      })
    });
    setDraftConfig(nextConfig);
    /** 上游配置已刷新，以服务端/父级为准，清空本地临时保存基线 */
    setSavedBaselineConfig(null);
    var enabled = nextConfig.canvases.filter(function (c) {
      return c.enabled;
    }).sort(function (a, b) {
      return a.order - b.order;
    });
    setCurrentCanvasId(function (prev) {
      var _enabled$0$id, _enabled$;
      return prev && enabled.some(function (c) {
        return c.id === prev;
      }) ? prev : (_enabled$0$id = (_enabled$ = enabled[0]) === null || _enabled$ === void 0 ? void 0 : _enabled$.id) !== null && _enabled$0$id !== void 0 ? _enabled$0$id : null;
    });
  }, [floorMapConfigProp]);

  /** 当前草稿与上游持久化 `floorMapConfig`（经同等规范化）是否不一致 */
  var isLayoutDirty = useMemo(function () {
    if (!isFloorMapView || !draftConfig || !floorMapConfigProp) return false;
    var baseline = savedBaselineConfig !== null && savedBaselineConfig !== void 0 ? savedBaselineConfig : normalizeFloorMapViewConfigFromProp(floorMapConfigProp);
    return !floorMapViewConfigsEqual(draftConfig, baseline);
  }, [isFloorMapView, draftConfig, floorMapConfigProp, savedBaselineConfig]);
  var handleAddCanvas = useCallback(function () {
    initFloorMapLayoutLocales(engineLocale);
    var label = locales.getText('pisell-floor-map-layout.canvas-tabs.default-new-canvas-name');
    var defaultName = createTranslationText(label, true);
    var newId = "floor_".concat(Date.now());
    var newCanvas = {
      id: newId,
      name: defaultName,
      order: 0,
      enabled: true
    };
    setDraftConfig(function (prev) {
      if (!prev) return prev;
      var list = prev.canvases.filter(function (c) {
        return c.enabled;
      }).sort(function (a, b) {
        return a.order - b.order;
      });
      newCanvas.order = list.length > 0 ? Math.max.apply(Math, _toConsumableArray(list.map(function (c) {
        return c.order;
      }))) + 1 : 0;
      return _objectSpread(_objectSpread({}, prev), {}, {
        canvases: [].concat(_toConsumableArray(prev.canvases), [newCanvas])
      });
    });
    setCurrentCanvasId(newId);
  }, [engineLocale]);
  var handleRemoveCanvas = useCallback(function (canvasId) {
    setDraftConfig(function (prev) {
      var _prev$sceneElements;
      if (!prev) return prev;
      var nextCanvases = prev.canvases.filter(function (c) {
        return c.id !== canvasId;
      });
      if (nextCanvases.length === 0) return prev;
      return _objectSpread(_objectSpread({}, prev), {}, {
        canvases: nextCanvases,
        sceneElements: ((_prev$sceneElements = prev.sceneElements) !== null && _prev$sceneElements !== void 0 ? _prev$sceneElements : []).filter(function (e) {
          return e.canvasId !== canvasId;
        })
      });
    });
    setCurrentCanvasId(function (prev) {
      var _enabled$0$id2, _enabled$2;
      if (prev !== canvasId) return prev;
      var cfg = configRef.current;
      if (!cfg) return prev;
      var enabled = cfg.canvases.filter(function (c) {
        return c.id !== canvasId && c.enabled;
      }).sort(function (a, b) {
        return a.order - b.order;
      });
      return (_enabled$0$id2 = (_enabled$2 = enabled[0]) === null || _enabled$2 === void 0 ? void 0 : _enabled$2.id) !== null && _enabled$0$id2 !== void 0 ? _enabled$0$id2 : null;
    });
  }, []);
  var handleRenameCanvas = useCallback(function (canvasId, name) {
    if (typeof name === 'string') {
      var trimmed = name.trim();
      if (!trimmed) return;
      setDraftConfig(function (prev) {
        if (!prev) return prev;
        return _objectSpread(_objectSpread({}, prev), {}, {
          canvases: prev.canvases.map(function (c) {
            return c.id === canvasId ? _objectSpread(_objectSpread({}, c), {}, {
              name: trimmed,
              nameKey: undefined
            }) : c;
          })
        });
      });
      return;
    }
    var hasAny = Object.values(name).some(function (s) {
      return typeof s === 'string' && s.trim();
    });
    if (!hasAny) return;
    setDraftConfig(function (prev) {
      if (!prev) return prev;
      return _objectSpread(_objectSpread({}, prev), {}, {
        canvases: prev.canvases.map(function (c) {
          return c.id === canvasId ? _objectSpread(_objectSpread({}, c), {}, {
            name: name,
            nameKey: undefined
          }) : c;
        })
      });
    });
  }, []);
  var mergedItems = useMemo(function () {
    if (!isFloorMapView || !config || !currentCanvasId) return [];
    return mergeCanvasItems(currentCanvasId, config, cellSizeProp !== null && cellSizeProp !== void 0 ? cellSizeProp : DEFAULT_CELL_SIZE);
  }, [isFloorMapView, config, currentCanvasId, cellSizeProp]);
  var items = isFloorMapView ? mergedItems : itemsProp;
  var updateDraftSceneElement = useCallback(function (instanceId, patch) {
    setDraftConfig(function (prev) {
      var _prev$sceneElements2, _prev$sceneElements3;
      if (!prev) return prev;
      var current = ((_prev$sceneElements2 = prev.sceneElements) !== null && _prev$sceneElements2 !== void 0 ? _prev$sceneElements2 : []).find(function (e) {
        return e.instanceId === instanceId;
      });
      var normalized = _objectSpread({}, patch);
      var unlocking = patch.layoutTransformLocked === false;
      if (current !== null && current !== void 0 && current.layoutTransformLocked && !unlocking) {
        var _normalized = normalized,
          _x = _normalized.x,
          _y = _normalized.y,
          _z = _normalized.zIndex,
          _w = _normalized.width,
          _h = _normalized.height,
          rest = _objectWithoutProperties(_normalized, _excluded);
        normalized = rest;
      }
      if (normalized.x !== undefined) normalized.x = Math.round(normalized.x);
      if (normalized.y !== undefined) normalized.y = Math.round(normalized.y);
      if (normalized.width !== undefined) normalized.width = Math.round(normalized.width);
      if (normalized.height !== undefined) normalized.height = Math.round(normalized.height);
      var list = ((_prev$sceneElements3 = prev.sceneElements) !== null && _prev$sceneElements3 !== void 0 ? _prev$sceneElements3 : []).map(function (e) {
        return e.instanceId === instanceId ? _objectSpread(_objectSpread({}, e), normalized) : e;
      });
      return _objectSpread(_objectSpread({}, prev), {}, {
        sceneElements: list
      });
    });
  }, []);
  var handleUpdateItem = useCallback(function (itemId, patch) {
    updateDraftSceneElement(itemId, patch);
  }, [updateDraftSceneElement]);
  var placeOverlayClass = "".concat(layoutPrefix, "-place-overlay");

  /**
   * 在内容坐标系下按「新建图元」模式落 sceneElement（支持 recordIds 批量；点击与拖拽共用）
   * @returns 是否已成功写入草稿（校验失败时为 false）
   */
  var applyScenePlacementAtCoords = useCallback(function (contentX, contentY, scene) {
    var _kindConfig$allowedDa, _ref, _scene$dataSourceKey;
    if (!config || !currentCanvasId) return false;
    var defaultPlacementWidth = 180;
    var defaultPlacementHeight = 120;
    var defaultDecoSize = 48;
    var kindConfig = getElementKindConfig(config, scene.elementKind);
    var policy = resolveDataBindingPolicy(kindConfig);
    var allKeys = Object.keys(dataSources !== null && dataSources !== void 0 ? dataSources : {});
    var allowedKeys = kindConfig !== null && kindConfig !== void 0 && (_kindConfig$allowedDa = kindConfig.allowedDataSourceKeys) !== null && _kindConfig$allowedDa !== void 0 && _kindConfig$allowedDa.length ? kindConfig.allowedDataSourceKeys.filter(function (k) {
      return allKeys.includes(k);
    }) : allKeys;
    var pickKey = (_ref = (_scene$dataSourceKey = scene.dataSourceKey) !== null && _scene$dataSourceKey !== void 0 ? _scene$dataSourceKey : allowedKeys[0]) !== null && _ref !== void 0 ? _ref : allKeys[0];
    var recordIdsToPlace = scene.recordIds && scene.recordIds.length > 0 ? scene.recordIds : scene.recordId ? [scene.recordId] : [];
    var isStage = scene.elementKind === FLOOR_MAP_STAGE_ELEMENT_KIND;
    var isImage = isFloorMapImageElementKind(scene.elementKind);
    var w = isImage ? IMAGE_PLACE_DEFAULT.width : isStage ? STAGE_DECO_DEFAULT.width : defaultPlacementWidth;
    var h = isImage ? IMAGE_PLACE_DEFAULT.height : isStage ? STAGE_DECO_DEFAULT.height : defaultPlacementHeight;
    var useDecoSize = policy === 'none' && scene.elementKind !== FLOOR_MAP_STAGE_ELEMENT_KIND && !isImage;
    var buildOneElement = function buildOneElement(dataBinding, x, y, name) {
      return _objectSpread({
        instanceId: newInstanceId(),
        canvasId: currentCanvasId,
        x: x,
        y: y,
        name: name,
        zIndex: isImage ? -5 : 0,
        width: useDecoSize ? defaultDecoSize : w,
        height: useDecoSize ? defaultDecoSize : h,
        elementKind: scene.elementKind,
        shape: isStage || isImage ? 'rect' : kindConfig === null || kindConfig === void 0 ? void 0 : kindConfig.defaultShape,
        dataBinding: dataBinding
      }, isImage ? {
        imageUrl: ''
      } : {});
    };
    var dataBinding;
    if (policy !== 'none' && pickKey) {
      var _dataSources$pickKey;
      var dsList = (_dataSources$pickKey = dataSources === null || dataSources === void 0 ? void 0 : dataSources[pickKey]) !== null && _dataSources$pickKey !== void 0 ? _dataSources$pickKey : [];
      if (dsList.length === 0) {
        dataBinding = {
          dataSourceKey: pickKey,
          recordId: "new_".concat(Date.now())
        };
      } else if (recordIdsToPlace.length === 0) {
        if (policy === 'required') {
          message.warning('请先在侧栏选择数据源与数据行，再落位');
          return false;
        }
      } else if (recordIdsToPlace.length === 1) {
        var rid = recordIdsToPlace[0];
        var record = dsList.find(function (r) {
          return r.id === rid;
        });
        if (!record) {
          message.error('所选记录不存在，请重新选择数据行');
          return false;
        }
        var cand = {
          dataSourceKey: pickKey,
          recordId: rid
        };
        if (duplicateBinding(config.sceneElements, cand)) {
          message.warning('该数据记录已在平面图中绑定，请勿重复添加');
          return false;
        }
        dataBinding = cand;
      } else {
        var newEls = [];
        var skippedDup = 0;
        var skippedMissing = 0;
        var placeIndex = 0;
        var seenInBatch = new Set();
        recordIdsToPlace.forEach(function (rid) {
          var _row$name;
          var record = dsList.find(function (r) {
            return r.id === rid;
          });
          if (!record) {
            skippedMissing += 1;
            return;
          }
          var cand = {
            dataSourceKey: pickKey,
            recordId: rid
          };
          if (seenInBatch.has(rid) || duplicateBinding(config.sceneElements, cand)) {
            skippedDup += 1;
            return;
          }
          seenInBatch.add(rid);
          var row = record;
          var placementName = String((_row$name = row === null || row === void 0 ? void 0 : row.name) !== null && _row$name !== void 0 ? _row$name : rid);
          newEls.push(buildOneElement(cand, contentX + placeIndex * BATCH_PLACE_OFFSET, contentY + placeIndex * BATCH_PLACE_OFFSET, placementName));
          placeIndex += 1;
        });
        if (skippedDup > 0) {
          message.warning("\u5DF2\u8DF3\u8FC7 ".concat(skippedDup, " \u6761\u5DF2\u5728\u5E73\u9762\u56FE\u4E2D\u7ED1\u5B9A\u7684\u8BB0\u5F55"));
        }
        if (skippedMissing > 0) {
          message.warning("\u6709 ".concat(skippedMissing, " \u6761\u8BB0\u5F55\u4E0D\u5B58\u5728\uFF0C\u5DF2\u8DF3\u8FC7"));
        }
        if (newEls.length === 0) {
          message.warning('没有可落位的记录');
          return false;
        }
        setDraftConfig(function (prev) {
          var _prev$sceneElements4;
          return prev ? _objectSpread(_objectSpread({}, prev), {}, {
            sceneElements: [].concat(_toConsumableArray((_prev$sceneElements4 = prev.sceneElements) !== null && _prev$sceneElements4 !== void 0 ? _prev$sceneElements4 : []), newEls)
          }) : prev;
        });
        return true;
      }
    }
    var placementName = function (_kindConfig$defaultPr, _kindConfig$defaultPr2) {
      if (isStage) return STAGE_DECO_DEFAULT.name;
      if (isImage) return locales.getText(I18N_PLACEMENT_FALLBACK_IMAGE);
      var db = dataBinding;
      var rid = recordIdsToPlace[0];
      if (db && rid) {
        var _dataSources$db$dataS, _row$name2;
        var row = dataSources === null || dataSources === void 0 || (_dataSources$db$dataS = dataSources[db.dataSourceKey]) === null || _dataSources$db$dataS === void 0 ? void 0 : _dataSources$db$dataS.find(function (r) {
          return r.id === rid;
        });
        return String((_row$name2 = row === null || row === void 0 ? void 0 : row.name) !== null && _row$name2 !== void 0 ? _row$name2 : rid);
      }
      return (_kindConfig$defaultPr = kindConfig === null || kindConfig === void 0 || (_kindConfig$defaultPr2 = kindConfig.defaultPresentation) === null || _kindConfig$defaultPr2 === void 0 ? void 0 : _kindConfig$defaultPr2.title) !== null && _kindConfig$defaultPr !== void 0 ? _kindConfig$defaultPr : '';
    }();
    var newEl = buildOneElement(dataBinding, contentX, contentY, placementName);
    setDraftConfig(function (prev) {
      var _prev$sceneElements5;
      return prev ? _objectSpread(_objectSpread({}, prev), {}, {
        sceneElements: [].concat(_toConsumableArray((_prev$sceneElements5 = prev.sceneElements) !== null && _prev$sceneElements5 !== void 0 ? _prev$sceneElements5 : []), [newEl])
      }) : prev;
    });
    return true;
  }, [config, currentCanvasId, dataSources]);
  var handleCanvasPlaceClick = useCallback(function (e) {
    if (!placeMode || placeMode.type !== 'scene' || !config || !currentCanvasId) return;
    var target = e.target;
    if (!target.classList.contains(placeOverlayClass)) return;
    var _contentOffsetRef$cur = contentOffsetRef.current,
      ox = _contentOffsetRef$cur.x,
      oy = _contentOffsetRef$cur.y;
    var contentX = Math.round(e.nativeEvent.offsetX - ox);
    var contentY = Math.round(e.nativeEvent.offsetY - oy);
    if (applyScenePlacementAtCoords(contentX, contentY, placeMode)) {
      setPlaceMode(null);
    }
  }, [placeMode, config, currentCanvasId, applyScenePlacementAtCoords, placeOverlayClass]);

  /** 从左侧图元栏拖拽到画布落位（与点击落点规则一致） */
  var placeSceneElementFromPaletteDrop = useCallback(function (contentX, contentY, scene) {
    if (applyScenePlacementAtCoords(contentX, contentY, scene)) {
      setPlaceMode(null);
    }
  }, [applyScenePlacementAtCoords]);
  var handleSave = useCallback(function () {
    if (!draftConfig || !onSave) return;
    setSaving(true);
    try {
      onSave(draftConfig);
      /** 先本地确认“已提交保存”，让提示即时消失；后续以 props 回写为准 */
      setSavedBaselineConfig(draftConfig);
    } finally {
      setSaving(false);
    }
  }, [draftConfig, onSave]);

  /** 切换当前画布草稿中的 mapLayer.showGrid（随布局保存持久化） */
  var toggleDraftCanvasShowGrid = useCallback(function () {
    setDraftConfig(function (prev) {
      if (!prev || !currentCanvasId) return prev;
      return _objectSpread(_objectSpread({}, prev), {}, {
        canvases: prev.canvases.map(function (c) {
          var _c$mapLayer;
          if (c.id !== currentCanvasId) return c;
          var nextShow = !Boolean((_c$mapLayer = c.mapLayer) === null || _c$mapLayer === void 0 ? void 0 : _c$mapLayer.showGrid);
          writeStoredGridVisible(currentCanvasId, nextShow);
          return _objectSpread(_objectSpread({}, c), {}, {
            mapLayer: _objectSpread(_objectSpread({}, c.mapLayer), {}, {
              showGrid: nextShow
            })
          });
        })
      });
    });
  }, [currentCanvasId]);
  var handleEditPanelUpdate = useCallback(function (patch) {
    if (!selectedId) return;
    var bindingPatch = patch.dataBinding;
    if (bindingPatch !== null && bindingPatch !== void 0 && bindingPatch.dataSourceKey && bindingPatch !== null && bindingPatch !== void 0 && bindingPatch.recordId) {
      var _configRef$current;
      var cand = bindingPatch;
      if (duplicateBinding((_configRef$current = configRef.current) === null || _configRef$current === void 0 ? void 0 : _configRef$current.sceneElements, cand, selectedId)) {
        message.warning('该数据记录已被其他图元绑定');
        return;
      }
    }
    updateDraftSceneElement(selectedId, patch);
  }, [selectedId, updateDraftSceneElement]);
  var handleSaveRecord = useCallback(function (dataSourceKey, id, newData) {
    onDataSourceRecordSave === null || onDataSourceRecordSave === void 0 || onDataSourceRecordSave(dataSourceKey, id, newData);
    setSavingRecord(true);
    setTimeout(function () {
      return setSavingRecord(false);
    }, 500);
  }, [onDataSourceRecordSave]);
  var handleEditPanelDelete = useCallback(function () {
    if (!selectedId) return;
    setDraftConfig(function (prev) {
      var _prev$sceneElements6;
      if (!prev) return prev;
      return _objectSpread(_objectSpread({}, prev), {}, {
        sceneElements: ((_prev$sceneElements6 = prev.sceneElements) !== null && _prev$sceneElements6 !== void 0 ? _prev$sceneElements6 : []).filter(function (e) {
          return e.instanceId !== selectedId;
        })
      });
    });
    setSelectedId(null);
  }, [selectedId]);

  /** 与编辑侧栏锁定按钮同源：切换 `layoutTransformLocked` */
  var toggleSelectedLayoutLock = useCallback(function () {
    var _configRef$current2;
    if (!selectedId) return;
    var el = (_configRef$current2 = configRef.current) === null || _configRef$current2 === void 0 || (_configRef$current2 = _configRef$current2.sceneElements) === null || _configRef$current2 === void 0 ? void 0 : _configRef$current2.find(function (e) {
      return e.instanceId === selectedId;
    });
    updateDraftSceneElement(selectedId, {
      layoutTransformLocked: !(el !== null && el !== void 0 && el.layoutTransformLocked)
    });
  }, [selectedId, updateDraftSceneElement]);

  /**
   * 复制选中图元：新实例 + 位移，**清除 dataBinding**（避免与侧栏一致的「同一记录不可重复绑定」冲突）。
   */
  var duplicateSelectedElement = useCallback(function () {
    var _prev$sceneElements7, _el$x, _el$y, _prev$sceneElements8;
    if (!selectedId) return;
    var prev = configRef.current;
    if (!prev) return;
    var el = ((_prev$sceneElements7 = prev.sceneElements) !== null && _prev$sceneElements7 !== void 0 ? _prev$sceneElements7 : []).find(function (e) {
      return e.instanceId === selectedId;
    });
    if (!el) return;
    var newId = newInstanceId();
    var copy = _objectSpread(_objectSpread({}, el), {}, {
      instanceId: newId,
      x: Math.round(((_el$x = el.x) !== null && _el$x !== void 0 ? _el$x : 0) + BATCH_PLACE_OFFSET),
      y: Math.round(((_el$y = el.y) !== null && _el$y !== void 0 ? _el$y : 0) + BATCH_PLACE_OFFSET),
      dataBinding: undefined,
      layoutTransformLocked: false
    });
    setDraftConfig(_objectSpread(_objectSpread({}, prev), {}, {
      sceneElements: [].concat(_toConsumableArray((_prev$sceneElements8 = prev.sceneElements) !== null && _prev$sceneElements8 !== void 0 ? _prev$sceneElements8 : []), [copy])
    }));
    setSelectedId(newId);
  }, [selectedId]);
  var selectedItem = selectedId ? mergedItems.find(function (m) {
    return m.id === selectedId;
  }) : null;

  /** 布局锁定中的图元仍可选中，但不展开右侧编辑面板（解锁后再展） */
  var editPanelParams = selectedItem && config && selectedId && !((_selectedItem$_sceneE = selectedItem._sceneElement) !== null && _selectedItem$_sceneE !== void 0 && _selectedItem$_sceneE.layoutTransformLocked) ? {
    itemId: selectedId,
    sceneElement: selectedItem._sceneElement,
    onUpdate: handleEditPanelUpdate,
    onSaveRecord: onDataSourceRecordSave ? handleSaveRecord : undefined,
    onClose: function onClose() {
      return setSelectedId(null);
    },
    onDelete: config.canvasUi.canEdit ? handleEditPanelDelete : undefined,
    recordFormColumns: dataSourceFormColumns,
    dataSourceRecordForm: dataSourceRecordForm,
    dataSourceLabels: dataSourceLabels,
    layoutDraftDirty: isLayoutDirty,
    showDataSourceRecordFormBlock: showDataSourceRecordFormBlock
  } : null;
  return {
    config: config,
    currentCanvasId: currentCanvasId,
    setCurrentCanvasId: setCurrentCanvasId,
    selectedId: selectedId,
    setSelectedId: setSelectedId,
    placeMode: placeMode,
    setPlaceMode: setPlaceMode,
    mergedItems: mergedItems,
    items: items,
    saving: saving,
    savingRecord: savingRecord,
    handleAddCanvas: handleAddCanvas,
    handleRemoveCanvas: handleRemoveCanvas,
    handleRenameCanvas: handleRenameCanvas,
    handleUpdateItem: handleUpdateItem,
    handleCanvasPlaceClick: handleCanvasPlaceClick,
    handleSave: handleSave,
    placeSceneElementFromPaletteDrop: placeSceneElementFromPaletteDrop,
    editPanelParams: editPanelParams,
    placeOverlayClass: placeOverlayClass,
    isLayoutDirty: isLayoutDirty,
    toggleDraftCanvasShowGrid: toggleDraftCanvasShowGrid,
    toggleSelectedLayoutLock: toggleSelectedLayoutLock,
    duplicateSelectedElement: duplicateSelectedElement,
    deleteSelectedElement: handleEditPanelDelete
  };
}