@nocobase/client-v2 2.2.0-alpha.1 → 2.2.0-alpha.10

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 (334) hide show
  1. package/es/APIClient.d.ts +1 -3
  2. package/es/BaseApplication.d.ts +3 -0
  3. package/es/PluginSettingsManager.d.ts +33 -0
  4. package/es/RouteRepository.d.ts +29 -6
  5. package/es/RouterManager.d.ts +15 -0
  6. package/es/authRedirect.d.ts +1 -0
  7. package/es/collection-field-interface/CollectionFieldInterface.d.ts +1 -0
  8. package/es/collection-field-interface/CollectionFieldInterfaceManager.d.ts +1 -0
  9. package/es/components/category-tabs/SortableCategoryTabs.d.ts +55 -0
  10. package/es/components/category-tabs/index.d.ts +9 -0
  11. package/es/components/form/JsonTextArea.d.ts +2 -1
  12. package/es/components/form/ScanInput/useCodeScanner.d.ts +3 -2
  13. package/es/components/form/TypedVariableInput.d.ts +31 -5
  14. package/es/components/form/VariableJsonTextArea.d.ts +19 -0
  15. package/es/components/form/filter/CollectionFilter.d.ts +2 -0
  16. package/es/components/form/filter/CollectionFilterItem.d.ts +11 -1
  17. package/es/components/form/filter/CollectionFilterPanel.d.ts +2 -0
  18. package/es/components/form/filter/index.d.ts +2 -0
  19. package/es/components/form/filter/useFilterActionProps.d.ts +2 -0
  20. package/es/components/form/index.d.ts +1 -0
  21. package/es/components/index.d.ts +2 -0
  22. package/es/entry-actions/EntryActionManager.d.ts +24 -0
  23. package/es/entry-actions/index.d.ts +9 -0
  24. package/es/flow/actions/afterSuccess.d.ts +8 -1
  25. package/es/flow/actions/index.d.ts +2 -2
  26. package/es/flow/actions/linkageRules.d.ts +2 -0
  27. package/es/flow/admin-shell/BaseLayoutModel.d.ts +6 -0
  28. package/es/flow/admin-shell/BaseLayoutRouteCoordinator.d.ts +7 -0
  29. package/es/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.d.ts +2 -0
  30. package/es/flow/admin-shell/admin-layout/AdminLayoutMenuFlowUtils.d.ts +2 -1
  31. package/es/flow/admin-shell/admin-layout/AdminLayoutMenuModels.d.ts +3 -0
  32. package/es/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.d.ts +3 -2
  33. package/es/flow/admin-shell/admin-layout/AdminLayoutSlotModels.d.ts +5 -0
  34. package/es/flow/admin-shell/admin-layout/AppListRender.d.ts +2 -1
  35. package/es/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.d.ts +24 -0
  36. package/es/flow/admin-shell/admin-layout/index.d.ts +1 -0
  37. package/es/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.d.ts +6 -0
  38. package/es/flow/admin-shell/admin-layout/useApplications.d.ts +7 -2
  39. package/es/flow/components/FieldAssignExactDatePicker.d.ts +1 -0
  40. package/es/flow/components/FieldAssignRulesEditor.d.ts +3 -1
  41. package/es/flow/components/FieldAssignValueInput.d.ts +9 -0
  42. package/es/flow/components/FlowRoute.d.ts +2 -2
  43. package/es/flow/components/RunJSValueEditor.d.ts +1 -0
  44. package/es/flow/components/filter/FilterGroup.d.ts +1 -0
  45. package/es/flow/components/filter/VariableFilterItem.d.ts +6 -1
  46. package/es/flow/index.d.ts +1 -0
  47. package/es/flow/internal/registerDeviceTypeContext.d.ts +10 -0
  48. package/es/flow/models/base/ActionModelCore.d.ts +2 -0
  49. package/es/flow/models/base/BlockGridModel.d.ts +3 -0
  50. package/es/flow/models/base/GridModel.d.ts +1 -1
  51. package/es/flow/models/base/PageModel/PageModel.d.ts +12 -0
  52. package/es/flow/models/base/PageModel/PageModelTabBar.d.ts +22 -0
  53. package/es/flow/models/base/PageModel/PageTabModel.d.ts +12 -0
  54. package/es/flow/models/blocks/filter-form/FilterFormBlockModel.d.ts +5 -0
  55. package/es/flow/models/blocks/form/FormBlockModel.d.ts +4 -0
  56. package/es/flow/models/blocks/form/QuickEditFormModel.d.ts +17 -2
  57. package/es/flow/models/blocks/form/submitHandler.d.ts +1 -1
  58. package/es/flow/models/blocks/form/value-runtime/rules.d.ts +21 -0
  59. package/es/flow/models/blocks/form/value-runtime/runtime.d.ts +30 -0
  60. package/es/flow/models/blocks/form/value-runtime/types.d.ts +2 -2
  61. package/es/flow/models/blocks/js-block/JSBlock.d.ts +1 -0
  62. package/es/flow/models/blocks/table/TableActionsColumnModel.d.ts +1 -0
  63. package/es/flow/models/blocks/table/TableBlockModel.d.ts +1 -0
  64. package/es/flow/models/blocks/table/TableColumnModel.d.ts +1 -0
  65. package/es/flow/models/blocks/table/dragSort/dragSortHooks.d.ts +1 -1
  66. package/es/flow/models/blocks/table/dragSort/dragSortSettings.d.ts +2 -1
  67. package/es/flow/models/blocks/table/dragSort/dragSortUtils.d.ts +6 -4
  68. package/es/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.d.ts +2 -0
  69. package/es/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.d.ts +6 -0
  70. package/es/flow/models/fields/DateTimeFieldModel/dateLimit.d.ts +15 -7
  71. package/es/flow/resolveViewParamsToViewList.d.ts +1 -1
  72. package/es/flow/routeTransientInputArgs.d.ts +14 -0
  73. package/es/flow/utils/dataScopeRowSnapshot.d.ts +59 -0
  74. package/es/flow/utils/dateTimeDisplayProps.d.ts +49 -0
  75. package/es/flow/utils/formValueDeps.d.ts +32 -0
  76. package/es/flow-compat/FieldValidation.d.ts +2 -1
  77. package/es/flow-compat/fieldValidationConstants.d.ts +1 -1
  78. package/es/flow-compat/routeTypes.d.ts +1 -0
  79. package/es/index.d.ts +8 -1
  80. package/es/index.mjs +367 -181
  81. package/es/utils/getRouteRuntimeVersion.d.ts +23 -0
  82. package/es/utils/index.d.ts +1 -0
  83. package/es/utils/markdownSanitize.d.ts +11 -0
  84. package/lib/index.js +367 -181
  85. package/lib/locale/languageCodes.js +3 -1
  86. package/package.json +9 -7
  87. package/src/APIClient.ts +1 -10
  88. package/src/Application.tsx +4 -0
  89. package/src/BaseApplication.tsx +13 -6
  90. package/src/PluginSettingsManager.ts +53 -0
  91. package/src/RouteRepository.ts +151 -24
  92. package/src/RouterManager.tsx +142 -1
  93. package/src/__tests__/PluginSettingsManager.test.ts +13 -0
  94. package/src/__tests__/RouteRepository.test.ts +239 -0
  95. package/src/__tests__/RouterManager.test.ts +125 -0
  96. package/src/__tests__/app.test.tsx +73 -0
  97. package/src/__tests__/authRedirect.test.ts +17 -0
  98. package/src/__tests__/browserChecker.test.ts +61 -0
  99. package/src/__tests__/exports.test.ts +16 -0
  100. package/src/__tests__/getRouteRuntimeVersion.test.ts +68 -0
  101. package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +234 -2
  102. package/src/__tests__/plugin-manager.test.tsx +44 -2
  103. package/src/__tests__/settings-center.test.tsx +40 -1
  104. package/src/authRedirect.ts +38 -0
  105. package/src/collection-field-interface/CollectionFieldInterface.ts +1 -0
  106. package/src/collection-field-interface/CollectionFieldInterfaceManager.ts +1 -0
  107. package/src/collection-manager/field-configure.ts +1 -1
  108. package/src/collection-manager/field-validation.ts +1 -1
  109. package/src/collection-manager/interfaces/id.ts +1 -1
  110. package/src/collection-manager/interfaces/m2m.tsx +2 -2
  111. package/src/collection-manager/interfaces/m2o.tsx +2 -2
  112. package/src/collection-manager/interfaces/nanoid.ts +1 -1
  113. package/src/collection-manager/interfaces/o2m.tsx +2 -2
  114. package/src/collection-manager/interfaces/obo.tsx +2 -2
  115. package/src/collection-manager/interfaces/oho.tsx +2 -2
  116. package/src/collection-manager/interfaces/properties/index.ts +2 -2
  117. package/src/collection-manager/interfaces/uuid.ts +1 -1
  118. package/src/components/AppComponents.tsx +19 -3
  119. package/src/components/README.md +7 -1
  120. package/src/components/README.zh-CN.md +6 -1
  121. package/src/components/category-tabs/SortableCategoryTabs.tsx +210 -0
  122. package/src/components/category-tabs/index.ts +10 -0
  123. package/src/components/form/JsonTextArea.tsx +25 -11
  124. package/src/components/form/ScanInput/CodeScanner.tsx +79 -35
  125. package/src/components/form/ScanInput/__tests__/CodeScanner.test.tsx +101 -0
  126. package/src/components/form/ScanInput/__tests__/useCodeScanner.test.tsx +284 -11
  127. package/src/components/form/ScanInput/useCodeScanner.ts +332 -24
  128. package/src/components/form/TypedVariableInput.tsx +452 -101
  129. package/src/components/form/VariableJsonTextArea.tsx +175 -0
  130. package/src/components/form/__tests__/JsonTextArea.test.tsx +43 -0
  131. package/src/components/form/__tests__/TypedVariableInput.test.tsx +364 -12
  132. package/src/components/form/__tests__/VariableJsonTextArea.test.tsx +86 -0
  133. package/src/components/form/filter/CollectionFilter.tsx +4 -0
  134. package/src/components/form/filter/CollectionFilterItem.tsx +32 -7
  135. package/src/components/form/filter/CollectionFilterPanel.tsx +4 -0
  136. package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +38 -0
  137. package/src/components/form/filter/__tests__/useFilterActionProps.test.tsx +95 -0
  138. package/src/components/form/filter/index.ts +2 -0
  139. package/src/components/form/filter/useFilterActionProps.ts +37 -6
  140. package/src/components/form/index.tsx +1 -0
  141. package/src/components/index.ts +2 -0
  142. package/src/entry-actions/EntryActionManager.ts +76 -0
  143. package/src/entry-actions/index.ts +10 -0
  144. package/src/flow/FlowPage.tsx +38 -3
  145. package/src/flow/__tests__/FlowPage.test.tsx +201 -27
  146. package/src/flow/__tests__/FlowRoute.test.tsx +1181 -80
  147. package/src/flow/__tests__/PluginFlowEngine.test.ts +58 -0
  148. package/src/flow/__tests__/getKey.test.ts +7 -0
  149. package/src/flow/__tests__/resolveViewParamsToViewList.test.ts +34 -0
  150. package/src/flow/actions/__tests__/actionLinkageRules.forkProps.test.ts +115 -0
  151. package/src/flow/actions/__tests__/afterSuccess.test.ts +73 -0
  152. package/src/flow/actions/__tests__/dataScopeFilter.test.ts +120 -0
  153. package/src/flow/actions/__tests__/dataScopeFormValueClear.test.ts +1124 -0
  154. package/src/flow/actions/__tests__/fieldLinkageRules.scopeDepth.test.ts +150 -1
  155. package/src/flow/actions/__tests__/linkageAssignField.legacy.test.ts +135 -0
  156. package/src/flow/actions/__tests__/linkageRules.hiddenSync.restore.test.ts +19 -5
  157. package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +92 -0
  158. package/src/flow/actions/__tests__/linkageRules.tab.test.ts +171 -0
  159. package/src/flow/actions/__tests__/linkageRulesRefresh.test.ts +7 -3
  160. package/src/flow/actions/__tests__/openView.defineProps.route.test.tsx +164 -0
  161. package/src/flow/actions/__tests__/subFormFieldLinkageRules.inputArgs.test.ts +2 -2
  162. package/src/flow/actions/afterSuccess.tsx +142 -3
  163. package/src/flow/actions/customVariable.tsx +1 -2
  164. package/src/flow/actions/dataScopeFilter.ts +20 -1
  165. package/src/flow/actions/dateTimeFormat.tsx +42 -28
  166. package/src/flow/actions/index.ts +3 -1
  167. package/src/flow/actions/linkageRules.tsx +209 -47
  168. package/src/flow/actions/linkageRulesFormValueRefresh.ts +22 -130
  169. package/src/flow/actions/linkageRulesRefresh.tsx +2 -6
  170. package/src/flow/actions/openView.tsx +59 -5
  171. package/src/flow/actions/runjs.tsx +2 -14
  172. package/src/flow/actions/validation.tsx +62 -30
  173. package/src/flow/admin-shell/BaseLayoutModel.tsx +149 -3
  174. package/src/flow/admin-shell/BaseLayoutRouteCoordinator.ts +187 -42
  175. package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +1020 -110
  176. package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +74 -14
  177. package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.test.tsx +486 -0
  178. package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +64 -8
  179. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuFlowUtils.ts +5 -3
  180. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuModels.tsx +61 -9
  181. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.tsx +71 -8
  182. package/src/flow/admin-shell/admin-layout/AdminLayoutModel.tsx +1 -1
  183. package/src/flow/admin-shell/admin-layout/AdminLayoutSlotModels.tsx +23 -9
  184. package/src/flow/admin-shell/admin-layout/AppListRender.tsx +13 -2
  185. package/src/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.tsx +289 -0
  186. package/src/flow/admin-shell/admin-layout/HelpLite.tsx +1 -3
  187. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutComponent.test.tsx +435 -0
  188. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +99 -0
  189. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutModel.test.tsx +518 -2
  190. package/src/flow/admin-shell/admin-layout/__tests__/TopbarActionsBar.test.tsx +214 -2
  191. package/src/flow/admin-shell/admin-layout/index.ts +1 -0
  192. package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.test.ts +20 -0
  193. package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.ts +33 -5
  194. package/src/flow/admin-shell/admin-layout/useApplications.tsx +81 -12
  195. package/src/flow/common/Markdown/Display.tsx +14 -3
  196. package/src/flow/common/Markdown/Edit.tsx +19 -7
  197. package/src/flow/common/Markdown/style.ts +4 -0
  198. package/src/flow/components/BlockItemCard.tsx +2 -2
  199. package/src/flow/components/DefaultValue.tsx +1 -2
  200. package/src/flow/components/DynamicFlowsIcon.tsx +447 -126
  201. package/src/flow/components/FieldAssignExactDatePicker.tsx +25 -11
  202. package/src/flow/components/FieldAssignRulesEditor.tsx +128 -21
  203. package/src/flow/components/FieldAssignValueInput.tsx +91 -20
  204. package/src/flow/components/FlowRoute.tsx +256 -53
  205. package/src/flow/components/RunJSValueEditor.tsx +9 -1
  206. package/src/flow/components/__tests__/DynamicFlowsIcon.test.tsx +148 -2
  207. package/src/flow/components/__tests__/FieldAssignRulesEditor.test.tsx +508 -4
  208. package/src/flow/components/__tests__/FieldAssignValueInput.context.test.tsx +216 -0
  209. package/src/flow/components/__tests__/fieldAssignOptions.test.ts +151 -3
  210. package/src/flow/components/code-editor/__tests__/useCodeRunner.test.tsx +2 -17
  211. package/src/flow/components/code-editor/hooks/useCodeRunner.ts +2 -14
  212. package/src/flow/components/code-editor/runjsDiagnostics.ts +8 -45
  213. package/src/flow/components/fieldAssignOptions.ts +155 -27
  214. package/src/flow/components/filter/FilterGroup.tsx +33 -5
  215. package/src/flow/components/filter/VariableFilterItem.tsx +158 -10
  216. package/src/flow/components/filter/__tests__/FilterGroup.test.tsx +45 -0
  217. package/src/flow/components/filter/__tests__/VariableFilterItem.leftMetaTree.test.tsx +9 -0
  218. package/src/flow/components/filter/__tests__/VariableFilterItem.test.tsx +70 -1
  219. package/src/flow/flows/editMarkdownFlow.tsx +1 -1
  220. package/src/flow/getViewDiffAndUpdateHidden.tsx +1 -0
  221. package/src/flow/index.ts +4 -1
  222. package/src/flow/internal/components/Markdown/util.ts +2 -1
  223. package/src/flow/internal/registerDeviceTypeContext.ts +39 -0
  224. package/src/flow/internal/utils/operatorSchemaHelper.ts +15 -1
  225. package/src/flow/models/actions/JSActionModel.tsx +2 -7
  226. package/src/flow/models/actions/JSCollectionActionModel.tsx +2 -7
  227. package/src/flow/models/actions/JSItemActionModel.tsx +2 -7
  228. package/src/flow/models/actions/JSRecordActionModel.tsx +2 -7
  229. package/src/flow/models/base/ActionModel.tsx +21 -8
  230. package/src/flow/models/base/ActionModelCore.tsx +11 -4
  231. package/src/flow/models/base/BlockGridModel.tsx +26 -0
  232. package/src/flow/models/base/CollectionBlockModel.tsx +6 -2
  233. package/src/flow/models/base/GridModel.tsx +38 -7
  234. package/src/flow/models/base/PageModel/PageModel.tsx +387 -50
  235. package/src/flow/models/base/PageModel/PageModelTabBar.tsx +114 -0
  236. package/src/flow/models/base/PageModel/PageTabModel.tsx +249 -18
  237. package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +817 -13
  238. package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.module-isolation.test.tsx +130 -0
  239. package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.test.tsx +118 -0
  240. package/src/flow/models/base/PageModel/__tests__/PageTabModel.test.ts +1075 -7
  241. package/src/flow/models/base/__tests__/ActionModel.test.ts +83 -0
  242. package/src/flow/models/base/__tests__/ActionModelCore.render.test.tsx +37 -0
  243. package/src/flow/models/base/__tests__/BlockGridModel.selectSceneActivation.test.ts +124 -0
  244. package/src/flow/models/base/__tests__/CollectionBlockModel.addAppends.test.ts +41 -0
  245. package/src/flow/models/base/__tests__/GridModel.dragSnapshotContainer.test.ts +239 -1
  246. package/src/flow/models/base/__tests__/transformRowsToSingleColumn.test.ts +48 -0
  247. package/src/flow/models/blocks/filter-form/FilterFormBlockModel.tsx +59 -6
  248. package/src/flow/models/blocks/filter-form/FilterFormItemModel.tsx +27 -12
  249. package/src/flow/models/blocks/filter-form/FilterFormJSActionModel.tsx +2 -7
  250. package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.defineChildren.test.ts +36 -0
  251. package/src/flow/models/blocks/filter-form/__tests__/defaultValues.wiring.test.ts +143 -4
  252. package/src/flow/models/blocks/filter-form/fields/FilterFormCustomFieldModel.tsx +1 -1
  253. package/src/flow/models/blocks/filter-manager/flow-actions/__tests__/customizeFilterRender.test.tsx +56 -1
  254. package/src/flow/models/blocks/form/EditFormModel.tsx +1 -0
  255. package/src/flow/models/blocks/form/FormActionModel.tsx +1 -1
  256. package/src/flow/models/blocks/form/FormBlockModel.tsx +7 -0
  257. package/src/flow/models/blocks/form/JSFormActionModel.tsx +2 -7
  258. package/src/flow/models/blocks/form/QuickEditFormModel.tsx +189 -36
  259. package/src/flow/models/blocks/form/__tests__/FormBlockModel.test.tsx +17 -0
  260. package/src/flow/models/blocks/form/__tests__/QuickEditFormModel.quickEdit.test.ts +350 -2
  261. package/src/flow/models/blocks/form/__tests__/submitHandler.test.ts +54 -1
  262. package/src/flow/models/blocks/form/submitHandler.ts +17 -3
  263. package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +940 -75
  264. package/src/flow/models/blocks/form/value-runtime/rules.ts +445 -13
  265. package/src/flow/models/blocks/form/value-runtime/runtime.ts +348 -13
  266. package/src/flow/models/blocks/form/value-runtime/types.ts +2 -2
  267. package/src/flow/models/blocks/js-block/JSBlock.tsx +225 -9
  268. package/src/flow/models/blocks/js-block/__tests__/JSBlockModel.test.tsx +150 -0
  269. package/src/flow/models/blocks/table/JSColumnModel.tsx +1 -9
  270. package/src/flow/models/blocks/table/TableActionsColumnModel.tsx +38 -14
  271. package/src/flow/models/blocks/table/TableBlockModel.tsx +42 -19
  272. package/src/flow/models/blocks/table/TableColumnModel.tsx +72 -6
  273. package/src/flow/models/blocks/table/__tests__/TableActionsColumnModel.test.tsx +111 -1
  274. package/src/flow/models/blocks/table/__tests__/TableBlockModel.dragSort.test.ts +127 -0
  275. package/src/flow/models/blocks/table/__tests__/TableBlockModel.mobileSettingsButtons.test.tsx +78 -0
  276. package/src/flow/models/blocks/table/__tests__/TableBlockModel.quickEditRefresh.test.ts +12 -0
  277. package/src/flow/models/blocks/table/__tests__/TableBlockModel.rowSelection.test.tsx +1 -0
  278. package/src/flow/models/blocks/table/__tests__/TableColumnModel.test.tsx +243 -1
  279. package/src/flow/models/blocks/table/dragSort/dragSortHooks.tsx +28 -17
  280. package/src/flow/models/blocks/table/dragSort/dragSortSettings.ts +13 -6
  281. package/src/flow/models/blocks/table/dragSort/dragSortUtils.ts +15 -2
  282. package/src/flow/models/fields/AssociationFieldModel/AssociationFieldModel.tsx +1 -1
  283. package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/PopupSubTableFieldModel.tsx +31 -7
  284. package/src/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.tsx +61 -17
  285. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.tsx +141 -19
  286. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableField.tsx +13 -1
  287. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableColumnModel.rowRecord.test.ts +197 -0
  288. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableFieldModel.reset.test.ts +180 -0
  289. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.tsx +6 -4
  290. package/src/flow/models/fields/AssociationFieldModel/__tests__/AssociationFieldModel.updateAssociation.test.ts +72 -0
  291. package/src/flow/models/fields/AssociationFieldModel/__tests__/RecordPickerFieldModel.itemContext.test.ts +23 -0
  292. package/src/flow/models/fields/ClickableFieldModel.tsx +5 -0
  293. package/src/flow/models/fields/DateTimeFieldModel/__tests__/DateTimeNoTzFieldModel.dateLimit.test.tsx +149 -0
  294. package/src/flow/models/fields/DateTimeFieldModel/dateLimit.ts +149 -113
  295. package/src/flow/models/fields/DisplayDateTimeFieldModel.tsx +29 -1
  296. package/src/flow/models/fields/InputFieldModel.tsx +40 -2
  297. package/src/flow/models/fields/JSEditableFieldModel.tsx +2 -11
  298. package/src/flow/models/fields/JSFieldModel.tsx +2 -7
  299. package/src/flow/models/fields/JSItemModel.tsx +2 -14
  300. package/src/flow/models/fields/SelectFieldModel.tsx +6 -4
  301. package/src/flow/models/fields/TextareaFieldModel.tsx +72 -3
  302. package/src/flow/models/fields/VariableFieldFormModel.tsx +3 -3
  303. package/src/flow/models/fields/__tests__/DisplayDateTimeFieldModel.test.tsx +96 -0
  304. package/src/flow/models/fields/__tests__/InputFieldModel.test.tsx +117 -1
  305. package/src/flow/models/fields/__tests__/SelectFieldModel.test.tsx +43 -0
  306. package/src/flow/models/fields/__tests__/TextareaFieldModel.test.tsx +131 -0
  307. package/src/flow/models/fields/__tests__/VariableFieldFormModel.test.tsx +51 -0
  308. package/src/flow/models/fields/mobile-components/MobileLazySelect.tsx +20 -10
  309. package/src/flow/models/fields/mobile-components/MobileSelect.tsx +24 -12
  310. package/src/flow/models/topbar/TopbarActionModel.tsx +168 -10
  311. package/src/flow/resolveViewParamsToViewList.tsx +11 -3
  312. package/src/flow/routeTransientInputArgs.ts +27 -0
  313. package/src/flow/utils/__tests__/dateTimeFormat.test.ts +300 -0
  314. package/src/flow/utils/dataScopeFormValueClear.ts +219 -81
  315. package/src/flow/utils/dataScopeRowSnapshot.ts +616 -0
  316. package/src/flow/utils/dateTimeDisplayProps.ts +135 -0
  317. package/src/flow/utils/formValueDeps.ts +170 -0
  318. package/src/flow-compat/FieldValidation.tsx +122 -60
  319. package/src/flow-compat/Popover.tsx +43 -4
  320. package/src/flow-compat/__tests__/Popover.test.tsx +34 -0
  321. package/src/flow-compat/fieldValidationConstants.ts +1 -1
  322. package/src/flow-compat/routeTypes.ts +1 -0
  323. package/src/index.ts +14 -1
  324. package/src/layout-manager/__tests__/LayoutRoute.test.tsx +41 -1
  325. package/src/locale/languageCodes.ts +3 -1
  326. package/src/nocobase-buildin-plugin/index.tsx +63 -15
  327. package/src/settings-center/AdminSettingsLayout.tsx +10 -2
  328. package/src/settings-center/SystemSettingsPage.tsx +1 -2
  329. package/src/settings-center/plugin-manager/PluginCard.tsx +2 -2
  330. package/src/settings-center/plugin-manager/index.tsx +3 -0
  331. package/src/settings-center/utils.tsx +0 -6
  332. package/src/utils/getRouteRuntimeVersion.ts +185 -0
  333. package/src/utils/index.tsx +1 -0
  334. package/src/utils/markdownSanitize.ts +88 -0
