@xbeeant/form-engine-designer 0.0.3 → 0.0.4

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.
Files changed (131) hide show
  1. package/dist/es/Canvas.js +42 -47
  2. package/dist/es/Canvas.js.map +1 -1
  3. package/dist/es/Designer.js +121 -98
  4. package/dist/es/Designer.js.map +1 -1
  5. package/dist/es/DesignerContext.js +86 -73
  6. package/dist/es/DesignerContext.js.map +1 -1
  7. package/dist/es/Palette.js +3 -3
  8. package/dist/es/Palette.js.map +1 -1
  9. package/dist/es/PropertyPanel.js +99 -100
  10. package/dist/es/PropertyPanel.js.map +1 -1
  11. package/dist/es/catalog.js +17 -10
  12. package/dist/es/catalog.js.map +1 -1
  13. package/dist/es/designer-context.js +110 -0
  14. package/dist/es/designer-context.js.map +1 -0
  15. package/dist/es/history.js +73 -0
  16. package/dist/es/history.js.map +1 -0
  17. package/dist/es/index.css +1 -1
  18. package/dist/es/index.js +3 -3
  19. package/dist/es/property/basic-property.js +6 -0
  20. package/dist/es/property/basic-property.js.map +1 -1
  21. package/dist/es/property-panel.js +294 -0
  22. package/dist/es/property-panel.js.map +1 -0
  23. package/dist/es/resizable-panel.js +103 -0
  24. package/dist/es/resizable-panel.js.map +1 -0
  25. package/dist/es/schema-utils.js +286 -0
  26. package/dist/es/schema-utils.js.map +1 -0
  27. package/dist/es/widgets/BindEditor.js +60 -49
  28. package/dist/es/widgets/BindEditor.js.map +1 -1
  29. package/dist/es/widgets/CodeEditor.js +41 -49
  30. package/dist/es/widgets/CodeEditor.js.map +1 -1
  31. package/dist/es/widgets/DefaultEditor.js +25 -30
  32. package/dist/es/widgets/DefaultEditor.js.map +1 -1
  33. package/dist/es/widgets/DependenciesEditor.js +21 -21
  34. package/dist/es/widgets/DependenciesEditor.js.map +1 -1
  35. package/dist/es/widgets/EnumEditor.js +25 -31
  36. package/dist/es/widgets/EnumEditor.js.map +1 -1
  37. package/dist/es/widgets/ExpressionSwitch.js +32 -30
  38. package/dist/es/widgets/ExpressionSwitch.js.map +1 -1
  39. package/dist/es/widgets/ReactionsEditor.js +103 -103
  40. package/dist/es/widgets/ReactionsEditor.js.map +1 -1
  41. package/dist/es/widgets/RemoteDataEditor.js +63 -63
  42. package/dist/es/widgets/RemoteDataEditor.js.map +1 -1
  43. package/dist/es/widgets/ValidateEditor.js +49 -49
  44. package/dist/es/widgets/ValidateEditor.js.map +1 -1
  45. package/dist/es/widgets/bind-editor.js +78 -0
  46. package/dist/es/widgets/bind-editor.js.map +1 -0
  47. package/dist/es/widgets/code-editor.js +76 -0
  48. package/dist/es/widgets/code-editor.js.map +1 -0
  49. package/dist/es/widgets/default-editor.js +50 -0
  50. package/dist/es/widgets/default-editor.js.map +1 -0
  51. package/dist/es/widgets/dependencies-editor.js +36 -0
  52. package/dist/es/widgets/dependencies-editor.js.map +1 -0
  53. package/dist/es/widgets/enum-editor.js +43 -0
  54. package/dist/es/widgets/enum-editor.js.map +1 -0
  55. package/dist/es/widgets/expression-builder.js +367 -0
  56. package/dist/es/widgets/expression-builder.js.map +1 -0
  57. package/dist/es/widgets/expression-model.js +340 -0
  58. package/dist/es/widgets/expression-model.js.map +1 -0
  59. package/dist/es/widgets/expression-switch.js +49 -0
  60. package/dist/es/widgets/expression-switch.js.map +1 -0
  61. package/dist/es/widgets/index.js +13 -13
  62. package/dist/es/widgets/index.js.map +1 -1
  63. package/dist/es/widgets/options-editor.js +102 -0
  64. package/dist/es/widgets/options-editor.js.map +1 -0
  65. package/dist/es/widgets/reactions-editor.js +401 -0
  66. package/dist/es/widgets/reactions-editor.js.map +1 -0
  67. package/dist/es/widgets/reactions-model.js +107 -0
  68. package/dist/es/widgets/reactions-model.js.map +1 -0
  69. package/dist/es/widgets/remote-data-editor.js +314 -0
  70. package/dist/es/widgets/remote-data-editor.js.map +1 -0
  71. package/dist/es/widgets/use-form-data-fields.js +16 -0
  72. package/dist/es/widgets/use-form-data-fields.js.map +1 -0
  73. package/dist/es/widgets/validate-editor.js +118 -0
  74. package/dist/es/widgets/validate-editor.js.map +1 -0
  75. package/package.json +4 -5
  76. package/dist/es/react/src/components/FormController.js +0 -160
  77. package/dist/es/react/src/components/FormController.js.map +0 -1
  78. package/dist/es/react/src/components/NexusField.js +0 -98
  79. package/dist/es/react/src/components/NexusField.js.map +0 -1
  80. package/dist/es/react/src/components/NexusForm.js +0 -128
  81. package/dist/es/react/src/components/NexusForm.js.map +0 -1
  82. package/dist/es/react/src/components/NexusFormProvider.js +0 -19
  83. package/dist/es/react/src/components/NexusFormProvider.js.map +0 -1
  84. package/dist/es/react/src/components/NexusLayout.js +0 -49
  85. package/dist/es/react/src/components/NexusLayout.js.map +0 -1
  86. package/dist/es/react/src/components/NexusObject.js +0 -65
  87. package/dist/es/react/src/components/NexusObject.js.map +0 -1
  88. package/dist/es/react/src/contexts/FieldInheritContext.js +0 -6
  89. package/dist/es/react/src/contexts/FieldInheritContext.js.map +0 -1
  90. package/dist/es/react/src/contexts/GridContext.js +0 -6
  91. package/dist/es/react/src/contexts/GridContext.js.map +0 -1
  92. package/dist/es/react/src/contexts/LayoutConfigContext.js +0 -6
  93. package/dist/es/react/src/contexts/LayoutConfigContext.js.map +0 -1
  94. package/dist/es/react/src/contexts/NexusContext.js +0 -13
  95. package/dist/es/react/src/contexts/NexusContext.js.map +0 -1
  96. package/dist/es/react/src/hooks/useForm.js +0 -13
  97. package/dist/es/react/src/hooks/useForm.js.map +0 -1
  98. package/dist/es/react/src/utils/renderTreeNode.js +0 -18
  99. package/dist/es/react/src/utils/renderTreeNode.js.map +0 -1
  100. package/dist/es/react/src/utils/resolveColSpan.js +0 -10
  101. package/dist/es/react/src/utils/resolveColSpan.js.map +0 -1
  102. package/src/Canvas.tsx +0 -1111
  103. package/src/Designer.css +0 -206
  104. package/src/Designer.tsx +0 -254
  105. package/src/DesignerContext.tsx +0 -192
  106. package/src/Palette.tsx +0 -261
  107. package/src/PropertyPanel.tsx +0 -486
  108. package/src/ResizablePanel.tsx +0 -210
  109. package/src/catalog.ts +0 -527
  110. package/src/index.ts +0 -25
  111. package/src/property/basic-property.ts +0 -126
  112. package/src/schemaUtils.test.ts +0 -261
  113. package/src/schemaUtils.ts +0 -627
  114. package/src/types.ts +0 -38
  115. package/src/vite-env.d.ts +0 -1
  116. package/src/widgets/BindEditor.tsx +0 -105
  117. package/src/widgets/CodeEditor.tsx +0 -114
  118. package/src/widgets/DefaultEditor.tsx +0 -73
  119. package/src/widgets/DependenciesEditor.tsx +0 -56
  120. package/src/widgets/EnumEditor.tsx +0 -66
  121. package/src/widgets/ExpressionBuilder.tsx +0 -509
  122. package/src/widgets/ExpressionSwitch.tsx +0 -62
  123. package/src/widgets/OptionsEditor.tsx +0 -141
  124. package/src/widgets/ReactionsEditor.tsx +0 -532
  125. package/src/widgets/RemoteDataEditor.tsx +0 -382
  126. package/src/widgets/ValidateEditor.tsx +0 -162
  127. package/src/widgets/expressionModel.test.ts +0 -262
  128. package/src/widgets/expressionModel.ts +0 -573
  129. package/src/widgets/index.ts +0 -45
  130. package/src/widgets/reactionsModel.ts +0 -190
  131. package/src/widgets/useFormDataFields.ts +0 -21
