import { FLOOR_MAP_STAGE_ELEMENT_KIND } from "../types.js";
import { FLOOR_MAP_BUILTIN_SHAPES, getFloorMapBuiltinShapeDef } from "../utils/floorMapBuiltinShapes.js";
import { FLOOR_MAP_RESOURCE_PLACE_DEFAULT, getElementKindConfig, getSwappableElementKindsInSameCategory, isFloorMapBuiltinShapeElementKind, isFloorMapImageElementKind, patchSceneElementForKindSwitch, resolveDataBindingPolicy } from "../utils/floorMapElementKindUtils.js";
import { FLOOR_MAP_CONFIRM_OVERLAY_Z_INDEX } from "../floorMapLayoutConstants.js";
import useEngineContext from "../../../hooks/useEngineContext.js";
import { getFloorMapCanvasDisplayName, getFloorMapDisplayLocale, initFloorMapLayoutLocales } from "../utils/floorMapCanvasDisplay.js";
import { buildNameAsTitleExtensionsPatch, isElementNameAsTitleEnabled } from "../utils/floorMapElementNameAsTitle.js";
import FloorMapDataForm from "./FloorMapDataForm.js";
import { formatDataRecordOptionLabel } from "../utils/floorMapDataRecordLabel.js";
import React, { useCallback, useMemo, useRef, useState } from "react";
import { locales } from "@pisell/utils";
import { Button, Checkbox, Form, Input, InputNumber, Popconfirm, Select, message } from "antd";
import { CloseOutlined, LockOutlined, UnlockOutlined } from "@ant-design/icons";
import classNames from "classnames";
import "./FloorMapEditPanel.less";
//#region src/components/pisellFloorMapLayout/components/FloorMapEditPanel.tsx
/**
* FloorMapEditPanel - 选中图元后的编辑面板：画布属性 + 可选数据绑定 + 数据源记录表单
*/
const PREFIX = "pisell-floor-map-layout";
const I18N_EP = "pisell-floor-map-layout.edit-panel";
function resolveDataSourceRecordForm(content, ctx) {
	if (typeof content === "function") return content(ctx);
	return content;
}
function FloorMapEditPanel(props) {
	var _kindConfig$allowedDa, _dataSources$binding$, _dataSources$binding$2, _dataSources$binding$3;
	const { sceneElement, itemId, onUpdate, onSaveRecord, onClose, onDelete, recordFormColumns, dataSourceRecordForm, config, dataSources, savingRecord, dataSourceLabels = {}, layoutDraftDirty, showDataSourceRecordFormBlock: showRecordFormProp, className } = props;
	const [form] = Form.useForm();
	/** 忽略由 setFieldsValue 触发的 onValuesChange，避免误判「未应用」 */
	const skipFormValuesChangeRef = useRef(false);
	const [formHasUnappliedChanges, setFormHasUnappliedChanges] = useState(false);
	const engineLocale = getFloorMapDisplayLocale(useEngineContext());
	initFloorMapLayoutLocales(engineLocale);
	const ep = useMemo(() => ({
		elementProps: locales.getText(`${I18N_EP}.element-props`),
		closeAria: locales.getText(`${I18N_EP}.close-aria`),
		hintApply: locales.getText(`${I18N_EP}.hint-apply`),
		hintSave: locales.getText(`${I18N_EP}.hint-save`),
		sectionLayout: locales.getText(`${I18N_EP}.section-layout`),
		lockOn: locales.getText(`${I18N_EP}.lock-on`),
		lockOff: locales.getText(`${I18N_EP}.lock-off`),
		labelX: locales.getText(`${I18N_EP}.label-x`),
		labelY: locales.getText(`${I18N_EP}.label-y`),
		labelZ: locales.getText(`${I18N_EP}.label-z`),
		labelWidth: locales.getText(`${I18N_EP}.label-width`),
		labelHeight: locales.getText(`${I18N_EP}.label-height`),
		labelName: locales.getText(`${I18N_EP}.label-name`),
		labelNameStage: locales.getText(`${I18N_EP}.label-name-stage`),
		phNameStage: locales.getText(`${I18N_EP}.ph-name-stage`),
		phName: locales.getText(`${I18N_EP}.ph-name`),
		labelNameAsTitle: locales.getText(`${I18N_EP}.label-name-as-title`),
		tipNameAsTitle: locales.getText(`${I18N_EP}.tip-name-as-title`),
		labelImageUrl: locales.getText(`${I18N_EP}.label-image-url`),
		extraImageUrl: locales.getText(`${I18N_EP}.extra-image-url`),
		phHttps: locales.getText(`${I18N_EP}.ph-https`),
		labelBuiltinShape: locales.getText(`${I18N_EP}.label-builtin-shape`),
		extraBuiltinShape: locales.getText(`${I18N_EP}.extra-builtin-shape`),
		phBuiltinShape: locales.getText(`${I18N_EP}.ph-builtin-shape`),
		labelCanvas: locales.getText(`${I18N_EP}.label-canvas`),
		apply: locales.getText(`${I18N_EP}.apply`),
		dataBinding: locales.getText(`${I18N_EP}.data-binding`),
		dataBindingNote: locales.getText(`${I18N_EP}.data-binding-note`),
		labelDataSource: locales.getText(`${I18N_EP}.label-data-source`),
		phDataSource: locales.getText(`${I18N_EP}.ph-data-source`),
		labelPickRow: locales.getText(`${I18N_EP}.label-pick-row`),
		phPickRow: locales.getText(`${I18N_EP}.ph-pick-row`),
		phNoRows: locales.getText(`${I18N_EP}.ph-no-rows`),
		hintUnbound: locales.getText(`${I18N_EP}.hint-unbound`),
		recordTitle: locales.getText(`${I18N_EP}.record-title`),
		popTitle: locales.getText(`${I18N_EP}.pop-title`),
		popDesc: locales.getText(`${I18N_EP}.pop-desc`),
		btnDelete: locales.getText(`${I18N_EP}.btn-delete`),
		btnCancel: locales.getText(`${I18N_EP}.btn-cancel`),
		btnOkDelete: locales.getText(`${I18N_EP}.btn-ok-delete`),
		labelElementKind: locales.getText(`${I18N_EP}.label-element-kind`),
		hintKindBindingCleared: locales.getText(`${I18N_EP}.hint-kind-binding-cleared`)
	}), [engineLocale]);
	const swappableKinds = useMemo(() => getSwappableElementKindsInSameCategory(config, sceneElement.elementKind), [config, sceneElement.elementKind]);
	const handleElementKindChange = useCallback((nextKind) => {
		if (nextKind === sceneElement.elementKind) return;
		const hadBinding = Boolean(sceneElement.dataBinding);
		const patch = patchSceneElementForKindSwitch(config, sceneElement, nextKind);
		if (hadBinding && patch.dataBinding === void 0) message.info(ep.hintKindBindingCleared);
		onUpdate(patch);
	}, [
		config,
		sceneElement,
		onUpdate,
		ep.hintKindBindingCleared
	]);
	const canvasOptions = config.canvases.filter((c) => c.enabled).sort((a, b) => a.order - b.order);
	const kindConfig = getElementKindConfig(config, sceneElement.elementKind);
	const bindingPolicy = resolveDataBindingPolicy(kindConfig);
	/**
	* 是否在编辑面板渲染「将图元名作为资源标题」勾选项，由 kindConfig 显式声明；
	* 未声明的 kind（含将来新增）保持现状不出现该项。
	*/
	const kindAllowsNameAsTitle = Boolean(kindConfig === null || kindConfig === void 0 ? void 0 : kindConfig.nameAsTitleConfigurable);
	const allKeys = Object.keys(dataSources);
	const allowedKeys = (kindConfig === null || kindConfig === void 0 || (_kindConfig$allowedDa = kindConfig.allowedDataSourceKeys) === null || _kindConfig$allowedDa === void 0 ? void 0 : _kindConfig$allowedDa.length) ? kindConfig.allowedDataSourceKeys.filter((k) => allKeys.includes(k)) : allKeys;
	/** 与 RecordBoard Story 图片图元一致：`floorMapImage` */
	const isImageKind = isFloorMapImageElementKind(sceneElement.elementKind);
	/** 内置图形图元：用 builtinShapeKey 选择厕所 / 沙发 / 大门 等预设 SVG */
	const isBuiltinShapeKind = isFloorMapBuiltinShapeElementKind(sceneElement.elementKind);
	const layoutLocked = Boolean(sceneElement.layoutTransformLocked);
	const initialValues = React.useMemo(() => {
		var _builtinDef$defaultSi, _builtinDef$defaultSi2, _sceneElement$name, _sceneElement$zIndex, _sceneElement$width, _sceneElement$height, _sceneElement$imageUr, _sceneElement$builtin;
		/** 内置图形宽高优先采用当前选定预设的 defaultSize，未选则给一个保底正方形 */
		const builtinDef = isBuiltinShapeKind ? getFloorMapBuiltinShapeDef(sceneElement.builtinShapeKey) : void 0;
		const bindingPolicy = resolveDataBindingPolicy(kindConfig);
		const dw = isImageKind ? 400 : isBuiltinShapeKind ? (_builtinDef$defaultSi = builtinDef === null || builtinDef === void 0 ? void 0 : builtinDef.defaultSize.width) !== null && _builtinDef$defaultSi !== void 0 ? _builtinDef$defaultSi : 96 : bindingPolicy !== "none" ? FLOOR_MAP_RESOURCE_PLACE_DEFAULT.width : 48;
		const dh = isImageKind ? 240 : isBuiltinShapeKind ? (_builtinDef$defaultSi2 = builtinDef === null || builtinDef === void 0 ? void 0 : builtinDef.defaultSize.height) !== null && _builtinDef$defaultSi2 !== void 0 ? _builtinDef$defaultSi2 : 96 : bindingPolicy !== "none" ? FLOOR_MAP_RESOURCE_PLACE_DEFAULT.height : 48;
		return {
			x: sceneElement.x,
			y: sceneElement.y,
			name: (_sceneElement$name = sceneElement.name) !== null && _sceneElement$name !== void 0 ? _sceneElement$name : "",
			zIndex: (_sceneElement$zIndex = sceneElement.zIndex) !== null && _sceneElement$zIndex !== void 0 ? _sceneElement$zIndex : 0,
			width: (_sceneElement$width = sceneElement.width) !== null && _sceneElement$width !== void 0 ? _sceneElement$width : dw,
			height: (_sceneElement$height = sceneElement.height) !== null && _sceneElement$height !== void 0 ? _sceneElement$height : dh,
			canvasId: sceneElement.canvasId,
			imageUrl: (_sceneElement$imageUr = sceneElement.imageUrl) !== null && _sceneElement$imageUr !== void 0 ? _sceneElement$imageUr : "",
			builtinShapeKey: (_sceneElement$builtin = sceneElement.builtinShapeKey) !== null && _sceneElement$builtin !== void 0 ? _sceneElement$builtin : void 0,
			nameAsTitle: isElementNameAsTitleEnabled(sceneElement)
		};
	}, [
		sceneElement,
		isImageKind,
		isBuiltinShapeKind
	]);
	React.useEffect(() => {
		setFormHasUnappliedChanges(false);
	}, [itemId]);
	React.useEffect(() => {
		skipFormValuesChangeRef.current = true;
		form.setFieldsValue(initialValues);
		queueMicrotask(() => {
			skipFormValuesChangeRef.current = false;
			setFormHasUnappliedChanges(false);
		});
	}, [
		itemId,
		initialValues,
		form
	]);
	const handleFinish = useCallback((values) => {
		const name = values.name != null ? String(values.name).trim() || void 0 : void 0;
		const patch = {
			name,
			canvasId: String(values.canvasId)
		};
		if (isImageKind) {
			var _values$imageUrl;
			patch.imageUrl = String((_values$imageUrl = values.imageUrl) !== null && _values$imageUrl !== void 0 ? _values$imageUrl : "").trim() || void 0;
		}
		if (isBuiltinShapeKind) {
			const raw = values.builtinShapeKey;
			patch.builtinShapeKey = (raw != null ? String(raw).trim() : "") || void 0;
		}
		if (!layoutLocked) {
			patch.x = Number(values.x);
			patch.y = Number(values.y);
			patch.zIndex = values.zIndex != null ? Number(values.zIndex) : void 0;
			const w = Number(values.width);
			const h = Number(values.height);
			patch.width = Number.isFinite(w) ? Math.max(20, w) : void 0;
			patch.height = Number.isFinite(h) ? Math.max(20, h) : void 0;
		}
		/**
		* 「图元名作为资源标题」开关：仅在 kindConfig 允许配置时才会出现在表单里；
		* 没有 name 的场景下即便勾选也无意义，因此用 `name` 是否为空决定写入是 true 还是清掉。
		* 写入路径走 extensions，避免顶层 schema 出现仅供 UI 偏好的字段。
		*/
		if (kindAllowsNameAsTitle) {
			const enabled = Boolean(values.nameAsTitle) && Boolean(name);
			patch.extensions = buildNameAsTitleExtensionsPatch(sceneElement.extensions, enabled);
		}
		onUpdate(patch);
		setFormHasUnappliedChanges(false);
	}, [
		onUpdate,
		isImageKind,
		isBuiltinShapeKind,
		layoutLocked,
		kindAllowsNameAsTitle,
		sceneElement.extensions
	]);
	const binding = sceneElement.dataBinding;
	const record = binding ? (_dataSources$binding$ = (_dataSources$binding$2 = dataSources[binding.dataSourceKey]) === null || _dataSources$binding$2 === void 0 ? void 0 : _dataSources$binding$2.find((r) => r.id === binding.recordId)) !== null && _dataSources$binding$ !== void 0 ? _dataSources$binding$ : {} : {};
	const dataRecordBindOptions = useMemo(() => {
		var _binding$dataSourceKe, _dataSources$key, _config$sceneElements;
		if (bindingPolicy === "none") return [];
		const key = (_binding$dataSourceKe = binding === null || binding === void 0 ? void 0 : binding.dataSourceKey) !== null && _binding$dataSourceKe !== void 0 ? _binding$dataSourceKe : allowedKeys[0];
		if (!key) return [];
		const list = (_dataSources$key = dataSources[key]) !== null && _dataSources$key !== void 0 ? _dataSources$key : [];
		if (!list.length) return [];
		const usedByOther = new Set(((_config$sceneElements = config.sceneElements) !== null && _config$sceneElements !== void 0 ? _config$sceneElements : []).filter((e) => {
			var _e$dataBinding;
			return e.instanceId !== sceneElement.instanceId && ((_e$dataBinding = e.dataBinding) === null || _e$dataBinding === void 0 ? void 0 : _e$dataBinding.dataSourceKey) === key;
		}).map((e) => e.dataBinding.recordId));
		return list.filter((r) => !usedByOther.has(r.id) || r.id === (binding === null || binding === void 0 ? void 0 : binding.recordId)).map((r) => ({
			value: r.id,
			label: formatDataRecordOptionLabel(r)
		}));
	}, [
		bindingPolicy,
		binding,
		allowedKeys,
		dataSources,
		config.sceneElements,
		sceneElement.instanceId
	]);
	const hasBoundDataRecord = Boolean(binding && ((_dataSources$binding$3 = dataSources[binding.dataSourceKey]) !== null && _dataSources$binding$3 !== void 0 ? _dataSources$binding$3 : []).some((r) => r.id === binding.recordId));
	const recordFormSlotRaw = binding ? dataSourceRecordForm === null || dataSourceRecordForm === void 0 ? void 0 : dataSourceRecordForm[binding.dataSourceKey] : void 0;
	const hasCustomRecordForm = recordFormSlotRaw !== void 0 && recordFormSlotRaw !== null && recordFormSlotRaw !== false;
	const showDataBindingSection = bindingPolicy !== "none";
	const showDataRecordEditorSection = showRecordFormProp !== false && hasBoundDataRecord && Boolean(binding) && (onSaveRecord != null || hasCustomRecordForm) && Boolean(binding);
	const recordFormContext = useMemo(() => {
		if (!binding) return null;
		return {
			dataSourceKey: binding.dataSourceKey,
			recordId: binding.recordId,
			record,
			dataSources,
			sceneElement,
			config,
			savingRecord: savingRecord !== null && savingRecord !== void 0 ? savingRecord : false,
			onSaveRecord: onSaveRecord ? (newData) => onSaveRecord(binding.dataSourceKey, binding.recordId, newData) : void 0
		};
	}, [
		binding,
		record,
		dataSources,
		sceneElement,
		config,
		savingRecord,
		onSaveRecord
	]);
	const isStageLike = sceneElement.elementKind === FLOOR_MAP_STAGE_ELEMENT_KIND;
	const toggleLayoutLock = () => {
		onUpdate({ layoutTransformLocked: !sceneElement.layoutTransformLocked });
	};
	const panelScrollRef = useRef(null);
	const getSelectPopupContainer = useCallback((node) => {
		var _ref, _node$parentElement;
		return (_ref = (_node$parentElement = node.parentElement) !== null && _node$parentElement !== void 0 ? _node$parentElement : panelScrollRef.current) !== null && _ref !== void 0 ? _ref : document.body;
	}, []);
	const dragScrollRef = useRef({
		active: false,
		pointerId: -1,
		startY: 0,
		startScrollTop: 0
	});
	const isDragScrollSurface = useCallback((target) => {
		if (!(target instanceof Element)) return false;
		/**
		* 侧栏「按住空白拖动滚动」：仅在 scrollHeight > clientHeight 时对 pointerdown 调用 setPointerCapture。
		*
		* 为何常见「桌面点不进 Select 选项、iPad/触控模拟却可以」：
		* - 无绑定的图元会多出「数据源 + 选数据行」两块，侧栏更易纵向溢出 → 桌面宽屏下右侧栏 maxHeight
		*   往往更紧，容易触发可滚动 + 捕获；平板/模拟器视口更高或布局不同，有时内容不溢出则根本不会捕获。
		* - 即便都可滚动：点在选项上时，Ant Design 的下拉层在 DOM 上多为 .ant-select-dropdown，与触发器 .ant-select
		*   兄弟挂载，closest('.ant-select') 命中不了选项节点 → 被当成「空白滚动面」误捕获，表现为下拉展开但点击无响应。
		*/
		return !target.closest("input,textarea,button,select,.ant-select,.ant-select-dropdown,.pisell-lowcode-select-dropdown,.rc-select-dropdown,.ant-input,[contenteditable=\"true\"]");
	}, []);
	const handlePanelPointerDown = useCallback((e) => {
		if (!isDragScrollSurface(e.target)) return;
		const el = panelScrollRef.current;
		if (!el || el.scrollHeight <= el.clientHeight) return;
		el.setPointerCapture(e.pointerId);
		dragScrollRef.current = {
			active: true,
			pointerId: e.pointerId,
			startY: e.clientY,
			startScrollTop: el.scrollTop
		};
	}, [isDragScrollSurface]);
	const handlePanelPointerMove = useCallback((e) => {
		const d = dragScrollRef.current;
		if (!d.active || e.pointerId !== d.pointerId) return;
		const el = panelScrollRef.current;
		if (!el) return;
		el.scrollTop = d.startScrollTop + (d.startY - e.clientY);
	}, []);
	const endPanelDragScroll = useCallback((e) => {
		const d = dragScrollRef.current;
		if (!d.active || e.pointerId !== d.pointerId) return;
		dragScrollRef.current = {
			active: false,
			pointerId: -1,
			startY: 0,
			startScrollTop: 0
		};
		try {
			var _panelScrollRef$curre;
			(_panelScrollRef$curre = panelScrollRef.current) === null || _panelScrollRef$curre === void 0 || _panelScrollRef$curre.releasePointerCapture(e.pointerId);
		} catch (_unused) {}
	}, []);
	return /* @__PURE__ */ React.createElement("div", {
		ref: panelScrollRef,
		className: classNames(`${PREFIX}-edit-panel`, className),
		onPointerDown: handlePanelPointerDown,
		onPointerMove: handlePanelPointerMove,
		onPointerUp: endPanelDragScroll,
		onPointerCancel: endPanelDragScroll
	}, /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-header` }, /* @__PURE__ */ React.createElement("span", { className: `${PREFIX}-edit-panel-header-title` }, ep.elementProps), /* @__PURE__ */ React.createElement(Button, {
		type: "text",
		size: "large",
		className: `${PREFIX}-edit-panel-close`,
		icon: /* @__PURE__ */ React.createElement(CloseOutlined, null),
		"aria-label": ep.closeAria,
		onClick: onClose
	})), (formHasUnappliedChanges || layoutDraftDirty) && /* @__PURE__ */ React.createElement("div", {
		className: `${PREFIX}-edit-panel-hints`,
		role: "status"
	}, formHasUnappliedChanges ? /* @__PURE__ */ React.createElement("p", { className: `${PREFIX}-edit-panel-hint warn` }, ep.hintApply) : null, layoutDraftDirty ? /* @__PURE__ */ React.createElement("p", { className: `${PREFIX}-edit-panel-hint muted` }, ep.hintSave) : null), swappableKinds.length > 1 ? /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-kind-row` }, /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-record-bind-label` }, ep.labelElementKind), /* @__PURE__ */ React.createElement(Select, {
		size: "large",
		value: sceneElement.elementKind,
		options: swappableKinds.map((k) => ({
			value: k.value,
			label: k.label
		})),
		onChange: handleElementKindChange,
		getPopupContainer: getSelectPopupContainer,
		style: {
			width: "100%",
			marginBottom: 12
		}
	})) : null, /* @__PURE__ */ React.createElement(Form, {
		form,
		layout: "vertical",
		size: "large",
		onFinish: handleFinish,
		initialValues,
		onValuesChange: () => {
			if (skipFormValuesChangeRef.current) return;
			setFormHasUnappliedChanges(true);
		}
	}, /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-layout-lock-header` }, /* @__PURE__ */ React.createElement("span", { className: `${PREFIX}-edit-panel-layout-lock-title` }, ep.sectionLayout), /* @__PURE__ */ React.createElement(Button, {
		type: "text",
		size: "large",
		className: `${PREFIX}-edit-panel-layout-lock-btn`,
		icon: layoutLocked ? /* @__PURE__ */ React.createElement(LockOutlined, null) : /* @__PURE__ */ React.createElement(UnlockOutlined, null),
		"aria-pressed": layoutLocked,
		onClick: toggleLayoutLock,
		title: layoutLocked ? ep.lockOn : ep.lockOff
	})), /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-xy-row` }, /* @__PURE__ */ React.createElement(Form.Item, {
		name: "x",
		label: ep.labelX
	}, /* @__PURE__ */ React.createElement(InputNumber, {
		style: { width: "100%" },
		disabled: layoutLocked
	})), /* @__PURE__ */ React.createElement(Form.Item, {
		name: "y",
		label: ep.labelY
	}, /* @__PURE__ */ React.createElement(InputNumber, {
		style: { width: "100%" },
		disabled: layoutLocked
	})), /* @__PURE__ */ React.createElement(Form.Item, {
		name: "zIndex",
		label: ep.labelZ
	}, /* @__PURE__ */ React.createElement(InputNumber, {
		style: { width: "100%" },
		disabled: layoutLocked
	}))), /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-size-row` }, /* @__PURE__ */ React.createElement(Form.Item, {
		name: "width",
		label: ep.labelWidth
	}, /* @__PURE__ */ React.createElement(InputNumber, {
		style: { width: "100%" },
		min: 20,
		disabled: layoutLocked
	})), /* @__PURE__ */ React.createElement(Form.Item, {
		name: "height",
		label: ep.labelHeight
	}, /* @__PURE__ */ React.createElement(InputNumber, {
		style: { width: "100%" },
		min: 20,
		disabled: layoutLocked
	}))), /* @__PURE__ */ React.createElement(Form.Item, {
		name: "name",
		label: isStageLike ? ep.labelNameStage : ep.labelName
	}, /* @__PURE__ */ React.createElement(Input, {
		placeholder: isStageLike ? ep.phNameStage : ep.phName,
		allowClear: true
	})), kindAllowsNameAsTitle ? /* @__PURE__ */ React.createElement(
		Form.Item,
		/**
		* 仅在 kindConfig.nameAsTitleConfigurable 时渲染。
		* 业务侧通过 {@link resolveSceneElementDisplayTitle} 读取该偏好，
		* 决定卡片标题是否覆盖业务字段（如 row.main_field / row.code）。
		*/
		{
			name: "nameAsTitle",
			valuePropName: "checked",
			extra: ep.tipNameAsTitle,
			style: { marginTop: -4 }
		},
		/* @__PURE__ */ React.createElement(Checkbox, null, ep.labelNameAsTitle)
	) : null, isImageKind ? /* @__PURE__ */ React.createElement(Form.Item, {
		name: "imageUrl",
		label: ep.labelImageUrl,
		extra: ep.extraImageUrl
	}, /* @__PURE__ */ React.createElement(Input, {
		allowClear: true,
		placeholder: ep.phHttps
	})) : null, isBuiltinShapeKind ? /* @__PURE__ */ React.createElement(
		Form.Item,
		/**
		* 内置图形选择：与图片图元的 imageUrl 字段对位，但把 URL 输入换成 Select；
		* 选项由 {@link FLOOR_MAP_BUILTIN_SHAPES} 驱动（厕所 / 分隔 / 柱子 / 沙发 / 大门 等）。
		* 用 i18n key 取展示名，跟随引擎语言切换。
		*/
		{
			name: "builtinShapeKey",
			label: ep.labelBuiltinShape,
			extra: ep.extraBuiltinShape
		},
		/* @__PURE__ */ React.createElement(Select, {
			allowClear: true,
			placeholder: ep.phBuiltinShape,
			getPopupContainer: getSelectPopupContainer,
			options: FLOOR_MAP_BUILTIN_SHAPES.map((s) => ({
				value: s.key,
				label: locales.getText(s.labelKey)
			}))
		})
	) : null, /* @__PURE__ */ React.createElement(Form.Item, {
		name: "canvasId",
		label: ep.labelCanvas
	}, /* @__PURE__ */ React.createElement(Select, {
		options: canvasOptions.map((c) => ({
			value: c.id,
			label: getFloorMapCanvasDisplayName(c, engineLocale)
		})),
		allowClear: false,
		getPopupContainer: getSelectPopupContainer
	})), /* @__PURE__ */ React.createElement(Form.Item, null, /* @__PURE__ */ React.createElement(Button, {
		type: "primary",
		htmlType: "submit",
		size: "large"
	}, ep.apply))), showDataBindingSection && /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-record` }, /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-record-title` }, ep.dataBinding), /* @__PURE__ */ React.createElement("p", { className: `${PREFIX}-edit-panel-record-draft-note` }, ep.dataBindingNote), allowedKeys.length >= 1 ? /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-record-bind` }, /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-record-bind-label` }, ep.labelDataSource), /* @__PURE__ */ React.createElement(Select, {
		size: "large",
		style: { width: "100%" },
		placeholder: ep.phDataSource,
		value: binding === null || binding === void 0 ? void 0 : binding.dataSourceKey,
		options: allowedKeys.map((k) => {
			var _dataSourceLabels$k;
			return {
				value: k,
				label: (_dataSourceLabels$k = dataSourceLabels[k]) !== null && _dataSourceLabels$k !== void 0 ? _dataSourceLabels$k : k
			};
		}),
		onChange: (key) => {
			if (!key && bindingPolicy === "optional") {
				onUpdate({ dataBinding: void 0 });
				return;
			}
			if (!key) return;
			onUpdate({ dataBinding: {
				dataSourceKey: key,
				recordId: (binding === null || binding === void 0 ? void 0 : binding.dataSourceKey) === key ? binding.recordId : ""
			} });
		},
		allowClear: bindingPolicy === "optional",
		getPopupContainer: getSelectPopupContainer
	})) : null, allowedKeys.length >= 1 && /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-record-bind` }, /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-record-bind-label` }, ep.labelPickRow), /* @__PURE__ */ React.createElement(Select, {
		size: "large",
		placeholder: dataRecordBindOptions.length ? ep.phPickRow : ep.phNoRows,
		style: { width: "100%" },
		value: hasBoundDataRecord ? binding === null || binding === void 0 ? void 0 : binding.recordId : void 0,
		allowClear: bindingPolicy === "optional",
		options: dataRecordBindOptions,
		getPopupContainer: getSelectPopupContainer,
		onChange: (newId) => {
			var _binding$dataSourceKe2, _dataSources$key2;
			const key = (_binding$dataSourceKe2 = binding === null || binding === void 0 ? void 0 : binding.dataSourceKey) !== null && _binding$dataSourceKe2 !== void 0 ? _binding$dataSourceKe2 : allowedKeys[0];
			if (!key) return;
			if (!newId) {
				onUpdate({ dataBinding: void 0 });
				return;
			}
			const row = ((_dataSources$key2 = dataSources[key]) !== null && _dataSources$key2 !== void 0 ? _dataSources$key2 : []).find((r) => r.id === newId);
			onUpdate({
				dataBinding: {
					dataSourceKey: key,
					recordId: newId
				},
				name: row ? String((() => {
					var _ref2, _name;
					const m = row.main_field;
					if (m != null && String(m).trim() !== "") {
						var _String$split$0$trim, _String$split$;
						return (_String$split$0$trim = (_String$split$ = String(m).split(" ## ")[0]) === null || _String$split$ === void 0 ? void 0 : _String$split$.trim()) !== null && _String$split$0$trim !== void 0 ? _String$split$0$trim : newId;
					}
					return (_ref2 = (_name = row.name) !== null && _name !== void 0 ? _name : row.code) !== null && _ref2 !== void 0 ? _ref2 : newId;
				})()) : void 0
			});
		}
	}), !hasBoundDataRecord && /* @__PURE__ */ React.createElement("p", { className: `${PREFIX}-edit-panel-record-bind-hint` }, ep.hintUnbound))), showDataRecordEditorSection && binding && /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-record` }, /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-record-title` }, ep.recordTitle), hasCustomRecordForm && recordFormContext && recordFormSlotRaw != null ? /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-record-custom` }, resolveDataSourceRecordForm(recordFormSlotRaw, recordFormContext)) : null, !hasCustomRecordForm && onSaveRecord ? /* @__PURE__ */ React.createElement(FloorMapDataForm, {
		dataSourceKey: binding.dataSourceKey,
		recordId: binding.recordId,
		record,
		dataSources,
		onSave: onSaveRecord,
		saving: savingRecord,
		columns: recordFormColumns === null || recordFormColumns === void 0 ? void 0 : recordFormColumns[binding.dataSourceKey]
	}) : null), config.canvasUi.canEdit && onDelete ? /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-edit-panel-footer` }, /* @__PURE__ */ React.createElement(Popconfirm, {
		title: ep.popTitle,
		description: ep.popDesc,
		onConfirm: onDelete,
		okText: ep.btnOkDelete,
		cancelText: ep.btnCancel,
		okButtonProps: { danger: true },
		zIndex: FLOOR_MAP_CONFIRM_OVERLAY_Z_INDEX
	}, /* @__PURE__ */ React.createElement(Button, {
		type: "default",
		danger: true,
		block: true,
		size: "large"
	}, ep.btnDelete))) : null);
}
//#endregion
export { FloorMapEditPanel as default };