@@ -48,6 +48,306 @@ describe('dateTimeFormat', () => {
48
48
  });
49
49
  });
50
50
 
51
+ it('uses the association title field when deciding the format schema', () => {
52
+ const ctx = {
53
+ model: {
54
+ props: {
55
+ titleField: 'shipmentsTime',
56
+ },
57
+ context: {
58
+ collectionField: {
59
+ type: 'belongsTo',
60
+ targetCollection: {
61
+ getField: (name) =>
62
+ name === 'shipmentsTime'
63
+ ? {
64
+ type: 'time',
65
+ interface: 'time',
66
+ }
67
+ : null,
68
+ },
69
+ },
70
+ },
71
+ },
72
+ };
73
+
74
+ expect(Object.keys(dateTimeFormat.uiSchema(ctx))).toEqual(['timeFormat']);
75
+ });
76
+
77
+ it('saves association title time field format as a time format', () => {
78
+ const setProps = vi.fn();
79
+ const ctx = {
80
+ model: {
81
+ props: {
82
+ titleField: 'shipmentsTime',
83
+ },
84
+ context: {
85
+ collectionField: {
86
+ type: 'belongsTo',
87
+ targetCollection: {
88
+ getField: (name) =>
89
+ name === 'shipmentsTime'
90
+ ? {
91
+ type: 'time',
92
+ interface: 'time',
93
+ }
94
+ : null,
95
+ },
96
+ },
97
+ },
98
+ setProps,
99
+ },
100
+ };
101
+
102
+ dateTimeFormat.handler(ctx, { timeFormat: 'hh:mm:ss a' });
103
+
104
+ expect(setProps).toHaveBeenCalledWith({
105
+ timeFormat: 'hh:mm:ss a',
106
+ format: 'hh:mm:ss a',
107
+ });
108
+ });
109
+
110
+ it('applies and persists date time format params when settings are saved', async () => {
111
+ const setProps = vi.fn();
112
+ const save = vi.fn();
113
+ const ctx = {
114
+ model: {
115
+ props: {
116
+ titleField: 'shipmentsDatetime',
117
+ },
118
+ context: {
119
+ collectionField: {
120
+ type: 'belongsTo',
121
+ targetCollection: {
122
+ getField: (name) =>
123
+ name === 'shipmentsDatetime'
124
+ ? {
125
+ type: 'datetime',
126
+ interface: 'datetime',
127
+ }
128
+ : null,
129
+ },
130
+ },
131
+ },
132
+ setProps,
133
+ save,
134
+ },
135
+ };
136
+
137
+ await dateTimeFormat.beforeParamsSave(ctx, {
138
+ picker: 'date',
139
+ dateFormat: 'YYYY-MM-DD',
140
+ showTime: true,
141
+ timeFormat: 'hh:mm:ss a',
142
+ });
143
+
144
+ expect(setProps).toHaveBeenCalledWith({
145
+ picker: 'date',
146
+ dateFormat: 'YYYY-MM-DD',
147
+ showTime: true,
148
+ timeFormat: 'hh:mm:ss a',
149
+ format: 'YYYY-MM-DD hh:mm:ss a',
150
+ });
151
+ expect(save).toHaveBeenCalled();
152
+ });
153
+
154
+ it('syncs table association column props when title date time format settings are saved', async () => {
155
+ const setProps = vi.fn();
156
+ const save = vi.fn();
157
+ const setParentProps = vi.fn();
158
+ const model = {
159
+ props: {
160
+ titleField: 'shipmentsDatetime',
161
+ },
162
+ context: {
163
+ collectionField: {
164
+ type: 'belongsTo',
165
+ targetCollection: {
166
+ getField: (name) =>
167
+ name === 'shipmentsDatetime'
168
+ ? {
169
+ type: 'datetime',
170
+ interface: 'datetime',
171
+ }
172
+ : null,
173
+ },
174
+ },
175
+ },
176
+ setProps,
177
+ save,
178
+ parent: {
179
+ use: 'TableColumnModel',
180
+ collectionField: {
181
+ isAssociationField: () => true,
182
+ },
183
+ setProps: setParentProps,
184
+ },
185
+ };
186
+ model.parent['subModels'] = {
187
+ field: model,
188
+ };
189
+
190
+ await dateTimeFormat.beforeParamsSave(
191
+ { model },
192
+ {
193
+ picker: 'date',
194
+ dateFormat: 'YYYY-MM-DD',
195
+ showTime: true,
196
+ timeFormat: 'hh:mm:ss a',
197
+ },
198
+ );
199
+
200
+ expect(setParentProps).toHaveBeenCalledWith({
201
+ picker: 'date',
202
+ dateFormat: 'YYYY-MM-DD',
203
+ showTime: true,
204
+ timeFormat: 'hh:mm:ss a',
205
+ format: 'YYYY-MM-DD hh:mm:ss a',
206
+ });
207
+ expect(save).toHaveBeenCalled();
208
+ });
209
+
210
+ it('syncs ordinary table column props when date time format settings are saved', async () => {
211
+ const setProps = vi.fn();
212
+ const save = vi.fn();
213
+ const setParentProps = vi.fn();
214
+ const model = {
215
+ context: {
216
+ collectionField: {
217
+ type: 'datetime',
218
+ interface: 'datetime',
219
+ },
220
+ },
221
+ setProps,
222
+ save,
223
+ parent: {
224
+ use: 'TableColumnModel',
225
+ setProps: setParentProps,
226
+ },
227
+ };
228
+ model.parent['subModels'] = {
229
+ field: model,
230
+ };
231
+
232
+ await dateTimeFormat.beforeParamsSave(
233
+ { model },
234
+ {
235
+ picker: 'date',
236
+ dateFormat: 'YYYY-MM-DD',
237
+ showTime: true,
238
+ timeFormat: 'HH:mm:ss',
239
+ },
240
+ );
241
+
242
+ expect(setParentProps).toHaveBeenCalledWith({
243
+ picker: 'date',
244
+ dateFormat: 'YYYY-MM-DD',
245
+ showTime: true,
246
+ timeFormat: 'HH:mm:ss',
247
+ format: 'YYYY-MM-DD HH:mm:ss',
248
+ });
249
+ expect(save).toHaveBeenCalled();
250
+ });
251
+
252
+ it('hides time format for association title date-only fields', () => {
253
+ const ctx = {
254
+ model: {
255
+ props: {
256
+ titleField: 'shipmentsDateOnly',
257
+ showTime: true,
258
+ },
259
+ context: {
260
+ collectionField: {
261
+ type: 'belongsTo',
262
+ targetCollection: {
263
+ getField: (name) =>
264
+ name === 'shipmentsDateOnly'
265
+ ? {
266
+ type: 'dateOnly',
267
+ interface: 'date',
268
+ getComponentProps: () => ({
269
+ dateOnly: true,
270
+ showTime: false,
271
+ }),
272
+ }
273
+ : null,
274
+ },
275
+ },
276
+ },
277
+ },
278
+ };
279
+ const schema = dateTimeFormat.uiSchema(ctx);
280
+ const timeFormatField: any = schema.timeFormat;
281
+ const showTimeField: any = schema.showTime;
282
+ const timeFormatState = {
283
+ hidden: false,
284
+ form: {
285
+ values: {
286
+ picker: 'date',
287
+ showTime: true,
288
+ },
289
+ },
290
+ };
291
+ const showTimeState = {
292
+ hidden: false,
293
+ value: true,
294
+ form: {
295
+ values: {
296
+ picker: 'date',
297
+ },
298
+ },
299
+ };
300
+
301
+ timeFormatField['x-reactions'][0](timeFormatState);
302
+ showTimeField['x-reactions'][1](showTimeState);
303
+
304
+ expect(timeFormatState.hidden).toBe(true);
305
+ expect(showTimeState.hidden).toBe(true);
306
+ expect(showTimeState.value).toBe(false);
307
+ expect(dateTimeFormat.defaultParams(ctx)).toMatchObject({
308
+ showTime: false,
309
+ });
310
+ });
311
+
312
+ it('saves association title date-only field format without time even when params contain showTime', () => {
313
+ const setProps = vi.fn();
314
+ const ctx = {
315
+ model: {
316
+ props: {
317
+ titleField: 'shipmentsDateOnly',
318
+ },
319
+ context: {
320
+ collectionField: {
321
+ type: 'belongsTo',
322
+ targetCollection: {
323
+ getField: (name) =>
324
+ name === 'shipmentsDateOnly'
325
+ ? {
326
+ type: 'dateOnly',
327
+ interface: 'date',
328
+ }
329
+ : null,
330
+ },
331
+ },
332
+ },
333
+ setProps,
334
+ },
335
+ };
336
+
337
+ dateTimeFormat.handler(ctx, {
338
+ dateFormat: 'YYYY-MM-DD',
339
+ showTime: true,
340
+ timeFormat: 'HH:mm:ss',
341
+ });
342
+
343
+ expect(setProps).toHaveBeenCalledWith({
344
+ dateFormat: 'YYYY-MM-DD',
345
+ showTime: false,
346
+ timeFormat: 'HH:mm:ss',
347
+ format: 'YYYY-MM-DD',
348
+ });
349
+ });
350
+
51
351
  it('uses format as the default time format when timeFormat is missing', () => {
52
352
  const ctx = {
53
353
  model: {
@@ -8,51 +8,188 @@
8
8
  */
9
9
 
10
10
  import type { FlowContext, FlowModel } from '@nocobase/flow-engine';
11
- import _ from 'lodash';
12
- import { namePathToPathKey, pathKeyToNamePath } from '../models/blocks/form/value-runtime/path';
11
+ import { namePathToPathKey } from '../models/blocks/form/value-runtime/path';
13
12
  import { collectStaticDepsFromTemplateValue, type DepCollector } from '../models/blocks/form/value-runtime/deps';
14
-
15
- type NamePath = Array<string | number>;
16
-
17
- type DataScopeClearDeps = {
18
- wildcard: boolean;
19
- valuePaths: NamePath[];
20
- };
13
+ import {
14
+ buildItemListRootPath,
15
+ buildItemRowPath,
16
+ findFormValueChangeSource,
17
+ getChangedPathsFromPayload,
18
+ isNamePathPrefix,
19
+ isSameNamePath,
20
+ parseFieldIndexEntries,
21
+ parsePathKey,
22
+ type NamePath,
23
+ } from './formValueDeps';
24
+ import {
25
+ applyDataScopeFieldIndexTargetKeys,
26
+ buildDepsSnapshot,
27
+ createDataScopeRowScope,
28
+ getDepsChangeStatus,
29
+ type DataScopeClearDeps,
30
+ type DataScopeClearSnapshot,
31
+ type DataScopeStructuralPath,
32
+ type DataScopeTriggerPath,
33
+ type DataScopeValuePath,
34
+ } from './dataScopeRowSnapshot';
21
35
 
22
36
  type DataScopeClearBinding = {
23
37
  signature: string;
38
+ snapshot: DataScopeClearSnapshot | null;
24
39
  dispose: () => void;
25
40
  };
26
41
 
27
42
  const FORM_VALUES_CHANGE_EVENT = 'formValuesChange';
28
43
  const DATA_SCOPE_CLEAR_BINDINGS_KEY = '__formValueDrivenDataScopeClearBindings';
29
44
 
30
- function dedupeNamePaths(paths: NamePath[]) {
31
- const byKey = new Map<string, NamePath>();
45
+ function dedupeValuePaths(paths: DataScopeValuePath[]) {
46
+ const byKey = new Map<string, DataScopeValuePath>();
32
47
  for (const path of paths) {
33
- if (!path?.length) continue;
34
- byKey.set(namePathToPathKey(path), path);
48
+ if (!path?.path?.length) continue;
49
+ byKey.set(namePathToPathKey(path.path), path);
35
50
  }
36
51
  return Array.from(byKey.values());
37
52
  }
38
53
 
39
- function isNamePathPrefix(prefix: NamePath, path: NamePath) {
40
- if (prefix.length > path.length) return false;
41
- return prefix.every((seg, index) => seg === path[index]);
42
- }
43
-
44
- function minimizeValueNamePaths(paths: NamePath[]) {
45
- const deduped = dedupeNamePaths(paths);
54
+ function minimizeValuePaths(paths: DataScopeValuePath[]) {
55
+ const deduped = dedupeValuePaths(paths);
46
56
  return deduped.filter((path, index) => {
47
- return !deduped.some((other, otherIndex) => otherIndex !== index && isNamePathPrefix(path, other));
57
+ return !deduped.some((other, otherIndex) => otherIndex !== index && isNamePathPrefix(path.path, other.path));
48
58
  });
49
59
  }
50
60
 
51
- function collectDataScopeClearDeps(params: any): DataScopeClearDeps {
61
+ function dedupeStructuralPaths(paths: DataScopeStructuralPath[]) {
62
+ const byKey = new Map<string, DataScopeStructuralPath>();
63
+ for (const path of paths) {
64
+ if (!path?.path?.length) continue;
65
+ byKey.set(`${path.kind}:${namePathToPathKey(path.path)}`, path);
66
+ }
67
+ return Array.from(byKey.values());
68
+ }
69
+
70
+ function dedupeTriggerPaths(paths: DataScopeTriggerPath[]) {
71
+ const byKey = new Map<string, DataScopeTriggerPath>();
72
+ for (const path of paths) {
73
+ if (!path?.path?.length) continue;
74
+ byKey.set(`${path.includeChildren ? 'children' : 'exact'}:${namePathToPathKey(path.path)}`, path);
75
+ }
76
+ return Array.from(byKey.values());
77
+ }
78
+
79
+ function emptyDeps(): DataScopeClearDeps {
80
+ return { wildcard: false, valuePaths: [], structuralPaths: [], triggerPaths: [] };
81
+ }
82
+
83
+ function wildcardDeps(): DataScopeClearDeps {
84
+ return { wildcard: true, valuePaths: [], structuralPaths: [], triggerPaths: [] };
85
+ }
86
+
87
+ function resolveRootItemDependencyPath(cursor: NamePath): DataScopeClearDeps {
88
+ const head = cursor[0];
89
+ if (head === 'value') {
90
+ const rootValuePath = cursor.slice(1);
91
+ return rootValuePath.length
92
+ ? { wildcard: false, valuePaths: [{ path: rootValuePath }], structuralPaths: [], triggerPaths: [] }
93
+ : wildcardDeps();
94
+ }
95
+
96
+ if (head === '__is_new__' || head === '__is_stored__') {
97
+ return { wildcard: false, valuePaths: [{ path: [head] }], structuralPaths: [], triggerPaths: [] };
98
+ }
99
+
100
+ return emptyDeps();
101
+ }
102
+
103
+ function resolveItemDependencyPath(ctx: FlowContext, depPath: NamePath): DataScopeClearDeps {
104
+ const entries = applyDataScopeFieldIndexTargetKeys(
105
+ ctx,
106
+ parseFieldIndexEntries((ctx.model as any)?.context?.fieldIndex ?? (ctx as any)?.fieldIndex),
107
+ );
108
+
109
+ let parentDepth = 0;
110
+ let cursor = [...depPath];
111
+ while (cursor[0] === 'parentItem') {
112
+ parentDepth += 1;
113
+ cursor = cursor.slice(1);
114
+ }
115
+
116
+ const head = cursor[0];
117
+ if (!head) {
118
+ return wildcardDeps();
119
+ }
120
+
121
+ if (!entries.length) {
122
+ return parentDepth === 0 ? resolveRootItemDependencyPath(cursor) : emptyDeps();
123
+ }
124
+
125
+ if (parentDepth === entries.length) {
126
+ return resolveRootItemDependencyPath(cursor);
127
+ }
128
+
129
+ if (parentDepth > entries.length) {
130
+ return wildcardDeps();
131
+ }
132
+
133
+ if (head === 'value') {
134
+ const rowPath = buildItemRowPath(entries, parentDepth);
135
+ if (!rowPath) return wildcardDeps();
136
+ const listRootPath = buildItemListRootPath(entries, parentDepth);
137
+ const tailPath = cursor.slice(1);
138
+ return {
139
+ wildcard: false,
140
+ valuePaths: [
141
+ {
142
+ path: [...rowPath, ...tailPath],
143
+ rowScope: createDataScopeRowScope(entries, parentDepth, tailPath),
144
+ },
145
+ ],
146
+ structuralPaths: [],
147
+ triggerPaths: [
148
+ { path: rowPath, includeChildren: true },
149
+ ...(listRootPath ? [{ path: listRootPath, includeChildren: false }] : []),
150
+ ],
151
+ };
152
+ }
153
+
154
+ if (head === 'index' || head === 'length') {
155
+ const listRootPath = buildItemListRootPath(entries, parentDepth);
156
+ if (!listRootPath) return wildcardDeps();
157
+ return {
158
+ wildcard: false,
159
+ valuePaths: [],
160
+ structuralPaths: [
161
+ { path: listRootPath, kind: head, rowScope: createDataScopeRowScope(entries, parentDepth, []) },
162
+ ],
163
+ triggerPaths: [{ path: listRootPath, includeChildren: false }],
164
+ };
165
+ }
166
+
167
+ if (head === '__is_new__' || head === '__is_stored__') {
168
+ const rowPath = buildItemRowPath(entries, parentDepth);
169
+ if (!rowPath) return wildcardDeps();
170
+ return {
171
+ wildcard: false,
172
+ valuePaths: [
173
+ {
174
+ path: [...rowPath, head],
175
+ rowScope: createDataScopeRowScope(entries, parentDepth, [head]),
176
+ },
177
+ ],
178
+ structuralPaths: [],
179
+ triggerPaths: [{ path: rowPath, includeChildren: true }],
180
+ };
181
+ }
182
+
183
+ return wildcardDeps();
184
+ }
185
+
186
+ function collectDataScopeClearDeps(ctx: FlowContext, params: any): DataScopeClearDeps {
52
187
  const collector: DepCollector = { deps: new Set(), wildcard: false };
53
188
  collectStaticDepsFromTemplateValue(params, collector);
54
189
 
55
- const valuePaths: NamePath[] = [];
190
+ const valuePaths: DataScopeValuePath[] = [];
191
+ const structuralPaths: DataScopeStructuralPath[] = [];
192
+ const triggerPaths: DataScopeTriggerPath[] = [];
56
193
  let wildcard = collector.wildcard;
57
194
 
58
195
  for (const depKey of collector.deps) {
@@ -61,6 +198,15 @@ function collectDataScopeClearDeps(params: any): DataScopeClearDeps {
61
198
  continue;
62
199
  }
63
200
  if (!depKey.startsWith('fv:')) {
201
+ if (depKey === 'ctx:item' || depKey.startsWith('ctx:item:')) {
202
+ const subPath = depKey === 'ctx:item' ? '' : depKey.slice('ctx:item:'.length);
203
+ const depPath = subPath ? parsePathKey(subPath) : [];
204
+ const resolved = resolveItemDependencyPath(ctx, depPath);
205
+ wildcard ||= resolved.wildcard;
206
+ valuePaths.push(...resolved.valuePaths);
207
+ structuralPaths.push(...resolved.structuralPaths);
208
+ triggerPaths.push(...resolved.triggerPaths);
209
+ }
64
210
  continue;
65
211
  }
66
212
  const inner = depKey.slice('fv:'.length);
@@ -68,17 +214,19 @@ function collectDataScopeClearDeps(params: any): DataScopeClearDeps {
68
214
  wildcard = true;
69
215
  continue;
70
216
  }
71
- valuePaths.push(pathKeyToNamePath(inner));
217
+ valuePaths.push({ path: parsePathKey(inner) });
72
218
  }
73
219
 
74
220
  return {
75
221
  wildcard,
76
- valuePaths: minimizeValueNamePaths(valuePaths),
222
+ valuePaths: minimizeValuePaths(valuePaths),
223
+ structuralPaths: dedupeStructuralPaths(structuralPaths),
224
+ triggerPaths: dedupeTriggerPaths(triggerPaths),
77
225
  };
78
226
  }
79
227
 
80
228
  function hasDeps(deps: DataScopeClearDeps) {
81
- return deps.wildcard || deps.valuePaths.length > 0;
229
+ return deps.wildcard || deps.valuePaths.length > 0 || deps.structuralPaths.length > 0 || deps.triggerPaths.length > 0;
82
230
  }
83
231
 
84
232
  function hasModelValue(model: any) {
@@ -88,36 +236,6 @@ function hasModelValue(model: any) {
88
236
  return true;
89
237
  }
90
238
 
91
- function getChangedPathsFromPayload(payload: any): NamePath[] {
92
- const rawChangedPaths = Array.isArray(payload?.changedPaths) ? payload.changedPaths : [];
93
- const out: NamePath[] = [];
94
-
95
- for (const path of rawChangedPaths) {
96
- if (Array.isArray(path)) {
97
- const segs = path.filter((seg) => typeof seg === 'string' || typeof seg === 'number') as NamePath;
98
- if (segs.length) out.push(segs);
99
- continue;
100
- }
101
- if (typeof path === 'string' && path) {
102
- out.push(pathKeyToNamePath(path));
103
- }
104
- }
105
-
106
- if (out.length) {
107
- return out;
108
- }
109
-
110
- const changedValues = payload?.changedValues;
111
- if (changedValues && typeof changedValues === 'object' && !Array.isArray(changedValues)) {
112
- for (const key of Object.keys(changedValues)) {
113
- const namePath = pathKeyToNamePath(key);
114
- if (namePath.length) out.push(namePath);
115
- }
116
- }
117
-
118
- return out;
119
- }
120
-
121
239
  function depsMatchPayload(deps: DataScopeClearDeps, payload: any) {
122
240
  if (!hasDeps(deps)) return false;
123
241
  if (deps.wildcard) return true;
@@ -127,7 +245,28 @@ function depsMatchPayload(deps: DataScopeClearDeps, payload: any) {
127
245
 
128
246
  for (const changedPath of changedPaths) {
129
247
  for (const depPath of deps.valuePaths) {
130
- if (isNamePathPrefix(depPath, changedPath) || isNamePathPrefix(changedPath, depPath)) {
248
+ if (isNamePathPrefix(depPath.path, changedPath) || isNamePathPrefix(changedPath, depPath.path)) {
249
+ return true;
250
+ }
251
+ }
252
+
253
+ for (const depPath of deps.structuralPaths) {
254
+ if (isSameNamePath(depPath.path, changedPath)) {
255
+ return true;
256
+ }
257
+ if (isNamePathPrefix(changedPath, depPath.path)) {
258
+ return true;
259
+ }
260
+ }
261
+
262
+ for (const depPath of deps.triggerPaths) {
263
+ if (
264
+ depPath.includeChildren &&
265
+ (isNamePathPrefix(depPath.path, changedPath) || isNamePathPrefix(changedPath, depPath.path))
266
+ ) {
267
+ return true;
268
+ }
269
+ if (!depPath.includeChildren && isSameNamePath(depPath.path, changedPath)) {
131
270
  return true;
132
271
  }
133
272
  }
@@ -136,11 +275,17 @@ function depsMatchPayload(deps: DataScopeClearDeps, payload: any) {
136
275
  }
137
276
 
138
277
  function getDepsSignature(deps: DataScopeClearDeps, formBlock: any) {
139
- const toKeys = (paths: NamePath[]) => paths.map((path) => namePathToPathKey(path)).sort();
278
+ const toKeys = (paths: DataScopeValuePath[]) => paths.map((path) => namePathToPathKey(path.path)).sort();
279
+ const toStructuralKeys = (paths: DataScopeStructuralPath[]) =>
280
+ paths.map((path) => `${path.kind}:${namePathToPathKey(path.path)}`).sort();
140
281
  return JSON.stringify({
141
282
  formBlockUid: formBlock?.uid,
142
283
  wildcard: deps.wildcard,
143
284
  valuePaths: toKeys(deps.valuePaths),
285
+ structuralPaths: toStructuralKeys(deps.structuralPaths),
286
+ triggerPaths: deps.triggerPaths
287
+ .map((path) => `${path.includeChildren ? 'children' : 'exact'}:${namePathToPathKey(path.path)}`)
288
+ .sort(),
144
289
  });
145
290
  }
146
291
 
@@ -148,28 +293,8 @@ function getBindings(model: any): Map<string, DataScopeClearBinding> {
148
293
  return (model[DATA_SCOPE_CLEAR_BINDINGS_KEY] ||= new Map<string, DataScopeClearBinding>());
149
294
  }
150
295
 
151
- function isFormBlock(model: any) {
152
- if (!model || typeof model !== 'object') return false;
153
- if (!model.emitter || typeof model.emitter.on !== 'function' || typeof model.emitter.off !== 'function') return false;
154
- return !!model.formValueRuntime || !!model.context?.form || typeof model.context?.setFormValues === 'function';
155
- }
156
-
157
296
  function findFormBlock(ctx: FlowContext): any | null {
158
- const candidates: any[] = [];
159
- const push = (model: any) => {
160
- if (model && !candidates.includes(model)) candidates.push(model);
161
- };
162
-
163
- push((ctx.model as any)?.context?.blockModel);
164
- push(ctx.model);
165
-
166
- let cursor: any = (ctx.model as any)?.parent;
167
- while (cursor) {
168
- push(cursor);
169
- cursor = cursor?.parent;
170
- }
171
-
172
- return candidates.find(isFormBlock) || null;
297
+ return findFormValueChangeSource(ctx) as any;
173
298
  }
174
299
 
175
300
  function clearModelValue(model: any) {
@@ -207,7 +332,7 @@ export function ensureFormValueDrivenDataScopeClear(ctx: FlowContext, params: an
207
332
 
208
333
  const stepKey = 'dataScope';
209
334
  const bindingKey = `${flowKey}:${stepKey}`;
210
- const deps = collectDataScopeClearDeps(params);
335
+ const deps = collectDataScopeClearDeps(ctx, params);
211
336
  if (!hasDeps(deps)) {
212
337
  disposeBinding(model, bindingKey);
213
338
  return;
@@ -233,6 +358,7 @@ export function ensureFormValueDrivenDataScopeClear(ctx: FlowContext, params: an
233
358
 
234
359
  const binding: DataScopeClearBinding = {
235
360
  signature,
361
+ snapshot: buildDepsSnapshot(deps, formBlock),
236
362
  dispose: () => {},
237
363
  };
238
364
 
@@ -251,7 +377,19 @@ export function ensureFormValueDrivenDataScopeClear(ctx: FlowContext, params: an
251
377
  return;
252
378
  }
253
379
 
254
- if (!hasModelValue(model) || !depsMatchPayload(deps, payload)) {
380
+ if (!depsMatchPayload(deps, payload)) {
381
+ return;
382
+ }
383
+
384
+ const changeStatus = getDepsChangeStatus(deps, formBlock, payload, binding.snapshot);
385
+ if (changeStatus.snapshot?.complete) {
386
+ binding.snapshot = changeStatus.snapshot;
387
+ }
388
+ if (changeStatus.status === 'unchanged') {
389
+ return;
390
+ }
391
+
392
+ if (!hasModelValue(model)) {
255
393
  return;
256
394
  }
257
395