@@ -1 +1 @@
1
- {"version":3,"file":"Palette.js","sources":["../../src/Palette.tsx"],"sourcesContent":["// ============================================================================\n// @xbeeant/form-engine-designer — 左侧组件目录面板\n// ============================================================================\n\nimport type { SchemaNode } from '@xbeeant/form-engine';\nimport { Collapse, Input } from 'antd';\nimport type { DragEvent } from 'react';\nimport { useCallback, useMemo, useState } from 'react';\nimport { useDesigner } from './DesignerContext';\nimport {\n generateKey,\n getNodeAtProperties,\n getPropertiesOf,\n} from './schemaUtils';\nimport type { CatalogItem, FieldDef } from './types';\n\n// 拖拽负载:palette 组件目录项 or 外部字段定义\nexport interface PaletteDragPayload {\n source: 'palette';\n catalogItem: CatalogItem;\n}\nexport interface FieldDefDragPayload {\n source: 'fieldDef';\n fieldDef: FieldDef;\n}\nexport type PaletteDragData = PaletteDragPayload | FieldDefDragPayload;\n\n// 面板类型 → 允许的唯一父容器类型(面板不能直接添加到根或普通容器)\nconst PANE_PARENT_TYPE: Record<string, string> = {\n tabPane: 'tabs',\n collapsePanel: 'collapse',\n step: 'steps',\n};\n\nconst isPaneItem = (item: CatalogItem): boolean =>\n item.category === 'layout' && !!PANE_PARENT_TYPE[item.layoutType ?? ''];\n\nfunction PaletteItem({\n item,\n onAdd,\n}: {\n item: CatalogItem;\n onAdd: (item: CatalogItem) => void;\n}) {\n const handleDragStart = (e: DragEvent<HTMLDivElement>) => {\n const payload: PaletteDragPayload = {\n source: 'palette',\n catalogItem: item,\n };\n e.dataTransfer.setData('application/json', JSON.stringify(payload));\n e.dataTransfer.effectAllowed = 'copy';\n };\n\n // 面板类组件只能放入对应容器,点击/拖拽提示差异化\n const paneParent = isPaneItem(item)\n ? PANE_PARENT_TYPE[item.layoutType ?? '']\n : undefined;\n const title = paneParent\n ? `拖拽「${item.label}」到「${paneParent}」容器中,或选中容器后点击`\n : `点击添加或拖拽「${item.label}」到画布`;\n\n return (\n <div\n className='group flex flex-col items-center gap-1 rounded-lg border border-[#f0f0f0] bg-white px-1 py-2 cursor-grab select-none transition-all hover:-translate-y-px hover:border-[#1677ff] hover:shadow-[0_2px_8px_rgba(22,119,255,0.12)] active:cursor-grabbing'\n draggable\n onDragStart={handleDragStart}\n onClick={() => onAdd(item)}\n title={title}\n >\n <span className='flex h-7 w-7 items-center justify-center rounded-md bg-[#f5f7fa] text-[15px] transition-colors group-hover:bg-[#e8f1ff]'>\n {item.icon}\n </span>\n <span className='w-full truncate text-center text-xs text-[#666] transition-colors group-hover:text-[#1677ff]'>\n {item.label}\n </span>\n </div>\n );\n}\n\nfunction FieldDefItem({ field }: { field: FieldDef }) {\n const handleDragStart = (e: DragEvent<HTMLDivElement>) => {\n const payload: FieldDefDragPayload = {\n source: 'fieldDef',\n fieldDef: field,\n };\n e.dataTransfer.setData('application/json', JSON.stringify(payload));\n e.dataTransfer.effectAllowed = 'copy';\n };\n\n return (\n <div\n className='flex items-center gap-2 rounded-lg border border-[#f0f0f0] bg-white px-2 py-1.5 cursor-grab select-none transition-all hover:-translate-y-px hover:border-[#1677ff] hover:shadow-[0_2px_8px_rgba(22,119,255,0.12)] active:cursor-grabbing'\n draggable\n onDragStart={handleDragStart}\n title={`id: ${field.id} · widget: ${field.widget}`}\n >\n <span className='flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-md bg-[#f5f7fa] text-[13px]'>\n 🔧\n </span>\n <span className='truncate text-xs text-[#666]'>{field.name}</span>\n </div>\n );\n}\n\nexport function Palette() {\n const {\n schema,\n selectedPath,\n addNode,\n fields,\n widgetCatalog,\n layoutCatalog,\n } = useDesigner();\n const [keyword, setKeyword] = useState('');\n\n const handleAdd = useCallback(\n (item: CatalogItem) => {\n const base = item.widget || item.layoutType || 'field';\n // 面板类组件只能放入对应容器:点击时若已选中匹配容器则加入,否则忽略\n const paneParentType = isPaneItem(item)\n ? PANE_PARENT_TYPE[item.layoutType ?? '']\n : undefined;\n if (paneParentType) {\n if (!selectedPath || selectedPath.length === 0) {\n return;\n }\n const parent = getNodeAtProperties(schema.properties, selectedPath);\n if (!parent || parent.type !== paneParentType) {\n return;\n }\n const parentProps = getPropertiesOf(parent);\n if (!parentProps) {\n return;\n }\n const key = generateKey(parentProps, base);\n addNode(selectedPath, key, item.createNode() as unknown as SchemaNode);\n return;\n }\n const key = generateKey(schema.properties, base);\n const node = item.createNode() as unknown as SchemaNode;\n addNode([], key, node);\n },\n [schema, addNode, selectedPath],\n );\n\n const kw = keyword.trim().toLowerCase();\n\n const widgetItems = useMemo(\n () =>\n widgetCatalog\n .filter((item) => item.label.toLowerCase().includes(kw))\n .map((item) => (\n <PaletteItem key={item.widget} item={item} onAdd={handleAdd} />\n )),\n [widgetCatalog, kw, handleAdd],\n );\n\n const layoutItems = useMemo(\n () =>\n layoutCatalog\n .filter((item) => item.label.toLowerCase().includes(kw))\n .map((item) => (\n <PaletteItem key={item.layoutType} item={item} onAdd={handleAdd} />\n )),\n [layoutCatalog, kw, handleAdd],\n );\n\n const fieldItems = useMemo(\n () =>\n (fields ?? [])\n .filter((field) => field.name.toLowerCase().includes(kw))\n .map((field) => <FieldDefItem key={field.id} field={field} />),\n [fields, kw],\n );\n\n const sectionGrid = (items: React.ReactNode[], hasMore: boolean) =>\n items.length > 0 ? (\n <div className='grid grid-cols-2 gap-1.5 px-1 pb-2'>{items}</div>\n ) : (\n <div className='py-3 text-center text-xs text-[#c0c4cc]'>\n {hasMore ? '无匹配组件' : '暂无组件'}\n </div>\n );\n\n const collapseItems = [\n {\n key: 'widgets',\n label: (\n <span className='flex w-full items-center justify-between pr-1'>\n <span>表单组件</span>\n <span className='rounded-full bg-[#f0f0f0] px-1.5 py-px text-[11px] text-[#999]'>\n {widgetItems.length}\n </span>\n </span>\n ),\n children: sectionGrid(widgetItems, true),\n },\n {\n key: 'layouts',\n label: (\n <span className='flex w-full items-center justify-between pr-1'>\n <span>布局组件</span>\n <span className='rounded-full bg-[#f0f0f0] px-1.5 py-px text-[11px] text-[#999]'>\n {layoutItems.length}\n </span>\n </span>\n ),\n children: sectionGrid(layoutItems, true),\n },\n ];\n\n // 仅当传入 fields 时显示「字段列表」分组\n if (fields && fields.length > 0) {\n collapseItems.push({\n key: 'fieldList',\n label: (\n <span className='flex w-full items-center justify-between pr-1'>\n <span>字段列表</span>\n <span className='rounded-full bg-[#f0f0f0] px-1.5 py-px text-[11px] text-[#999]'>\n {fieldItems.length}\n </span>\n </span>\n ),\n children: (\n <div className='flex flex-col gap-1.5 px-1 pb-2'>\n {fieldItems.length > 0 ? (\n fieldItems\n ) : (\n <div className='py-3 text-center text-xs text-[#c0c4cc]'>\n 无匹配字段\n </div>\n )}\n </div>\n ),\n });\n }\n\n return (\n <div className='flex h-full flex-col border-r border-[#f0f0f0] bg-[#f7f8fa]'>\n <div className='px-3 pb-2 pt-3'>\n <Input\n size='small'\n allowClear\n prefix={<span className='text-xs text-[#bbb]'>🔍</span>}\n placeholder='搜索组件…'\n value={keyword}\n onChange={(e) => setKeyword(e.target.value)}\n className='nexus-palette-search'\n />\n </div>\n <div className='flex-1 overflow-y-auto px-2 pb-3'>\n <Collapse\n className='nexus-palette-collapse'\n expandIconPlacement='end'\n defaultActiveKey={['widgets', 'layouts']}\n items={collapseItems}\n />\n </div>\n </div>\n );\n}\n"],"names":["PANE_PARENT_TYPE","isPaneItem","item","PaletteItem","onAdd","handleDragStart","e","payload","paneParent","title","jsxs","jsx","FieldDefItem","field","Palette","schema","selectedPath","addNode","fields","widgetCatalog","layoutCatalog","useDesigner","keyword","setKeyword","useState","handleAdd","useCallback","paneParentType","parent","getNodeAtProperties","parentProps","getPropertiesOf","key","generateKey","node","kw","widgetItems","useMemo","layoutItems","fieldItems","sectionGrid","items","hasMore","collapseItems","Input","Collapse"],"mappings":"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"}
1
+ {"version":3,"file":"palette.js","sources":["../../src/palette.tsx"],"sourcesContent":["// ============================================================================\n// @xbeeant/form-engine-designer — 左侧组件目录面板\n// ============================================================================\n\nimport type { SchemaNode } from '@xbeeant/form-engine';\nimport { Collapse, Input } from 'antd';\nimport type { DragEvent } from 'react';\nimport { useCallback, useMemo, useState } from 'react';\nimport { useDesigner } from './designer-context';\nimport {\n generateKey,\n getNodeAtProperties,\n getPropertiesOf,\n} from './schema-utils';\nimport type { CatalogItem, FieldDef } from './types';\n\n// 拖拽负载:palette 组件目录项 or 外部字段定义\nexport interface PaletteDragPayload {\n source: 'palette';\n catalogItem: CatalogItem;\n}\nexport interface FieldDefDragPayload {\n source: 'fieldDef';\n fieldDef: FieldDef;\n}\nexport type PaletteDragData = PaletteDragPayload | FieldDefDragPayload;\n\n// 面板类型 → 允许的唯一父容器类型(面板不能直接添加到根或普通容器)\nconst PANE_PARENT_TYPE: Record<string, string> = {\n tabPane: 'tabs',\n collapsePanel: 'collapse',\n step: 'steps',\n};\n\nconst isPaneItem = (item: CatalogItem): boolean =>\n item.category === 'layout' && !!PANE_PARENT_TYPE[item.layoutType ?? ''];\n\nfunction PaletteItem({\n item,\n onAdd,\n}: {\n item: CatalogItem;\n onAdd: (item: CatalogItem) => void;\n}) {\n const handleDragStart = (e: DragEvent<HTMLDivElement>) => {\n const payload: PaletteDragPayload = {\n source: 'palette',\n catalogItem: item,\n };\n e.dataTransfer.setData('application/json', JSON.stringify(payload));\n e.dataTransfer.effectAllowed = 'copy';\n };\n\n // 面板类组件只能放入对应容器,点击/拖拽提示差异化\n const paneParent = isPaneItem(item)\n ? PANE_PARENT_TYPE[item.layoutType ?? '']\n : undefined;\n const title = paneParent\n ? `拖拽「${item.label}」到「${paneParent}」容器中,或选中容器后点击`\n : `点击添加或拖拽「${item.label}」到画布`;\n\n return (\n <div\n className='group flex flex-col items-center gap-1 rounded-lg border border-[#f0f0f0] bg-white px-1 py-2 cursor-grab select-none transition-all hover:-translate-y-px hover:border-[#1677ff] hover:shadow-[0_2px_8px_rgba(22,119,255,0.12)] active:cursor-grabbing'\n draggable\n onDragStart={handleDragStart}\n onClick={() => onAdd(item)}\n title={title}\n >\n <span className='flex h-7 w-7 items-center justify-center rounded-md bg-[#f5f7fa] text-[15px] transition-colors group-hover:bg-[#e8f1ff]'>\n {item.icon}\n </span>\n <span className='w-full truncate text-center text-xs text-[#666] transition-colors group-hover:text-[#1677ff]'>\n {item.label}\n </span>\n </div>\n );\n}\n\nfunction FieldDefItem({ field }: { field: FieldDef }) {\n const handleDragStart = (e: DragEvent<HTMLDivElement>) => {\n const payload: FieldDefDragPayload = {\n source: 'fieldDef',\n fieldDef: field,\n };\n e.dataTransfer.setData('application/json', JSON.stringify(payload));\n e.dataTransfer.effectAllowed = 'copy';\n };\n\n return (\n <div\n className='flex items-center gap-2 rounded-lg border border-[#f0f0f0] bg-white px-2 py-1.5 cursor-grab select-none transition-all hover:-translate-y-px hover:border-[#1677ff] hover:shadow-[0_2px_8px_rgba(22,119,255,0.12)] active:cursor-grabbing'\n draggable\n onDragStart={handleDragStart}\n title={`id: ${field.id} · widget: ${field.widget}`}\n >\n <span className='flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-md bg-[#f5f7fa] text-[13px]'>\n 🔧\n </span>\n <span className='truncate text-xs text-[#666]'>{field.name}</span>\n </div>\n );\n}\n\nexport function Palette() {\n const {\n schema,\n selectedPath,\n addNode,\n fields,\n widgetCatalog,\n layoutCatalog,\n } = useDesigner();\n const [keyword, setKeyword] = useState('');\n\n const handleAdd = useCallback(\n (item: CatalogItem) => {\n const base = item.widget || item.layoutType || 'field';\n // 面板类组件只能放入对应容器:点击时若已选中匹配容器则加入,否则忽略\n const paneParentType = isPaneItem(item)\n ? PANE_PARENT_TYPE[item.layoutType ?? '']\n : undefined;\n if (paneParentType) {\n if (!selectedPath || selectedPath.length === 0) {\n return;\n }\n const parent = getNodeAtProperties(schema.properties, selectedPath);\n if (!parent || parent.type !== paneParentType) {\n return;\n }\n const parentProps = getPropertiesOf(parent);\n if (!parentProps) {\n return;\n }\n const key = generateKey(parentProps, base);\n addNode(selectedPath, key, item.createNode() as unknown as SchemaNode);\n return;\n }\n const key = generateKey(schema.properties, base);\n const node = item.createNode() as unknown as SchemaNode;\n addNode([], key, node);\n },\n [schema, addNode, selectedPath],\n );\n\n const kw = keyword.trim().toLowerCase();\n\n const widgetItems = useMemo(\n () =>\n widgetCatalog\n .filter((item) => item.label.toLowerCase().includes(kw))\n .map((item) => (\n <PaletteItem key={item.widget} item={item} onAdd={handleAdd} />\n )),\n [widgetCatalog, kw, handleAdd],\n );\n\n const layoutItems = useMemo(\n () =>\n layoutCatalog\n .filter((item) => item.label.toLowerCase().includes(kw))\n .map((item) => (\n <PaletteItem key={item.layoutType} item={item} onAdd={handleAdd} />\n )),\n [layoutCatalog, kw, handleAdd],\n );\n\n const fieldItems = useMemo(\n () =>\n (fields ?? [])\n .filter((field) => field.name.toLowerCase().includes(kw))\n .map((field) => <FieldDefItem key={field.id} field={field} />),\n [fields, kw],\n );\n\n const sectionGrid = (items: React.ReactNode[], hasMore: boolean) =>\n items.length > 0 ? (\n <div className='grid grid-cols-2 gap-1.5 px-1 pb-2'>{items}</div>\n ) : (\n <div className='py-3 text-center text-xs text-[#c0c4cc]'>\n {hasMore ? '无匹配组件' : '暂无组件'}\n </div>\n );\n\n const collapseItems = [\n {\n key: 'widgets',\n label: (\n <span className='flex w-full items-center justify-between pr-1'>\n <span>表单组件</span>\n <span className='rounded-full bg-[#f0f0f0] px-1.5 py-px text-[11px] text-[#999]'>\n {widgetItems.length}\n </span>\n </span>\n ),\n children: sectionGrid(widgetItems, true),\n },\n {\n key: 'layouts',\n label: (\n <span className='flex w-full items-center justify-between pr-1'>\n <span>布局组件</span>\n <span className='rounded-full bg-[#f0f0f0] px-1.5 py-px text-[11px] text-[#999]'>\n {layoutItems.length}\n </span>\n </span>\n ),\n children: sectionGrid(layoutItems, true),\n },\n ];\n\n // 仅当传入 fields 时显示「字段列表」分组\n if (fields && fields.length > 0) {\n collapseItems.push({\n key: 'fieldList',\n label: (\n <span className='flex w-full items-center justify-between pr-1'>\n <span>字段列表</span>\n <span className='rounded-full bg-[#f0f0f0] px-1.5 py-px text-[11px] text-[#999]'>\n {fieldItems.length}\n </span>\n </span>\n ),\n children: (\n <div className='flex flex-col gap-1.5 px-1 pb-2'>\n {fieldItems.length > 0 ? (\n fieldItems\n ) : (\n <div className='py-3 text-center text-xs text-[#c0c4cc]'>\n 无匹配字段\n </div>\n )}\n </div>\n ),\n });\n }\n\n return (\n <div className='flex h-full flex-col border-r border-[#f0f0f0] bg-[#f7f8fa]'>\n <div className='px-3 pb-2 pt-3'>\n <Input\n size='small'\n allowClear\n prefix={<span className='text-xs text-[#bbb]'>🔍</span>}\n placeholder='搜索组件…'\n value={keyword}\n onChange={(e) => setKeyword(e.target.value)}\n className='nexus-palette-search'\n />\n </div>\n <div className='flex-1 overflow-y-auto px-2 pb-3'>\n <Collapse\n className='nexus-palette-collapse'\n expandIconPlacement='end'\n defaultActiveKey={['widgets', 'layouts']}\n items={collapseItems}\n />\n </div>\n </div>\n );\n}\n"],"names":["PANE_PARENT_TYPE","isPaneItem","item","PaletteItem","onAdd","handleDragStart","e","payload","paneParent","title","jsxs","jsx","FieldDefItem","field","Palette","schema","selectedPath","addNode","fields","widgetCatalog","layoutCatalog","useDesigner","keyword","setKeyword","useState","handleAdd","useCallback","paneParentType","parent","getNodeAtProperties","parentProps","getPropertiesOf","key","generateKey","node","kw","widgetItems","useMemo","layoutItems","fieldItems","sectionGrid","items","hasMore","collapseItems","Input","Collapse"],"mappings":"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"}
@@ -1,43 +1,41 @@
1
- import { jsxs as a, jsx as o } from "react/jsx-runtime";
2
- /* empty css */
3
- import { NexusForm as S } from "./react/src/components/NexusForm.js";
4
- import { useForm as V } from "./react/src/hooks/useForm.js";
5
- import { registerAntdUI as W } from "@xbeeant/form-engine-ui";
6
- import { Input as T } from "antd";
7
- import { useMemo as P, useCallback as b, useState as A, useRef as D } from "react";
8
- import { useDesigner as E } from "./DesignerContext.js";
9
- import { dependencyPropertyFields as B, reactionPropertyFields as I, validationPropertyFields as M, commonPropertyFields as $ } from "./property/basic-property.js";
10
- import { getNodeAtProperties as z, extractFormLevelConfig as U, flattenNodeForPropertyEditor as F, diffPropertyPatch as q } from "./schemaUtils.js";
11
- import { propertyWidgets as G } from "./widgets/index.js";
12
- function H({
13
- schema: n,
1
+ import { jsxs as c, jsx as n } from "react/jsx-runtime";
2
+ import { useForm as W, NexusForm as E } from "@xbeeant/form-engine-react";
3
+ import { registerAntdUI as T } from "@xbeeant/form-engine-ui";
4
+ import { Input as A } from "antd";
5
+ import { useMemo as P, useCallback as b, useState as D, useRef as C, useEffect as K } from "react";
6
+ import { useDesigner as B } from "./DesignerContext.js";
7
+ import { dependencyPropertyFields as I, reactionPropertyFields as M, validationPropertyFields as $, commonPropertyFields as z } from "./property/basic-property.js";
8
+ import { getNodeAtProperties as U, extractFormLevelConfig as q, flattenNodeForPropertyEditor as j, diffPropertyPatch as G } from "./schemaUtils.js";
9
+ import { propertyWidgets as H } from "./widgets/index.js";
10
+ function J({
11
+ schema: o,
14
12
  initialValues: e,
15
13
  onValuesChange: r
16
14
  }) {
17
- const [i] = V(), d = i._getEngine();
18
- W(d);
19
- const s = D(/* @__PURE__ */ new Set()), l = b(
20
- (t, c, u) => {
21
- u && s.current.add(u), r(
15
+ const [s] = W(), a = s._getEngine();
16
+ T(a);
17
+ const i = C(/* @__PURE__ */ new Set()), d = b(
18
+ (t, l, u) => {
19
+ u && i.current.add(u), r(
22
20
  t,
23
- s.current
21
+ i.current
24
22
  );
25
23
  },
26
24
  [r]
27
25
  );
28
- return /* @__PURE__ */ o(
29
- S,
26
+ return /* @__PURE__ */ n(
27
+ E,
30
28
  {
31
29
  footer: !1,
32
- form: i,
33
- schema: n,
30
+ form: s,
31
+ schema: o,
34
32
  initialValues: e,
35
- watch: { "#": l },
36
- widgets: G
33
+ watch: { "#": d },
34
+ widgets: H
37
35
  }
38
36
  );
39
37
  }
40
- const j = {
38
+ const F = {
41
39
  displayType: {
42
40
  widget: "select",
43
41
  type: "string",
@@ -80,7 +78,7 @@ const j = {
80
78
  title: "每行显示列数(column)",
81
79
  default: 1
82
80
  }
83
- }, J = {
81
+ }, Q = {
84
82
  column: { widget: "number", type: "number", title: "列数(column)" },
85
83
  gap: { widget: "number", type: "number", title: "间距(gap)" },
86
84
  direction: {
@@ -95,63 +93,64 @@ const j = {
95
93
  }
96
94
  }
97
95
  };
98
- function m(n, e, r) {
96
+ function m(o, e, r) {
99
97
  return {
100
- [n]: {
98
+ [o]: {
101
99
  type: "collapsePanel",
102
100
  title: e,
103
101
  properties: r
104
102
  }
105
103
  };
106
104
  }
107
- function Q({ oldKey: n, locked: e, onRename: r }) {
108
- const [i, d] = A(n);
109
- if (e)
110
- return /* @__PURE__ */ a("div", { className: "mb-3 flex items-center justify-between gap-2 rounded-lg border border-[#f0f0f0] bg-[#fafafa] px-3 py-2", children: [
111
- /* @__PURE__ */ a("div", { className: "min-w-0", children: [
112
- /* @__PURE__ */ o("div", { className: "mb-0.5 text-[11px] text-[#999]", children: "字段标识(key)" }),
113
- /* @__PURE__ */ o("code", { className: "break-all font-mono text-[13px] text-[#333]", children: n })
105
+ function X({ oldKey: o, locked: e, onRename: r }) {
106
+ const [s, a] = D(o), i = C(o);
107
+ if (K(() => {
108
+ o !== i.current && (i.current = o, a(o));
109
+ }, [o]), e)
110
+ return /* @__PURE__ */ c("div", { className: "mb-3 flex items-center justify-between gap-2 rounded-lg border border-[#f0f0f0] bg-[#fafafa] px-3 py-2", children: [
111
+ /* @__PURE__ */ c("div", { className: "min-w-0", children: [
112
+ /* @__PURE__ */ n("div", { className: "mb-0.5 text-[11px] text-[#999]", children: "字段标识(key)" }),
113
+ /* @__PURE__ */ n("code", { className: "break-all font-mono text-[13px] text-[#333]", children: o })
114
114
  ] }),
115
- /* @__PURE__ */ o("span", { className: "shrink-0 rounded bg-[#f0f0f0] px-1.5 py-0.5 text-[11px] text-[#999]", children: "🔒 锁定" })
115
+ /* @__PURE__ */ n("span", { className: "shrink-0 rounded bg-[#f0f0f0] px-1.5 py-0.5 text-[11px] text-[#999]", children: "🔒 锁定" })
116
116
  ] });
117
- const s = (l) => {
118
- d(l), r(l);
117
+ const d = (t) => {
118
+ i.current = t, a(t), r(t);
119
119
  };
120
- return /* @__PURE__ */ a("div", { className: "mb-3", children: [
121
- /* @__PURE__ */ o("div", { className: "mb-1.5 text-[11px] text-[#999]", children: "字段标识(key)" }),
122
- /* @__PURE__ */ o(
123
- T,
120
+ return /* @__PURE__ */ c("div", { className: "mb-3", children: [
121
+ /* @__PURE__ */ n("div", { className: "mb-1.5 text-[11px] text-[#999]", children: "字段标识(key)" }),
122
+ /* @__PURE__ */ n(
123
+ A,
124
124
  {
125
125
  size: "small",
126
- value: i,
127
- onChange: (l) => {
128
- const t = (l.target.value || "").trim();
129
- s(t);
126
+ value: s,
127
+ onChange: (t) => {
128
+ const l = (t.target.value || "").trim();
129
+ d(l);
130
130
  },
131
- autoFocus: !0,
132
131
  className: "nexus-key-input"
133
132
  }
134
133
  ),
135
- /* @__PURE__ */ o("div", { className: "mt-1 text-[11px] text-[#c0c4cc]", children: "用于数据路径与联动引用,修改后自动迁移子节点" })
134
+ /* @__PURE__ */ n("div", { className: "mt-1 text-[11px] text-[#c0c4cc]", children: "用于数据路径与联动引用,修改后自动迁移子节点" })
136
135
  ] });
137
136
  }
138
- function ae() {
137
+ function ce() {
139
138
  const {
140
- schema: n,
139
+ schema: o,
141
140
  selectedPath: e,
142
141
  updateNode: r,
143
- renameNode: i,
144
- selectNode: d,
145
- setSchema: s,
146
- propertySchemaMap: l
147
- } = E(), t = e && e.length > 0 ? z(n.properties, e) : void 0, c = !e || e.length === 0, u = `node_${(e || []).join("_")}_${t?.type || "root"}`, g = e?.[e.length - 1] ?? "", C = t?._lockedKey === !0, x = t ? t.widget || t.type : null, L = P(() => {
148
- if (c)
142
+ renameNode: s,
143
+ selectNode: a,
144
+ setSchema: i,
145
+ propertySchemaMap: d
146
+ } = B(), t = e && e.length > 0 ? U(o.properties, e) : void 0, l = !e || e.length === 0, u = `node_${(e || []).join("_")}_${t?.type || "root"}`, g = e?.[e.length - 1] ?? "", L = t?._lockedKey === !0, x = t ? t.widget || t.type : null, R = P(() => {
147
+ if (l)
149
148
  return {
150
149
  type: "object",
151
- properties: j,
150
+ properties: F,
152
151
  displayType: "column"
153
152
  };
154
- const p = l[x] || J;
153
+ const p = d[x] || Q;
155
154
  return {
156
155
  type: "object",
157
156
  properties: {
@@ -171,7 +170,7 @@ function ae() {
171
170
  ...m(
172
171
  "sectionCommon",
173
172
  "通用属性",
174
- $
173
+ z
175
174
  ),
176
175
  ...m(
177
176
  "sectionFieldProps",
@@ -181,71 +180,71 @@ function ae() {
181
180
  ...m(
182
181
  "sectionValidation",
183
182
  "校验配置",
184
- M
183
+ $
185
184
  ),
186
185
  ...m(
187
186
  "sectionReaction",
188
187
  "联动配置",
189
- I
188
+ M
190
189
  ),
191
190
  ...m(
192
191
  "sectionDependency",
193
192
  "依赖配置",
194
- B
193
+ I
195
194
  )
196
195
  }
197
196
  }
198
197
  },
199
198
  displayType: "column"
200
199
  };
201
- }, [c, x, l]), f = P(
202
- () => U(
203
- n,
204
- Object.keys(j)
200
+ }, [l, x, d]), f = P(
201
+ () => q(
202
+ o,
203
+ Object.keys(F)
205
204
  ),
206
- [n]
207
- ), K = b(
208
- (p, O) => {
209
- const R = t ? F(
205
+ [o]
206
+ ), _ = b(
207
+ (p, S) => {
208
+ const V = t ? j(
210
209
  t
211
- ) : f, y = q(R, p, O);
210
+ ) : f, y = G(V, p, S);
212
211
  if (Object.keys(y).length === 0)
213
212
  return;
214
213
  if (!e || e.length === 0) {
215
- const h = { ...n };
214
+ const h = { ...o };
216
215
  for (const [k, N] of Object.entries(y))
217
216
  N === void 0 ? delete h[k] : h[k] = N;
218
- s(h);
217
+ i(h);
219
218
  return;
220
219
  }
221
- const { key: X, ...v } = y;
220
+ const { key: Y, ...v } = y;
222
221
  Object.keys(v).length > 0 && r(e, v);
223
222
  },
224
223
  [
225
224
  e,
226
225
  r,
227
- s,
228
- n,
226
+ i,
227
+ o,
229
228
  t,
230
229
  f
231
230
  ]
232
- ), _ = b(
231
+ ), O = b(
233
232
  (p) => {
234
- !e || e.length === 0 || i(e, p);
233
+ !e || e.length === 0 || s(e, p);
235
234
  },
236
- [e, i]
235
+ [e, s]
237
236
  ), w = t ? (t.widget || t.type || "").toLowerCase() : "";
238
- return /* @__PURE__ */ a("div", { className: "flex h-full flex-col border-l border-[#f0f0f0] bg-white", children: [
239
- /* @__PURE__ */ a("div", { className: "flex items-center justify-between border-b border-[#f0f0f0] px-4 py-2.5", children: [
240
- /* @__PURE__ */ a("div", { className: "pl-5 flex min-w-0 items-center gap-1 h-6", children: [
241
- !c && /* @__PURE__ */ o(
237
+ return /* @__PURE__ */ c("div", { className: "flex h-full flex-col border-l border-[#f0f0f0] bg-white", children: [
238
+ /* @__PURE__ */ c("div", { className: "flex items-center justify-between border-b border-[#f0f0f0] px-4 py-2.5", children: [
239
+ /* @__PURE__ */ c("div", { className: "pl-5 flex min-w-0 items-center gap-1 h-6", children: [
240
+ !l && /* @__PURE__ */ n(
242
241
  "button",
243
242
  {
244
243
  type: "button",
245
- onClick: () => d(null),
244
+ onClick: () => a(null),
246
245
  className: "-ml-1 mr-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-[#999] transition-colors hover:bg-[#f0f0f0] hover:text-[#333]",
247
246
  title: "返回表单属性",
248
- children: /* @__PURE__ */ o(
247
+ children: /* @__PURE__ */ n(
249
248
  "svg",
250
249
  {
251
250
  width: "12",
@@ -257,32 +256,32 @@ function ae() {
257
256
  strokeLinecap: "round",
258
257
  strokeLinejoin: "round",
259
258
  "aria-hidden": "true",
260
- children: /* @__PURE__ */ o("polyline", { points: "15 18 9 12 15 6" })
259
+ children: /* @__PURE__ */ n("polyline", { points: "15 18 9 12 15 6" })
261
260
  }
262
261
  )
263
262
  }
264
263
  ),
265
- /* @__PURE__ */ o("span", { className: "truncate text-[13px] font-semibold text-[#333]", children: c ? "表单属性" : "节点属性" })
264
+ /* @__PURE__ */ n("span", { className: "truncate text-[13px] font-semibold text-[#333]", children: l ? "表单属性" : "节点属性" })
266
265
  ] }),
267
- !c && w && /* @__PURE__ */ o("span", { className: "ml-2 shrink-0 rounded-md bg-[#e8f1ff] px-1.5 py-0.5 text-[11px] text-[#1677ff]", children: w })
266
+ !l && w && /* @__PURE__ */ n("span", { className: "ml-2 shrink-0 rounded-md bg-[#e8f1ff] px-1.5 py-0.5 text-[11px] text-[#1677ff]", children: w })
268
267
  ] }),
269
- /* @__PURE__ */ a("div", { className: "nexus-property-body flex-1 overflow-y-auto px-4 py-3", children: [
270
- !c && g && /* @__PURE__ */ o(
271
- Q,
268
+ /* @__PURE__ */ c("div", { className: "nexus-property-body flex-1 overflow-y-auto px-4 py-3", children: [
269
+ !l && g && /* @__PURE__ */ n(
270
+ X,
272
271
  {
273
272
  oldKey: g,
274
- locked: C,
275
- onRename: _
273
+ locked: L,
274
+ onRename: O
276
275
  }
277
276
  ),
278
- /* @__PURE__ */ o(
279
- H,
277
+ /* @__PURE__ */ n(
278
+ J,
280
279
  {
281
- schema: L,
282
- initialValues: t ? F(
280
+ schema: R,
281
+ initialValues: t ? j(
283
282
  t
284
283
  ) : f,
285
- onValuesChange: K
284
+ onValuesChange: _
286
285
  },
287
286
  u
288
287
  )
@@ -290,6 +289,6 @@ function ae() {
290
289
  ] });
291
290
  }
292
291
  export {
293
- ae as PropertyPanel
292
+ ce as PropertyPanel
294
293
  };
295
294
  //# sourceMappingURL=PropertyPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PropertyPanel.js","sources":["../../src/PropertyPanel.tsx"],"sourcesContent":["// ============================================================================\n// @xbeeant/form-engine-designer — 右侧属性配置面板\n// 属性定义采用「描述符驱动」:\n// - 组件(widget)属性来自外部传入的 propertySchemaMap(key 为 widget 名,\n// 值为该组件的属性字段定义,示例见 @xbeeant/form-engine-ui/src/schema/*-schema.ts)\n// - 通用 / 校验 / 依赖分区在 ./property/basic-property.ts 中定义\n// - 布局节点与表单级属性在下方 formLevelProps / layoutBasicProps 内联定义\n//\n// 编辑流程(与 schemaUtils 的读/写通路对应):\n// flattenNodeForPropertyEditor → 节点 → 扁平 initialValues(读)\n// updateNodeWithNesting → 扁平 patch → 节点(写,split schema级/props级)\n// PropertyForm 通过 NexusForm 渲染 propertySchema 描述符驱动的表单\n// ============================================================================\n\nimport type { NexusSchema, SchemaNode } from '@xbeeant/form-engine';\nimport { NexusForm, useForm } from '@xbeeant/form-engine-react';\nimport { registerAntdUI } from '@xbeeant/form-engine-ui';\nimport { Input } from 'antd';\nimport { useCallback, useMemo, useRef, useState } from 'react';\nimport { useDesigner } from './DesignerContext';\nimport {\n commonPropertyFields,\n dependencyPropertyFields,\n reactionPropertyFields,\n validationPropertyFields,\n} from './property/basic-property.ts';\nimport {\n diffPropertyPatch,\n extractFormLevelConfig,\n flattenNodeForPropertyEditor,\n getNodeAtProperties,\n} from './schemaUtils';\nimport { propertyWidgets } from './widgets';\n\n// ────────────────────────────────────────────────────────────────────────────\n// PropertyForm — 属性表单容器\n// Designer 的自定义属性编辑器独立于 form-engine 的渲染系统\n// ────────────────────────────────────────────────────────────────────────────\n\ninterface PropertyFormProps {\n schema: NexusSchema;\n initialValues: Record<string, unknown>;\n onValuesChange: (\n allValues: Record<string, unknown>,\n changedFields: ReadonlySet<string>,\n ) => void;\n}\n\nfunction PropertyForm({\n schema,\n initialValues,\n onValuesChange,\n}: PropertyFormProps) {\n const [form] = useForm();\n const engine = form._getEngine();\n\n // 注册 antd 基础 widget(select/input/switch/number/textarea/collapse/collapsePanel)\n registerAntdUI(engine);\n // 记录本表单实例中用户实际改动过的字段(组件随 formKey 重建,节点切换时自动重置)。\n // 用于区分「未触碰的字符串默认值 ''」与「用户主动清空」——\n // 后者需要回写 schema(删除属性),前者写回会污染 schema(如 bind:'' 导致数据 key 丢失)。\n const changedFieldsRef = useRef<Set<string>>(new Set());\n // '#' 全局 watcher 由 FormController._onFieldValueChange 调用,\n // 前两个参数为 (globalData, globalData),第三参为本次实际变更的字段路径\n const handleWatch = useCallback(\n (value: unknown, _allValues: unknown, changedPath?: string) => {\n if (changedPath) {\n changedFieldsRef.current.add(changedPath);\n }\n onValuesChange(\n value as Record<string, unknown>,\n changedFieldsRef.current,\n );\n },\n [onValuesChange],\n );\n\n return (\n <NexusForm\n footer={false}\n form={form}\n schema={schema}\n initialValues={initialValues}\n watch={{ '#': handleWatch }}\n widgets={propertyWidgets}\n />\n );\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// 表单级属性(未选中节点时编辑 NexusSchema 顶层配置)\n// ────────────────────────────────────────────────────────────────────────────\n\nconst formLevelProps: Record<string, SchemaNode> = {\n displayType: {\n widget: 'select',\n type: 'string',\n title: '表单布局方向(displayType)',\n props: {\n options: [\n { label: '水平(row)', value: 'row' },\n { label: '垂直(column)', value: 'column' },\n { label: '行内(inline)', value: 'inline' },\n ],\n },\n },\n labelWidth: {\n widget: 'input',\n type: 'string',\n title: 'label 宽度(labelWidth)',\n placeholder: '如 120 或 20%',\n },\n colon: {\n widget: 'switch',\n type: 'boolean',\n title: '显示冒号(colon)',\n default: true,\n },\n label: {\n widget: 'switch',\n type: 'boolean',\n title: '显示 label(label)',\n default: true,\n },\n readOnly: {\n widget: 'switch',\n type: 'boolean',\n title: '整个表单只读(readOnly)',\n default: false,\n },\n column: {\n widget: 'number',\n type: 'number',\n title: '每行显示列数(column)',\n default: 1,\n },\n};\n\n// ────────────────────────────────────────────────────────────────────────────\n// 布局节点基础属性(layout nodes 不在 propertySchemaMap 中,单独定义)\n// ────────────────────────────────────────────────────────────────────────────\n\nconst layoutBasicProps: Record<string, SchemaNode> = {\n column: { widget: 'number', type: 'number', title: '列数(column)' },\n gap: { widget: 'number', type: 'number', title: '间距(gap)' },\n direction: {\n widget: 'select',\n type: 'string',\n title: '方向(direction)',\n props: {\n options: [\n { label: '水平', value: 'row' },\n { label: '垂直', value: 'column' },\n ],\n },\n },\n};\n\n// ────────────────────────────────────────────────────────────────────────────\n// collapseSection — 将一组扁平字段包裹成单个 collapse 分区\n// collapse / collapsePanel 均为布局节点,key 不进入数据路径,\n// 因此其内部字段(title / validate / bind 等)会被扁平地暴露给属性表单。\n// ────────────────────────────────────────────────────────────────────────────\n\nfunction collapseSection(\n key: string,\n title: string,\n fields: Record<string, SchemaNode>,\n): Record<string, SchemaNode> {\n // @ts-expect-error\n return {\n [key]: {\n type: 'collapsePanel',\n title,\n properties: fields,\n },\n } as unknown as SchemaNode;\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// KeyEditor — 单独处理 key 的编辑器\n// key 不是 SchemaNode 的属性,而是 properties 的索引键\n// 修改 key = schema 结构级操作:删除旧 key + 添加新 key + 更新选中路径\n// ────────────────────────────────────────────────────────────────────────────\n\ninterface KeyEditorProps {\n oldKey: string;\n locked?: boolean;\n onRename: (newKey: string) => void;\n}\n\nfunction KeyEditor({ oldKey, locked, onRename }: KeyEditorProps) {\n const [value, setValue] = useState(oldKey);\n\n if (locked) {\n return (\n <div className='mb-3 flex items-center justify-between gap-2 rounded-lg border border-[#f0f0f0] bg-[#fafafa] px-3 py-2'>\n <div className='min-w-0'>\n <div className='mb-0.5 text-[11px] text-[#999]'>字段标识(key)</div>\n <code className='break-all font-mono text-[13px] text-[#333]'>\n {oldKey}\n </code>\n </div>\n <span className='shrink-0 rounded bg-[#f0f0f0] px-1.5 py-0.5 text-[11px] text-[#999]'>\n 🔒 锁定\n </span>\n </div>\n );\n }\n\n const onChange = (v: string) => {\n setValue(v);\n onRename(v);\n };\n\n return (\n <div className='mb-3'>\n <div className='mb-1.5 text-[11px] text-[#999]'>字段标识(key)</div>\n <Input\n size='small'\n value={value}\n onChange={(e) => {\n const trimmed = (e.target.value || '').trim();\n onChange(trimmed);\n }}\n autoFocus\n className='nexus-key-input'\n />\n <div className='mt-1 text-[11px] text-[#c0c4cc]'>\n 用于数据路径与联动引用,修改后自动迁移子节点\n </div>\n </div>\n );\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// PropertyPanel — 主组件\n// ────────────────────────────────────────────────────────────────────────────\n\nexport function PropertyPanel() {\n const {\n schema,\n selectedPath,\n updateNode,\n renameNode,\n selectNode,\n setSchema,\n propertySchemaMap,\n } = useDesigner();\n\n const selectedNode =\n selectedPath && selectedPath.length > 0\n ? getNodeAtProperties(schema.properties, selectedPath)\n : undefined;\n\n const isFormLevel = !selectedPath || selectedPath.length === 0;\n\n // 选择变化时强制重建引擎(nodeVersion bump)\n const formKey = `node_${(selectedPath || []).join('_')}_${(selectedNode as { type?: string } | undefined)?.type || 'root'}`;\n\n // key 的特殊性:从 path 最后一段提取,不通过 NexusForm 管理\n const currentKey = selectedPath?.[selectedPath.length - 1] ?? '';\n const keyLocked =\n (selectedNode as unknown as Record<string, unknown> | undefined)\n ?._lockedKey === true;\n\n // 选中节点的 widget/type:决定属性面板使用哪组组件属性;\n // 仅在切换节点(widget/type 改变)时重新计算,避免每次输入都重建 schema\n // (selectedNode 的 object identity 会随每次 edit 变化,不能直接依赖)\n const selectedWidgetKey = selectedNode\n ? (selectedNode.widget as string | undefined) ||\n (selectedNode.type as string)\n : null;\n\n // 构建属性表单 schema:\n // - 未选中节点(form-level):formLevelProps(NexusSchema 顶层配置)\n // - 选中节点:4 个 collapse 分区(通用属性 / 组件属性 / 校验配置 / 依赖配置)\n // collapse 与 collapsePanel 均为布局节点,key 不进入数据路径,\n // 各分区内部字段会被扁平暴露给属性表单。\n // 注意:不依赖 selectedNode 对象本身(每次 edit 都是新引用),\n // 只依赖 isFormLevel 和 selectedWidgetKey,避免无谓 re-init。\n const formSchema = useMemo<NexusSchema>(() => {\n if (isFormLevel) {\n return {\n type: 'object',\n properties: formLevelProps,\n displayType: 'column',\n } as NexusSchema;\n }\n\n const widgetProps =\n propertySchemaMap[selectedWidgetKey as string] || layoutBasicProps;\n\n return {\n type: 'object',\n properties: {\n sectionProperty: {\n widget: 'collapse',\n props: {\n defaultActiveKey: [\n 'sectionCommon',\n 'sectionFieldProps',\n 'sectionValidation',\n 'sectionReaction',\n 'sectionDependency',\n ],\n },\n type: 'collapse',\n properties: {\n ...collapseSection(\n 'sectionCommon',\n '通用属性',\n commonPropertyFields,\n ),\n ...collapseSection(\n 'sectionFieldProps',\n '组件属性',\n widgetProps as Record<string, SchemaNode>,\n ),\n ...collapseSection(\n 'sectionValidation',\n '校验配置',\n validationPropertyFields,\n ),\n ...collapseSection(\n 'sectionReaction',\n '联动配置',\n reactionPropertyFields,\n ),\n ...collapseSection(\n 'sectionDependency',\n '依赖配置',\n dependencyPropertyFields,\n ),\n },\n },\n },\n displayType: 'column',\n } as NexusSchema;\n }, [isFormLevel, selectedWidgetKey, propertySchemaMap]);\n\n // 表单级属性面板的取值来源:只提取 NexusSchema 顶层的表单配置键,\n // 而非整个 schema 对象(schema 含 properties 与嵌套字段,不是表单级配置)\n const formLevelConfig = useMemo<Record<string, unknown>>(\n () =>\n extractFormLevelConfig(\n schema as unknown as Record<string, unknown>,\n Object.keys(formLevelProps),\n ),\n [schema],\n );\n\n const handleValuesChange = useCallback(\n (\n allValues: Record<string, unknown>,\n changedFields: ReadonlySet<string>,\n ) => {\n // 只写回「真正变化」的值:未触碰的空字符串(''/undefined/null)视为未赋值,\n // 不写回 Schema(否则 bind:'' / hidden:'' / required:'' 会导致 key 丢失 / 空联动);\n // 用户主动清空的字段(changedFields 命中)以 undefined 回写,由\n // updateNodeWithNesting 从节点删除对应属性(详见 diffPropertyPatch)\n const initial = selectedNode\n ? flattenNodeForPropertyEditor(\n selectedNode as unknown as Record<string, any>,\n )\n : formLevelConfig;\n\n const patch = diffPropertyPatch(initial, allValues, changedFields);\n if (Object.keys(patch).length === 0) {\n return;\n }\n\n if (!selectedPath || selectedPath.length === 0) {\n // form-level:修改 NexusSchema 顶层属性(undefined 表示清空,删除该键)\n const next = { ...(schema as unknown as Record<string, unknown>) };\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) {\n delete next[key];\n } else {\n next[key] = value;\n }\n }\n setSchema(next as unknown as NexusSchema);\n return;\n }\n\n // 节点级:key 已由 KeyEditor 单独处理,此处跳过\n const { key: _key, ...rest } = patch;\n if (Object.keys(rest).length > 0) {\n updateNode(selectedPath, rest);\n }\n },\n [\n selectedPath,\n updateNode,\n setSchema,\n schema,\n selectedNode,\n formLevelConfig,\n ],\n );\n\n const handleRename = useCallback(\n (newKey: string) => {\n if (!selectedPath || selectedPath.length === 0) {\n return;\n }\n renameNode(selectedPath, newKey);\n },\n [selectedPath, renameNode],\n );\n\n // 节点类型徽标:字段取 widget,布局/对象取 type\n const nodeKind = selectedNode\n ? (\n (selectedNode.widget as string) ||\n (selectedNode.type as string) ||\n ''\n ).toLowerCase()\n : '';\n\n return (\n <div className='flex h-full flex-col border-l border-[#f0f0f0] bg-white'>\n {/* 导航头 */}\n <div className='flex items-center justify-between border-b border-[#f0f0f0] px-4 py-2.5'>\n <div className='pl-5 flex min-w-0 items-center gap-1 h-6'>\n {!isFormLevel && (\n <button\n type='button'\n onClick={() => selectNode(null)}\n className='-ml-1 mr-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-[#999] transition-colors hover:bg-[#f0f0f0] hover:text-[#333]'\n title='返回表单属性'\n >\n <svg\n width='12'\n height='12'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2.5'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <polyline points='15 18 9 12 15 6' />\n </svg>\n </button>\n )}\n <span className='truncate text-[13px] font-semibold text-[#333]'>\n {isFormLevel ? '表单属性' : '节点属性'}\n </span>\n </div>\n {!isFormLevel && nodeKind && (\n <span className='ml-2 shrink-0 rounded-md bg-[#e8f1ff] px-1.5 py-0.5 text-[11px] text-[#1677ff]'>\n {nodeKind}\n </span>\n )}\n </div>\n\n <div className='nexus-property-body flex-1 overflow-y-auto px-4 py-3'>\n {/* key 特殊性处理:key 不是 SchemaNode 属性,而是 properties 索引键 */}\n {!isFormLevel && currentKey && (\n <KeyEditor\n oldKey={currentKey}\n locked={keyLocked}\n onRename={handleRename}\n />\n )}\n\n {/* 属性表单:完全基于 descriptor 驱动 */}\n <PropertyForm\n key={formKey}\n schema={formSchema}\n initialValues={\n selectedNode\n ? flattenNodeForPropertyEditor(\n selectedNode as unknown as Record<string, any>,\n )\n : formLevelConfig\n }\n onValuesChange={handleValuesChange}\n />\n </div>\n </div>\n );\n}\n"],"names":["PropertyForm","schema","initialValues","onValuesChange","form","useForm","engine","registerAntdUI","changedFieldsRef","useRef","handleWatch","useCallback","value","_allValues","changedPath","jsx","NexusForm","propertyWidgets","formLevelProps","layoutBasicProps","collapseSection","key","title","fields","KeyEditor","oldKey","locked","onRename","setValue","useState","jsxs","onChange","v","Input","e","trimmed","PropertyPanel","selectedPath","updateNode","renameNode","selectNode","setSchema","propertySchemaMap","useDesigner","selectedNode","getNodeAtProperties","isFormLevel","formKey","currentKey","keyLocked","selectedWidgetKey","formSchema","useMemo","widgetProps","commonPropertyFields","validationPropertyFields","reactionPropertyFields","dependencyPropertyFields","formLevelConfig","extractFormLevelConfig","handleValuesChange","allValues","changedFields","initial","flattenNodeForPropertyEditor","patch","diffPropertyPatch","next","_key","rest","handleRename","newKey","nodeKind"],"mappings":"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"}
1
+ {"version":3,"file":"PropertyPanel.js","sources":["../../src/PropertyPanel.tsx"],"sourcesContent":["// ============================================================================\n// @xbeeant/form-engine-designer — 右侧属性配置面板\n// 属性定义采用「描述符驱动」:\n// - 组件(widget)属性来自外部传入的 propertySchemaMap(key 为 widget 名,\n// 值为该组件的属性字段定义,示例见 @xbeeant/form-engine-ui/src/schema/*-schema.ts)\n// - 通用 / 校验 / 依赖分区在 ./property/basic-property.ts 中定义\n// - 布局节点与表单级属性在下方 formLevelProps / layoutBasicProps 内联定义\n//\n// 编辑流程(与 schemaUtils 的读/写通路对应):\n// flattenNodeForPropertyEditor → 节点 → 扁平 initialValues(读)\n// updateNodeWithNesting → 扁平 patch → 节点(写,split schema级/props级)\n// PropertyForm 通过 NexusForm 渲染 propertySchema 描述符驱动的表单\n// ============================================================================\n\nimport type { NexusSchema, SchemaNode } from '@xbeeant/form-engine';\nimport { NexusForm, useForm } from '@xbeeant/form-engine-react';\nimport { registerAntdUI } from '@xbeeant/form-engine-ui';\nimport { Input } from 'antd';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useDesigner } from './DesignerContext';\nimport {\n commonPropertyFields,\n dependencyPropertyFields,\n reactionPropertyFields,\n validationPropertyFields,\n} from './property/basic-property.ts';\nimport {\n diffPropertyPatch,\n extractFormLevelConfig,\n flattenNodeForPropertyEditor,\n getNodeAtProperties,\n} from './schemaUtils';\nimport { propertyWidgets } from './widgets';\n\n// ────────────────────────────────────────────────────────────────────────────\n// PropertyForm — 属性表单容器\n// Designer 的自定义属性编辑器独立于 form-engine 的渲染系统\n// ────────────────────────────────────────────────────────────────────────────\n\ninterface PropertyFormProps {\n schema: NexusSchema;\n initialValues: Record<string, unknown>;\n onValuesChange: (\n allValues: Record<string, unknown>,\n changedFields: ReadonlySet<string>,\n ) => void;\n}\n\nfunction PropertyForm({\n schema,\n initialValues,\n onValuesChange,\n}: PropertyFormProps) {\n const [form] = useForm();\n const engine = form._getEngine();\n\n // 注册 antd 基础 widget(select/input/switch/number/textarea/collapse/collapsePanel)\n registerAntdUI(engine);\n // 记录本表单实例中用户实际改动过的字段(组件随 formKey 重建,节点切换时自动重置)。\n // 用于区分「未触碰的字符串默认值 ''」与「用户主动清空」——\n // 后者需要回写 schema(删除属性),前者写回会污染 schema(如 bind:'' 导致数据 key 丢失)。\n const changedFieldsRef = useRef<Set<string>>(new Set());\n // '#' 全局 watcher 由 FormController._onFieldValueChange 调用,\n // 前两个参数为 (globalData, globalData),第三参为本次实际变更的字段路径\n const handleWatch = useCallback(\n (value: unknown, _allValues: unknown, changedPath?: string) => {\n if (changedPath) {\n changedFieldsRef.current.add(changedPath);\n }\n onValuesChange(\n value as Record<string, unknown>,\n changedFieldsRef.current,\n );\n },\n [onValuesChange],\n );\n\n return (\n <NexusForm\n footer={false}\n form={form}\n schema={schema}\n initialValues={initialValues}\n watch={{ '#': handleWatch }}\n widgets={propertyWidgets}\n />\n );\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// 表单级属性(未选中节点时编辑 NexusSchema 顶层配置)\n// ────────────────────────────────────────────────────────────────────────────\n\nconst formLevelProps: Record<string, SchemaNode> = {\n displayType: {\n widget: 'select',\n type: 'string',\n title: '表单布局方向(displayType)',\n props: {\n options: [\n { label: '水平(row)', value: 'row' },\n { label: '垂直(column)', value: 'column' },\n { label: '行内(inline)', value: 'inline' },\n ],\n },\n },\n labelWidth: {\n widget: 'input',\n type: 'string',\n title: 'label 宽度(labelWidth)',\n placeholder: '如 120 或 20%',\n },\n colon: {\n widget: 'switch',\n type: 'boolean',\n title: '显示冒号(colon)',\n default: true,\n },\n label: {\n widget: 'switch',\n type: 'boolean',\n title: '显示 label(label)',\n default: true,\n },\n readOnly: {\n widget: 'switch',\n type: 'boolean',\n title: '整个表单只读(readOnly)',\n default: false,\n },\n column: {\n widget: 'number',\n type: 'number',\n title: '每行显示列数(column)',\n default: 1,\n },\n};\n\n// ────────────────────────────────────────────────────────────────────────────\n// 布局节点基础属性(layout nodes 不在 propertySchemaMap 中,单独定义)\n// ────────────────────────────────────────────────────────────────────────────\n\nconst layoutBasicProps: Record<string, SchemaNode> = {\n column: { widget: 'number', type: 'number', title: '列数(column)' },\n gap: { widget: 'number', type: 'number', title: '间距(gap)' },\n direction: {\n widget: 'select',\n type: 'string',\n title: '方向(direction)',\n props: {\n options: [\n { label: '水平', value: 'row' },\n { label: '垂直', value: 'column' },\n ],\n },\n },\n};\n\n// ────────────────────────────────────────────────────────────────────────────\n// collapseSection — 将一组扁平字段包裹成单个 collapse 分区\n// collapse / collapsePanel 均为布局节点,key 不进入数据路径,\n// 因此其内部字段(title / validate / bind 等)会被扁平地暴露给属性表单。\n// ────────────────────────────────────────────────────────────────────────────\n\nfunction collapseSection(\n key: string,\n title: string,\n fields: Record<string, SchemaNode>,\n): Record<string, SchemaNode> {\n // @ts-expect-error\n return {\n [key]: {\n type: 'collapsePanel',\n title,\n properties: fields,\n },\n } as unknown as SchemaNode;\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// KeyEditor — 单独处理 key 的编辑器\n// key 不是 SchemaNode 的属性,而是 properties 的索引键\n// 修改 key = schema 结构级操作:删除旧 key + 添加新 key + 更新选中路径\n// ────────────────────────────────────────────────────────────────────────────\n\ninterface KeyEditorProps {\n oldKey: string;\n locked?: boolean;\n onRename: (newKey: string) => void;\n}\n\nfunction KeyEditor({ oldKey, locked, onRename }: KeyEditorProps) {\n const [value, setValue] = useState(oldKey);\n // 记录已同步到本地 state 的外部 key:仅当外部 oldKey 发生「非本次编辑产生」的\n // 变化(如切换选中节点)时才重置输入框,避免用 key 重建组件导致失焦\n const syncedKeyRef = useRef(oldKey);\n\n useEffect(() => {\n if (oldKey !== syncedKeyRef.current) {\n syncedKeyRef.current = oldKey;\n setValue(oldKey);\n }\n }, [oldKey]);\n\n if (locked) {\n return (\n <div className='mb-3 flex items-center justify-between gap-2 rounded-lg border border-[#f0f0f0] bg-[#fafafa] px-3 py-2'>\n <div className='min-w-0'>\n <div className='mb-0.5 text-[11px] text-[#999]'>字段标识(key)</div>\n <code className='break-all font-mono text-[13px] text-[#333]'>\n {oldKey}\n </code>\n </div>\n <span className='shrink-0 rounded bg-[#f0f0f0] px-1.5 py-0.5 text-[11px] text-[#999]'>\n 🔒 锁定\n </span>\n </div>\n );\n }\n\n const onChange = (v: string) => {\n syncedKeyRef.current = v;\n setValue(v);\n onRename(v);\n };\n\n return (\n <div className='mb-3'>\n <div className='mb-1.5 text-[11px] text-[#999]'>字段标识(key)</div>\n <Input\n size='small'\n value={value}\n onChange={(e) => {\n const trimmed = (e.target.value || '').trim();\n onChange(trimmed);\n }}\n className='nexus-key-input'\n />\n <div className='mt-1 text-[11px] text-[#c0c4cc]'>\n 用于数据路径与联动引用,修改后自动迁移子节点\n </div>\n </div>\n );\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// PropertyPanel — 主组件\n// ────────────────────────────────────────────────────────────────────────────\n\nexport function PropertyPanel() {\n const {\n schema,\n selectedPath,\n updateNode,\n renameNode,\n selectNode,\n setSchema,\n propertySchemaMap,\n } = useDesigner();\n\n const selectedNode =\n selectedPath && selectedPath.length > 0\n ? getNodeAtProperties(schema.properties, selectedPath)\n : undefined;\n\n const isFormLevel = !selectedPath || selectedPath.length === 0;\n\n // 选择变化时强制重建引擎(nodeVersion bump)\n const formKey = `node_${(selectedPath || []).join('_')}_${(selectedNode as { type?: string } | undefined)?.type || 'root'}`;\n\n // key 的特殊性:从 path 最后一段提取,不通过 NexusForm 管理\n const currentKey = selectedPath?.[selectedPath.length - 1] ?? '';\n const keyLocked =\n (selectedNode as unknown as Record<string, unknown> | undefined)\n ?._lockedKey === true;\n\n // 选中节点的 widget/type:决定属性面板使用哪组组件属性;\n // 仅在切换节点(widget/type 改变)时重新计算,避免每次输入都重建 schema\n // (selectedNode 的 object identity 会随每次 edit 变化,不能直接依赖)\n const selectedWidgetKey = selectedNode\n ? (selectedNode.widget as string | undefined) ||\n (selectedNode.type as string)\n : null;\n\n // 构建属性表单 schema:\n // - 未选中节点(form-level):formLevelProps(NexusSchema 顶层配置)\n // - 选中节点:4 个 collapse 分区(通用属性 / 组件属性 / 校验配置 / 依赖配置)\n // collapse 与 collapsePanel 均为布局节点,key 不进入数据路径,\n // 各分区内部字段会被扁平暴露给属性表单。\n // 注意:不依赖 selectedNode 对象本身(每次 edit 都是新引用),\n // 只依赖 isFormLevel 和 selectedWidgetKey,避免无谓 re-init。\n const formSchema = useMemo<NexusSchema>(() => {\n if (isFormLevel) {\n return {\n type: 'object',\n properties: formLevelProps,\n displayType: 'column',\n } as NexusSchema;\n }\n\n const widgetProps =\n propertySchemaMap[selectedWidgetKey as string] || layoutBasicProps;\n\n return {\n type: 'object',\n properties: {\n sectionProperty: {\n widget: 'collapse',\n props: {\n defaultActiveKey: [\n 'sectionCommon',\n 'sectionFieldProps',\n 'sectionValidation',\n 'sectionReaction',\n 'sectionDependency',\n ],\n },\n type: 'collapse',\n properties: {\n ...collapseSection(\n 'sectionCommon',\n '通用属性',\n commonPropertyFields,\n ),\n ...collapseSection(\n 'sectionFieldProps',\n '组件属性',\n widgetProps as Record<string, SchemaNode>,\n ),\n ...collapseSection(\n 'sectionValidation',\n '校验配置',\n validationPropertyFields,\n ),\n ...collapseSection(\n 'sectionReaction',\n '联动配置',\n reactionPropertyFields,\n ),\n ...collapseSection(\n 'sectionDependency',\n '依赖配置',\n dependencyPropertyFields,\n ),\n },\n },\n },\n displayType: 'column',\n } as NexusSchema;\n }, [isFormLevel, selectedWidgetKey, propertySchemaMap]);\n\n // 表单级属性面板的取值来源:只提取 NexusSchema 顶层的表单配置键,\n // 而非整个 schema 对象(schema 含 properties 与嵌套字段,不是表单级配置)\n const formLevelConfig = useMemo<Record<string, unknown>>(\n () =>\n extractFormLevelConfig(\n schema as unknown as Record<string, unknown>,\n Object.keys(formLevelProps),\n ),\n [schema],\n );\n\n const handleValuesChange = useCallback(\n (\n allValues: Record<string, unknown>,\n changedFields: ReadonlySet<string>,\n ) => {\n // 只写回「真正变化」的值:未触碰的空字符串(''/undefined/null)视为未赋值,\n // 不写回 Schema(否则 bind:'' / hidden:'' / required:'' 会导致 key 丢失 / 空联动);\n // 用户主动清空的字段(changedFields 命中)以 undefined 回写,由\n // updateNodeWithNesting 从节点删除对应属性(详见 diffPropertyPatch)\n const initial = selectedNode\n ? flattenNodeForPropertyEditor(\n selectedNode as unknown as Record<string, any>,\n )\n : formLevelConfig;\n\n const patch = diffPropertyPatch(initial, allValues, changedFields);\n if (Object.keys(patch).length === 0) {\n return;\n }\n\n if (!selectedPath || selectedPath.length === 0) {\n // form-level:修改 NexusSchema 顶层属性(undefined 表示清空,删除该键)\n const next = { ...(schema as unknown as Record<string, unknown>) };\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) {\n delete next[key];\n } else {\n next[key] = value;\n }\n }\n setSchema(next as unknown as NexusSchema);\n return;\n }\n\n // 节点级:key 已由 KeyEditor 单独处理,此处跳过\n const { key: _key, ...rest } = patch;\n if (Object.keys(rest).length > 0) {\n updateNode(selectedPath, rest);\n }\n },\n [\n selectedPath,\n updateNode,\n setSchema,\n schema,\n selectedNode,\n formLevelConfig,\n ],\n );\n\n const handleRename = useCallback(\n (newKey: string) => {\n if (!selectedPath || selectedPath.length === 0) {\n return;\n }\n renameNode(selectedPath, newKey);\n },\n [selectedPath, renameNode],\n );\n\n // 节点类型徽标:字段取 widget,布局/对象取 type\n const nodeKind = selectedNode\n ? (\n (selectedNode.widget as string) ||\n (selectedNode.type as string) ||\n ''\n ).toLowerCase()\n : '';\n\n return (\n <div className='flex h-full flex-col border-l border-[#f0f0f0] bg-white'>\n {/* 导航头 */}\n <div className='flex items-center justify-between border-b border-[#f0f0f0] px-4 py-2.5'>\n <div className='pl-5 flex min-w-0 items-center gap-1 h-6'>\n {!isFormLevel && (\n <button\n type='button'\n onClick={() => selectNode(null)}\n className='-ml-1 mr-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-[#999] transition-colors hover:bg-[#f0f0f0] hover:text-[#333]'\n title='返回表单属性'\n >\n <svg\n width='12'\n height='12'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2.5'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <polyline points='15 18 9 12 15 6' />\n </svg>\n </button>\n )}\n <span className='truncate text-[13px] font-semibold text-[#333]'>\n {isFormLevel ? '表单属性' : '节点属性'}\n </span>\n </div>\n {!isFormLevel && nodeKind && (\n <span className='ml-2 shrink-0 rounded-md bg-[#e8f1ff] px-1.5 py-0.5 text-[11px] text-[#1677ff]'>\n {nodeKind}\n </span>\n )}\n </div>\n\n <div className='nexus-property-body flex-1 overflow-y-auto px-4 py-3'>\n {/* key 特殊性处理:key 不是 SchemaNode 属性,而是 properties 索引键 */}\n {!isFormLevel && currentKey && (\n <KeyEditor\n oldKey={currentKey}\n locked={keyLocked}\n onRename={handleRename}\n />\n )}\n\n {/* 属性表单:完全基于 descriptor 驱动 */}\n <PropertyForm\n key={formKey}\n schema={formSchema}\n initialValues={\n selectedNode\n ? flattenNodeForPropertyEditor(\n selectedNode as unknown as Record<string, any>,\n )\n : formLevelConfig\n }\n onValuesChange={handleValuesChange}\n />\n </div>\n </div>\n );\n}\n"],"names":["PropertyForm","schema","initialValues","onValuesChange","form","useForm","engine","registerAntdUI","changedFieldsRef","useRef","handleWatch","useCallback","value","_allValues","changedPath","jsx","NexusForm","propertyWidgets","formLevelProps","layoutBasicProps","collapseSection","key","title","fields","KeyEditor","oldKey","locked","onRename","setValue","useState","syncedKeyRef","useEffect","jsxs","onChange","v","Input","e","trimmed","PropertyPanel","selectedPath","updateNode","renameNode","selectNode","setSchema","propertySchemaMap","useDesigner","selectedNode","getNodeAtProperties","isFormLevel","formKey","currentKey","keyLocked","selectedWidgetKey","formSchema","useMemo","widgetProps","commonPropertyFields","validationPropertyFields","reactionPropertyFields","dependencyPropertyFields","formLevelConfig","extractFormLevelConfig","handleValuesChange","allValues","changedFields","initial","flattenNodeForPropertyEditor","patch","diffPropertyPatch","next","_key","rest","handleRename","newKey","nodeKind"],"mappings":"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"}
@@ -44,10 +44,10 @@ const e = [
44
44
  label: "下拉选择(远程)",
45
45
  icon: "📡",
46
46
  category: "widget",
47
- widget: "selectWithRemote",
47
+ widget: "remoteSelect",
48
48
  createNode: () => ({
49
49
  type: "string",
50
- widget: "selectWithRemote",
50
+ widget: "remoteSelect",
51
51
  title: "下拉选择(远程)",
52
52
  remoteData: {
53
53
  url: "/api/options",
@@ -111,10 +111,10 @@ const e = [
111
111
  label: "多选下拉(远程)",
112
112
  icon: "📡",
113
113
  category: "widget",
114
- widget: "multiSelectWithRemote",
114
+ widget: "remoteMultiSelect",
115
115
  createNode: () => ({
116
116
  type: "array",
117
- widget: "multiSelectWithRemote",
117
+ widget: "remoteMultiSelect",
118
118
  title: "多选下拉(远程)",
119
119
  remoteData: {
120
120
  url: "/api/multi-options",
@@ -246,10 +246,10 @@ const e = [
246
246
  label: "自动完成(远程)",
247
247
  icon: "📡",
248
248
  category: "widget",
249
- widget: "autoCompleteWithRemote",
249
+ widget: "remoteAutoComplete",
250
250
  createNode: () => ({
251
251
  type: "string",
252
- widget: "autoCompleteWithRemote",
252
+ widget: "remoteAutoComplete",
253
253
  title: "自动完成(远程)",
254
254
  remoteData: {
255
255
  url: "/api/suggestions",
@@ -276,10 +276,10 @@ const e = [
276
276
  label: "级联选择(远程)",
277
277
  icon: "📡",
278
278
  category: "widget",
279
- widget: "cascaderWithRemote",
279
+ widget: "remoteCascader",
280
280
  createNode: () => ({
281
281
  type: "array",
282
- widget: "cascaderWithRemote",
282
+ widget: "remoteCascader",
283
283
  title: "级联选择(远程)",
284
284
  remoteData: {
285
285
  url: "/api/cascader/nodes",
@@ -311,10 +311,10 @@ const e = [
311
311
  label: "提及(远程)",
312
312
  icon: "📡",
313
313
  category: "widget",
314
- widget: "mentionsWithRemote",
314
+ widget: "remoteMentions",
315
315
  createNode: () => ({
316
316
  type: "string",
317
- widget: "mentionsWithRemote",
317
+ widget: "remoteMentions",
318
318
  title: "提及(远程)",
319
319
  remoteData: {
320
320
  url: "/api/users/suggestions",
@@ -506,6 +506,13 @@ const e = [
506
506
  category: "layout",
507
507
  layoutType: "space",
508
508
  createNode: () => ({ type: "space", properties: {} })
509
+ },
510
+ {
511
+ label: "透传容器",
512
+ icon: "📶",
513
+ category: "layout",
514
+ layoutType: "passThrough",
515
+ createNode: () => ({ type: "passThrough", properties: {} })
509
516
  }
510
517
  ];
511
518
  export {