@nocobase/flow-engine 2.0.0-alpha.4 → 2.0.0-alpha.41

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 (466) hide show
  1. package/lib/BlockScopedFlowEngine.d.ts +23 -0
  2. package/lib/BlockScopedFlowEngine.js +90 -0
  3. package/lib/FlowContextProvider.d.ts +2 -2
  4. package/lib/FlowContextProvider.js +3 -3
  5. package/lib/FlowDefinition.d.ts +4 -2
  6. package/lib/JSRunner.js +3 -0
  7. package/lib/ViewScopedFlowEngine.d.ts +1 -1
  8. package/lib/ViewScopedFlowEngine.js +12 -0
  9. package/lib/acl/Acl.d.ts +1 -0
  10. package/lib/acl/Acl.js +11 -0
  11. package/lib/components/FieldModelRenderer.js +14 -6
  12. package/lib/components/FieldSkeleton.d.ts +10 -0
  13. package/lib/components/FieldSkeleton.js +64 -0
  14. package/lib/components/FlowContextSelector.js +7 -2
  15. package/lib/components/FlowModelRenderer.d.ts +3 -6
  16. package/lib/components/FlowModelRenderer.js +16 -47
  17. package/lib/components/FormItem.js +5 -1
  18. package/lib/components/MobilePopup.d.ts +20 -0
  19. package/lib/components/MobilePopup.js +102 -0
  20. package/lib/components/MobilePopup.style.d.ts +17 -0
  21. package/lib/components/MobilePopup.style.js +186 -0
  22. package/lib/components/index.d.ts +1 -0
  23. package/lib/components/index.js +3 -1
  24. package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +2 -2
  25. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +17 -5
  26. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +2 -2
  27. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +2 -2
  28. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +35 -6
  29. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +7 -1
  30. package/lib/components/variables/VariableInput.js +19 -5
  31. package/lib/components/variables/VariableTag.js +43 -2
  32. package/lib/components/variables/types.d.ts +2 -0
  33. package/lib/data-source/index.d.ts +15 -4
  34. package/lib/data-source/index.js +42 -13
  35. package/lib/data-source/sortCollectionsByInherits.d.ts +10 -0
  36. package/lib/data-source/sortCollectionsByInherits.js +71 -0
  37. package/lib/emitter.d.ts +6 -0
  38. package/lib/emitter.js +12 -0
  39. package/lib/executor/FlowExecutor.d.ts +4 -5
  40. package/lib/executor/FlowExecutor.js +168 -99
  41. package/lib/flow-registry/GlobalFlowRegistry.d.ts +1 -0
  42. package/lib/flow-registry/GlobalFlowRegistry.js +3 -0
  43. package/lib/flow-registry/InstanceFlowRegistry.d.ts +1 -0
  44. package/lib/flow-registry/InstanceFlowRegistry.js +3 -0
  45. package/lib/flowContext.d.ts +37 -5
  46. package/lib/flowContext.js +224 -87
  47. package/lib/flowEngine.d.ts +24 -1
  48. package/lib/flowEngine.js +81 -8
  49. package/lib/flowSettings.d.ts +2 -1
  50. package/lib/flowSettings.js +16 -8
  51. package/lib/hooks/useApplyAutoFlows.js +2 -1
  52. package/lib/index.d.ts +7 -1
  53. package/lib/index.js +32 -3
  54. package/lib/locale/en-US.json +4 -2
  55. package/lib/locale/index.d.ts +4 -0
  56. package/lib/locale/zh-CN.json +4 -2
  57. package/lib/models/CollectionFieldModel.d.ts +3 -0
  58. package/lib/models/CollectionFieldModel.js +52 -6
  59. package/lib/models/flowModel.d.ts +30 -29
  60. package/lib/models/flowModel.js +153 -100
  61. package/lib/models/forkFlowModel.d.ts +8 -4
  62. package/lib/models/forkFlowModel.js +38 -8
  63. package/lib/provider.d.ts +3 -1
  64. package/lib/provider.js +7 -5
  65. package/lib/resources/multiRecordResource.js +25 -1
  66. package/lib/resources/singleRecordResource.js +19 -1
  67. package/lib/resources/sqlResource.d.ts +1 -0
  68. package/lib/resources/sqlResource.js +20 -24
  69. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
  70. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +27 -20
  71. package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +1 -6
  72. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +46 -33
  73. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +1 -2
  74. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +14 -15
  75. package/lib/runjs-context/contexts/{LinkageRunJSContext.d.ts → JSColumnRunJSContext.d.ts} +6 -3
  76. package/lib/runjs-context/contexts/JSColumnRunJSContext.js +78 -0
  77. package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +1 -6
  78. package/lib/runjs-context/contexts/JSFieldRunJSContext.js +28 -24
  79. package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +1 -6
  80. package/lib/runjs-context/contexts/JSItemRunJSContext.js +24 -20
  81. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +1 -2
  82. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +16 -17
  83. package/lib/runjs-context/contexts/base.d.ts +9 -0
  84. package/lib/runjs-context/contexts/base.js +205 -0
  85. package/lib/runjs-context/helpers.d.ts +5 -2
  86. package/lib/runjs-context/helpers.js +36 -27
  87. package/lib/runjs-context/registry.d.ts +7 -4
  88. package/lib/runjs-context/registry.js +10 -42
  89. package/lib/runjs-context/setup.d.ts +9 -0
  90. package/lib/runjs-context/setup.js +82 -0
  91. package/lib/runjs-context/snippets/global/{copy-record-json.snippet.js → api-request.snippet.js} +25 -10
  92. package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
  93. package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.js → import-esm.snippet.js} +26 -12
  94. package/lib/runjs-context/snippets/global/message-error.snippet.js +6 -0
  95. package/lib/runjs-context/snippets/global/message-success.snippet.js +6 -0
  96. package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +3 -8
  97. package/lib/runjs-context/snippets/global/notification-open.snippet.js +8 -1
  98. package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +10 -3
  99. package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +10 -3
  100. package/lib/runjs-context/snippets/global/query-selector.snippet.js +53 -0
  101. package/lib/runjs-context/snippets/global/require-amd.snippet.d.ts +11 -0
  102. package/lib/runjs-context/snippets/global/{requireAsync.snippet.js → require-amd.snippet.js} +16 -13
  103. package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +3 -8
  104. package/lib/runjs-context/snippets/global/window-open.snippet.js +8 -1
  105. package/lib/runjs-context/snippets/index.d.ts +14 -3
  106. package/lib/runjs-context/snippets/index.js +162 -40
  107. package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.d.ts +11 -0
  108. package/lib/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.js +11 -2
  109. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.d.ts +11 -0
  110. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +64 -0
  111. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.d.ts +11 -0
  112. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +99 -0
  113. package/lib/runjs-context/snippets/{libs → scene/block}/echarts-init.snippet.js +24 -7
  114. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.d.ts +11 -0
  115. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.js +65 -0
  116. package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.d.ts +11 -0
  117. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.js +17 -9
  118. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.d.ts +11 -0
  119. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +57 -0
  120. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.d.ts +11 -0
  121. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +71 -0
  122. package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.d.ts +11 -0
  123. package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.js → block/render-react-jsx.snippet.js} +26 -13
  124. package/lib/runjs-context/snippets/scene/block/render-react.snippet.d.ts +11 -0
  125. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.js +18 -17
  126. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.d.ts +11 -0
  127. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +95 -0
  128. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.d.ts +11 -0
  129. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +84 -0
  130. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.d.ts +11 -0
  131. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +60 -0
  132. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.d.ts +11 -0
  133. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +283 -0
  134. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.d.ts +11 -0
  135. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +124 -0
  136. package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.d.ts +11 -0
  137. package/lib/runjs-context/snippets/scene/{jsfield → detail}/color-by-value.snippet.js +13 -3
  138. package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.d.ts +11 -0
  139. package/lib/runjs-context/snippets/{global → scene/detail}/copy-to-clipboard.snippet.js +28 -6
  140. package/lib/runjs-context/snippets/scene/detail/format-number.snippet.d.ts +11 -0
  141. package/lib/runjs-context/snippets/scene/{jsfield → detail}/format-number.snippet.js +13 -3
  142. package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.d.ts +11 -0
  143. package/lib/runjs-context/snippets/scene/{jsfield → detail}/innerHTML-value.snippet.js +13 -3
  144. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.d.ts +11 -0
  145. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +82 -0
  146. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.d.ts +11 -0
  147. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +80 -0
  148. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.d.ts +11 -0
  149. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +74 -0
  150. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.d.ts +11 -0
  151. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.js +63 -0
  152. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.d.ts +11 -0
  153. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +81 -0
  154. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.d.ts +11 -0
  155. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.js +64 -0
  156. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.d.ts +11 -0
  157. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.js +74 -0
  158. package/lib/runjs-context/snippets/scene/form/render-basic.snippet.d.ts +11 -0
  159. package/lib/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.js +11 -2
  160. package/lib/runjs-context/snippets/scene/form/set-disabled.snippet.d.ts +11 -0
  161. package/lib/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.js +12 -3
  162. package/lib/runjs-context/snippets/scene/form/set-field-value.snippet.d.ts +11 -0
  163. package/lib/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.js +12 -3
  164. package/lib/runjs-context/snippets/scene/form/set-required.snippet.d.ts +11 -0
  165. package/lib/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.js +12 -3
  166. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.d.ts +11 -0
  167. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.js +67 -0
  168. package/lib/runjs-context/snippets/scene/form/toggle-visible.snippet.d.ts +11 -0
  169. package/lib/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.js +12 -3
  170. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.d.ts +11 -0
  171. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +64 -0
  172. package/lib/runjs-context/snippets/scene/table/collection-selected-count.snippet.d.ts +11 -0
  173. package/lib/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.js +11 -2
  174. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.d.ts +11 -0
  175. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +79 -0
  176. package/lib/runjs-context/snippets/scene/table/destroy-selected.snippet.d.ts +11 -0
  177. package/lib/runjs-context/snippets/{global/log-json-record.snippet.js → scene/table/destroy-selected.snippet.js} +24 -11
  178. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.d.ts +11 -0
  179. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.js +64 -0
  180. package/lib/runjs-context/snippets/scene/table/iterate-selected-rows.snippet.d.ts +11 -0
  181. package/lib/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.js +11 -2
  182. package/lib/runjs-context/snippets/types.d.ts +9 -1
  183. package/lib/scheduler/ModelOperationScheduler.d.ts +51 -0
  184. package/lib/scheduler/ModelOperationScheduler.js +262 -0
  185. package/lib/types.d.ts +28 -3
  186. package/lib/types.js +4 -3
  187. package/lib/utils/associationObjectVariable.d.ts +32 -0
  188. package/lib/utils/associationObjectVariable.js +157 -0
  189. package/lib/utils/buildSettingsViewInputArgs.d.ts +19 -0
  190. package/lib/utils/buildSettingsViewInputArgs.js +75 -0
  191. package/lib/utils/createEphemeralContext.d.ts +13 -0
  192. package/lib/utils/createEphemeralContext.js +140 -0
  193. package/lib/utils/flows.d.ts +10 -0
  194. package/lib/{runjs-context/snippets/global/api-request-post.snippet.js → utils/flows.js} +21 -15
  195. package/lib/utils/index.d.ts +7 -2
  196. package/lib/utils/index.js +21 -2
  197. package/lib/utils/jsxTransform.d.ts +15 -0
  198. package/lib/utils/jsxTransform.js +68 -0
  199. package/lib/utils/params-resolvers.js +3 -3
  200. package/lib/utils/parsePathnameToViewParams.d.ts +1 -1
  201. package/lib/utils/parsePathnameToViewParams.js +41 -5
  202. package/lib/utils/pruneFilter.d.ts +21 -0
  203. package/lib/{runjs-context/snippets/global/try-catch-async.snippet.js → utils/pruneFilter.js} +24 -16
  204. package/lib/utils/safeGlobals.d.ts +5 -3
  205. package/lib/utils/safeGlobals.js +40 -0
  206. package/lib/utils/schema-utils.js +2 -2
  207. package/lib/utils/serverContextParams.d.ts +1 -0
  208. package/lib/utils/translation.d.ts +4 -1
  209. package/lib/utils/translation.js +6 -2
  210. package/lib/utils/variablesParams.d.ts +22 -5
  211. package/lib/utils/variablesParams.js +132 -36
  212. package/lib/views/DrawerComponent.js +21 -2
  213. package/lib/views/PageComponent.js +2 -1
  214. package/lib/views/ViewNavigation.d.ts +3 -9
  215. package/lib/views/ViewNavigation.js +16 -2
  216. package/lib/views/createViewMeta.d.ts +29 -1
  217. package/lib/views/createViewMeta.js +338 -72
  218. package/lib/views/index.d.ts +1 -0
  219. package/lib/views/index.js +3 -0
  220. package/lib/views/useDialog.d.ts +9 -8
  221. package/lib/views/useDialog.js +19 -14
  222. package/lib/views/useDrawer.d.ts +9 -8
  223. package/lib/views/useDrawer.js +54 -35
  224. package/lib/views/usePage.d.ts +9 -8
  225. package/lib/views/usePage.js +20 -14
  226. package/package.json +6 -3
  227. package/src/BlockScopedFlowEngine.ts +86 -0
  228. package/src/FlowContextProvider.tsx +4 -2
  229. package/src/JSRunner.ts +3 -0
  230. package/src/ViewScopedFlowEngine.ts +15 -1
  231. package/src/__tests__/JSRunner.test.ts +62 -53
  232. package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
  233. package/src/__tests__/createViewMeta.popup.test.ts +132 -0
  234. package/src/__tests__/flow-engine.test.ts +3 -0
  235. package/src/__tests__/flowContext.test.ts +52 -0
  236. package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
  237. package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
  238. package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
  239. package/src/__tests__/flowSettings.open.test.tsx +2 -0
  240. package/src/__tests__/flowSettings.test.ts +2 -0
  241. package/src/__tests__/globalFlowRegistry.test.ts +1 -1
  242. package/src/__tests__/modelOperationScheduler.test.ts +346 -0
  243. package/src/__tests__/objectVariable.test.ts +464 -0
  244. package/src/__tests__/runjsContext.test.ts +216 -35
  245. package/src/__tests__/runjsContextImplementations.test.ts +217 -0
  246. package/src/__tests__/runjsContextRuntime.test.ts +269 -0
  247. package/src/__tests__/runjsEdgeCases.test.ts +281 -0
  248. package/src/__tests__/runjsLocales.test.ts +36 -0
  249. package/src/__tests__/runjsRuntimeFeatures.test.ts +461 -0
  250. package/src/__tests__/runjsSnippets.test.ts +140 -0
  251. package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
  252. package/src/acl/Acl.tsx +14 -0
  253. package/src/acl/__tests__/Acl.test.tsx +43 -0
  254. package/src/components/DynamicFlowsEditor.tsx +3 -4
  255. package/src/components/FieldModelRenderer.tsx +20 -7
  256. package/src/components/FieldSkeleton.tsx +27 -0
  257. package/src/components/FlowContextSelector.tsx +6 -2
  258. package/src/components/FlowModelRenderer.tsx +33 -81
  259. package/src/components/FormItem.tsx +8 -1
  260. package/src/components/MobilePopup.style.ts +220 -0
  261. package/src/components/MobilePopup.tsx +86 -0
  262. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +6 -6
  263. package/src/components/index.ts +1 -0
  264. package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +1 -1
  265. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +17 -4
  266. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +1 -1
  267. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +39 -10
  268. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +14 -1
  269. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +425 -0
  270. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +5 -7
  271. package/src/components/variables/VariableInput.tsx +25 -5
  272. package/src/components/variables/VariableTag.tsx +54 -2
  273. package/src/components/variables/types.ts +2 -0
  274. package/src/data-source/__tests__/sortCollectionsByInherits.test.ts +125 -0
  275. package/src/data-source/index.ts +42 -11
  276. package/src/data-source/sortCollectionsByInherits.ts +61 -0
  277. package/src/emitter.ts +14 -0
  278. package/src/executor/FlowExecutor.ts +213 -119
  279. package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
  280. package/src/executor/__tests__/flowExecutor.test.ts +151 -5
  281. package/src/flow-registry/GlobalFlowRegistry.ts +1 -0
  282. package/src/flow-registry/InstanceFlowRegistry.ts +1 -0
  283. package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +54 -0
  284. package/src/flowContext.ts +303 -104
  285. package/src/flowEngine.ts +96 -6
  286. package/src/flowSettings.ts +12 -4
  287. package/src/hooks/useApplyAutoFlows.ts +3 -1
  288. package/src/index.ts +12 -1
  289. package/src/locale/en-US.json +4 -2
  290. package/src/locale/zh-CN.json +4 -2
  291. package/src/models/CollectionFieldModel.tsx +60 -8
  292. package/src/models/__tests__/dispatchEvent.behavior.test.ts +169 -0
  293. package/src/models/__tests__/flowModel.getFlows.sort.test.ts +33 -9
  294. package/src/models/__tests__/flowModel.scheduleModelOperation.test.tsx +129 -0
  295. package/src/models/__tests__/flowModel.test.ts +234 -111
  296. package/src/models/__tests__/forkFlowModel.test.ts +40 -7
  297. package/src/models/flowModel.tsx +197 -132
  298. package/src/models/forkFlowModel.ts +48 -8
  299. package/src/provider.tsx +10 -7
  300. package/src/resources/multiRecordResource.ts +28 -1
  301. package/src/resources/singleRecordResource.ts +19 -1
  302. package/src/resources/sqlResource.ts +20 -25
  303. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +28 -21
  304. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +46 -34
  305. package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
  306. package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
  307. package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
  308. package/src/runjs-context/contexts/JSItemRunJSContext.ts +25 -21
  309. package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
  310. package/src/runjs-context/contexts/base.ts +196 -0
  311. package/src/runjs-context/helpers.ts +32 -30
  312. package/src/runjs-context/registry.ts +16 -47
  313. package/src/runjs-context/setup.ts +51 -0
  314. package/src/runjs-context/snippets/global/api-request.snippet.ts +38 -0
  315. package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
  316. package/src/runjs-context/snippets/global/import-esm.snippet.ts +39 -0
  317. package/src/runjs-context/snippets/global/message-error.snippet.ts +6 -0
  318. package/src/runjs-context/snippets/global/message-success.snippet.ts +6 -0
  319. package/src/runjs-context/snippets/global/notification-open.snippet.ts +11 -1
  320. package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +10 -3
  321. package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +10 -3
  322. package/src/runjs-context/snippets/global/query-selector.snippet.ts +34 -0
  323. package/src/runjs-context/snippets/global/require-amd.snippet.ts +30 -0
  324. package/src/runjs-context/snippets/global/window-open.snippet.ts +11 -1
  325. package/src/runjs-context/snippets/index.ts +178 -39
  326. package/src/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.ts +14 -2
  327. package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +45 -0
  328. package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +80 -0
  329. package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +44 -0
  330. package/src/runjs-context/snippets/scene/block/render-antd-icons.snippet.ts +46 -0
  331. package/src/runjs-context/snippets/scene/block/render-button-handler.snippet.ts +35 -0
  332. package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +38 -0
  333. package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +52 -0
  334. package/src/runjs-context/snippets/scene/block/render-react-jsx.snippet.ts +39 -0
  335. package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +38 -0
  336. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +76 -0
  337. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +65 -0
  338. package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +46 -0
  339. package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +264 -0
  340. package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +105 -0
  341. package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +33 -0
  342. package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +45 -0
  343. package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +32 -0
  344. package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +31 -0
  345. package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +63 -0
  346. package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +61 -0
  347. package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +55 -0
  348. package/src/runjs-context/snippets/scene/form/calculate-total.snippet.ts +44 -0
  349. package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +62 -0
  350. package/src/runjs-context/snippets/scene/form/conditional-required.snippet.ts +45 -0
  351. package/src/runjs-context/snippets/scene/form/copy-field-values.snippet.ts +55 -0
  352. package/src/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.ts +14 -2
  353. package/src/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.ts +15 -3
  354. package/src/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.ts +15 -3
  355. package/src/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.ts +15 -3
  356. package/src/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.ts +48 -0
  357. package/src/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.ts +15 -3
  358. package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +45 -0
  359. package/src/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.ts +14 -2
  360. package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +60 -0
  361. package/src/runjs-context/snippets/scene/table/destroy-selected.snippet.ts +36 -0
  362. package/src/runjs-context/snippets/scene/table/export-selected-json.snippet.ts +45 -0
  363. package/src/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.ts +14 -2
  364. package/src/runjs-context/snippets/types.ts +5 -1
  365. package/src/scheduler/ModelOperationScheduler.ts +304 -0
  366. package/src/types.ts +34 -0
  367. package/src/utils/__tests__/flows.test.ts +65 -0
  368. package/src/utils/__tests__/jsxTransform.test.ts +38 -0
  369. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +25 -0
  370. package/src/utils/__tests__/pruneFilter.test.ts +38 -0
  371. package/src/utils/__tests__/safeGlobals.test.ts +22 -1
  372. package/src/utils/__tests__/variablesParams.test.ts +63 -0
  373. package/src/utils/associationObjectVariable.ts +180 -0
  374. package/src/utils/buildSettingsViewInputArgs.ts +72 -0
  375. package/src/utils/createEphemeralContext.ts +142 -0
  376. package/src/utils/flows.ts +23 -0
  377. package/src/utils/index.ts +11 -2
  378. package/src/utils/jsxTransform.ts +39 -0
  379. package/src/utils/params-resolvers.ts +2 -2
  380. package/src/utils/parsePathnameToViewParams.ts +50 -6
  381. package/src/utils/pruneFilter.ts +41 -0
  382. package/src/utils/safeGlobals.ts +49 -3
  383. package/src/utils/schema-utils.ts +1 -1
  384. package/src/utils/serverContextParams.ts +1 -0
  385. package/src/utils/translation.ts +7 -2
  386. package/src/utils/variablesParams.ts +156 -38
  387. package/src/views/DrawerComponent.tsx +21 -2
  388. package/src/views/PageComponent.tsx +1 -1
  389. package/src/views/ViewNavigation.ts +20 -12
  390. package/src/views/__tests__/ViewNavigation.test.ts +10 -0
  391. package/src/views/createViewMeta.ts +393 -70
  392. package/src/views/index.tsx +1 -0
  393. package/src/views/useDialog.tsx +24 -18
  394. package/src/views/useDrawer.tsx +74 -45
  395. package/src/views/usePage.tsx +26 -17
  396. package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +0 -38
  397. package/lib/runjs-context/contexts/FlowRunJSContext.js +0 -217
  398. package/lib/runjs-context/contexts/LinkageRunJSContext.js +0 -62
  399. package/lib/runjs-context/index.d.ts +0 -19
  400. package/lib/runjs-context/index.js +0 -57
  401. package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +0 -16
  402. package/lib/runjs-context/snippets/global/api-request-get.snippet.js +0 -42
  403. package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +0 -16
  404. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +0 -16
  405. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +0 -41
  406. package/lib/runjs-context/snippets/global/requireAsync.snippet.d.ts +0 -16
  407. package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +0 -16
  408. package/lib/runjs-context/snippets/global/sleep.snippet.js +0 -43
  409. package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +0 -16
  410. package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +0 -15
  411. package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +0 -15
  412. package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +0 -15
  413. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +0 -15
  414. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +0 -43
  415. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +0 -15
  416. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +0 -40
  417. package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +0 -15
  418. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +0 -15
  419. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +0 -42
  420. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +0 -15
  421. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js +0 -46
  422. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +0 -15
  423. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +0 -41
  424. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +0 -15
  425. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +0 -41
  426. package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +0 -15
  427. package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +0 -15
  428. package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +0 -15
  429. package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +0 -15
  430. package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +0 -15
  431. package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +0 -15
  432. package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +0 -15
  433. package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +0 -15
  434. package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +0 -15
  435. package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +0 -15
  436. package/src/runjs-context/contexts/FlowRunJSContext.ts +0 -190
  437. package/src/runjs-context/contexts/LinkageRunJSContext.ts +0 -35
  438. package/src/runjs-context/index.ts +0 -20
  439. package/src/runjs-context/snippets/global/api-request-get.snippet.ts +0 -20
  440. package/src/runjs-context/snippets/global/api-request-post.snippet.ts +0 -20
  441. package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +0 -19
  442. package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +0 -21
  443. package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +0 -21
  444. package/src/runjs-context/snippets/global/log-json-record.snippet.ts +0 -21
  445. package/src/runjs-context/snippets/global/requireAsync.snippet.ts +0 -24
  446. package/src/runjs-context/snippets/global/sleep.snippet.ts +0 -21
  447. package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +0 -22
  448. package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +0 -23
  449. package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +0 -24
  450. package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +0 -21
  451. package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +0 -18
  452. package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +0 -20
  453. package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +0 -24
  454. package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +0 -19
  455. package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +0 -24
  456. package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +0 -24
  457. package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +0 -30
  458. package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +0 -34
  459. package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +0 -20
  460. package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +0 -19
  461. package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +0 -18
  462. /package/lib/runjs-context/snippets/global/{copy-record-json.snippet.d.ts → api-request.snippet.d.ts} +0 -0
  463. /package/lib/runjs-context/snippets/global/{copy-to-clipboard.snippet.d.ts → clipboard-copy-text.snippet.d.ts} +0 -0
  464. /package/lib/runjs-context/snippets/global/{log-json-record.snippet.d.ts → import-esm.snippet.d.ts} +0 -0
  465. /package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.d.ts → query-selector.snippet.d.ts} +0 -0
  466. /package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.d.ts → block/echarts-init.snippet.d.ts} +0 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSBlockRunJSContext } from '../../../contexts/JSBlockRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSBlockRunJSContext],
15
+ prefix: 'sn-three-users-orbit',
16
+ label: 'Users orbit (three.js)',
17
+ description: 'Fetch users:list and render a rotating 3D orbit of users with hover/click',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: 'Three.js 用户轨道',
21
+ description: '从 users:list 加载用户,并以 3D 轨道方式展示(支持悬停高亮与点击提示)',
22
+ },
23
+ },
24
+ content: `
25
+ // Container
26
+ const container = document.createElement('div');
27
+ container.style.width = '100%';
28
+ container.style.height = '360px';
29
+ container.style.position = 'relative';
30
+ container.style.borderRadius = '10px';
31
+ container.style.overflow = 'hidden';
32
+ container.style.background = 'radial-gradient(700px 300px at 20% 25%, #172036, #0b0f19 60%), radial-gradient(600px 240px at 80% 70%, rgba(56,189,248,0.12), transparent 60%)';
33
+ ctx.element.replaceChildren(container);
34
+
35
+ // 不做显式清理逻辑;如需存储信息,统一挂在 ctx.model 上
36
+
37
+ // 使用 ctx.useResource 加载 users:list(真实数据)
38
+ ctx.useResource('MultiRecordResource');
39
+ const resource = ctx.resource;
40
+ resource.setDataSourceKey && resource.setDataSourceKey('main');
41
+ resource.setResourceName && resource.setResourceName('users');
42
+ resource.setPageSize && resource.setPageSize(50);
43
+ try {
44
+ await resource.refresh();
45
+ } catch (err) {
46
+ var msg = (err && err.message) ? err.message : 'users:list 请求失败';
47
+ ctx.element.innerHTML = '<div style="color:#cbd5e1; padding: 12px; text-align:center;">' + msg + '</div>';
48
+ throw err;
49
+ }
50
+
51
+ // Helpers: generate avatar textures (emoji or initials)
52
+ function makeAvatarTexture(user, idx) {
53
+ const canvas = document.createElement('canvas');
54
+ const size = 128;
55
+ canvas.width = canvas.height = size;
56
+ const g = canvas.getContext('2d');
57
+ // background circle with subtle gradient
58
+ const palettes = ['#60a5fa','#34d399','#fbbf24','#f472b6','#a78bfa','#f87171','#22d3ee'];
59
+ const c1 = palettes[idx % palettes.length];
60
+ const grad = g.createRadialGradient(size*0.35, size*0.35, 10, size*0.5, size*0.5, size*0.6);
61
+ grad.addColorStop(0, c1);
62
+ grad.addColorStop(1, '#111827');
63
+ g.fillStyle = grad;
64
+ g.beginPath();
65
+ g.arc(size/2, size/2, size*0.48, 0, Math.PI*2);
66
+ g.fill();
67
+ // border
68
+ g.lineWidth = 4; g.strokeStyle = 'rgba(255,255,255,0.25)';
69
+ g.stroke();
70
+ // content: emoji if possible, else initials
71
+ const emojis = ['😀','😎','🚀','🌟','🎉','🧠','🐼','🦊','🐯','🦄','🍀','🍕','⚡️','🔥','❤️'];
72
+ const text = emojis[idx % emojis.length];
73
+ g.textAlign = 'center';
74
+ g.textBaseline = 'middle';
75
+ g.font = 'bold 68px system-ui, -apple-system, Segoe UI Emoji, Noto Color Emoji, Apple Color Emoji';
76
+ g.fillStyle = '#fff';
77
+ g.fillText(text, size/2, size/2 + 4);
78
+ const tex = new THREE.CanvasTexture(canvas);
79
+ tex.needsUpdate = true;
80
+ return tex;
81
+ }
82
+
83
+ const THREE = await ctx.importAsync('https://esm.sh/three@0.160.0');
84
+ const { Scene, PerspectiveCamera, WebGLRenderer, Color, AmbientLight, DirectionalLight, Group, Mesh, MeshStandardMaterial, SphereGeometry, Raycaster, Vector2 } = THREE;
85
+
86
+ const scene = new Scene();
87
+ scene.background = new Color(0x0b0f19);
88
+
89
+ const camera = new PerspectiveCamera(55, container.clientWidth / container.clientHeight, 0.1, 100);
90
+ camera.position.set(0, 1.2, 6.5);
91
+
92
+ const renderer = new WebGLRenderer({ antialias: true, alpha: false });
93
+ renderer.setSize(container.clientWidth, container.clientHeight);
94
+ renderer.setPixelRatio(1); // sandbox-friendly
95
+ container.appendChild(renderer.domElement);
96
+
97
+ scene.add(new AmbientLight(0xffffff, 0.8));
98
+ const dir = new DirectionalLight(0xffffff, 0.6);
99
+ dir.position.set(2.5, 3.0, 4.0);
100
+ scene.add(dir);
101
+
102
+ const orbit = new Group();
103
+ scene.add(orbit);
104
+
105
+ const users = (resource && resource.getData && Array.isArray(resource.getData())) ? resource.getData() : [];
106
+ if (!users.length) {
107
+ container.innerHTML = '<div style="color:#cbd5e1; padding: 12px; text-align:center;">users:list 接口无数据</div>';
108
+ return;
109
+ }
110
+ const N = users.length;
111
+ const R = 2.8;
112
+ // background starfield
113
+ const starCount = 500;
114
+ const starPos = new Float32Array(starCount * 3);
115
+ for (let i = 0; i < starCount; i++) {
116
+ const r = 10 * Math.pow(Math.random(), 0.7) + 4;
117
+ const th = Math.random() * Math.PI * 2;
118
+ const ph = Math.acos(2 * Math.random() - 1);
119
+ starPos[i*3+0] = r * Math.sin(ph) * Math.cos(th);
120
+ starPos[i*3+1] = r * Math.cos(ph) * 0.5;
121
+ starPos[i*3+2] = r * Math.sin(ph) * Math.sin(th);
122
+ }
123
+ const starGeo = new THREE.BufferGeometry();
124
+ starGeo.setAttribute('position', new THREE.Float32BufferAttribute(starPos, 3));
125
+ const starMat = new THREE.PointsMaterial({ color: 0xffffff, size: 0.02, transparent: true, opacity: 0.8 });
126
+ const stars = new THREE.Points(starGeo, starMat);
127
+ scene.add(stars);
128
+
129
+ const items = [];
130
+ for (let i = 0; i < N; i++) {
131
+ const u = users[i];
132
+ const a = (i / N) * Math.PI * 2;
133
+ const y = (Math.sin(a * 2) * 0.6);
134
+ const tex = makeAvatarTexture(u, i);
135
+ const mat = new THREE.SpriteMaterial({ map: tex, transparent: true, depthWrite: false });
136
+ const sprite = new THREE.Sprite(mat);
137
+ sprite.scale.set(0.9, 0.9, 1);
138
+ sprite.position.set(Math.cos(a) * R, y, Math.sin(a) * R);
139
+ sprite.userData.user = u;
140
+ orbit.add(sprite);
141
+ items.push(sprite);
142
+ }
143
+
144
+ // Simple ring wireframe for context
145
+ const ring = new Group();
146
+ scene.add(ring);
147
+ for (let k = 0; k < 64; k++) {
148
+ const a = (k / 64) * Math.PI * 2;
149
+ const seg = new Mesh(new SphereGeometry(0.01, 8, 8), new MeshStandardMaterial({ color: 0xffffff }));
150
+ seg.position.set(Math.cos(a) * R, 0, Math.sin(a) * R);
151
+ ring.add(seg);
152
+ }
153
+
154
+ // Hover + click via Raycaster
155
+ const raycaster = new Raycaster();
156
+ const mouse = new Vector2();
157
+ let over = null;
158
+
159
+ function updateMouse(e) {
160
+ const rect = container.getBoundingClientRect();
161
+ const x = (e.clientX - rect.left) / rect.width;
162
+ const y = (e.clientY - rect.top) / rect.height;
163
+ mouse.set(x * 2 - 1, -(y * 2 - 1));
164
+ }
165
+
166
+ function handleHover() {
167
+ raycaster.setFromCamera(mouse, camera);
168
+ const intersects = raycaster.intersectObjects(items, false);
169
+ const hit = (intersects && intersects[0] && intersects[0].object) ? intersects[0].object : null;
170
+ if (over && over !== hit) {
171
+ over.material.opacity = 1.0;
172
+ over.scale.set(0.9, 0.9, 1);
173
+ over = null;
174
+ }
175
+ if (hit && hit !== over) {
176
+ over = hit;
177
+ over.material.opacity = 1.0;
178
+ over.scale.set(1.15, 1.15, 1);
179
+ }
180
+ }
181
+
182
+ const onMouseMove = (e) => { updateMouse(e); handleHover(); };
183
+ // resolve primary key field name from collection meta
184
+ let __pkField = null;
185
+ async function getPrimaryKeyField() {
186
+ if (__pkField) return __pkField;
187
+ const name = (resource && resource.getResourceName) ? resource.getResourceName() : 'users';
188
+ try {
189
+ const meta = await ctx.api.request({ url: 'collections:get', method: 'get', params: { filterByTk: name } });
190
+ const data = (meta && meta.data) ? meta.data : {};
191
+ // prefer filterTargetKey, fallback to fields.primaryKey
192
+ const ft = (data && data.filterTargetKey) ? data.filterTargetKey : (data && data.options && data.options.filterTargetKey);
193
+ if (ft && typeof ft === 'string') {
194
+ __pkField = ft;
195
+ return __pkField;
196
+ }
197
+ const fields = (data && data.fields) ? data.fields : (data && data.options && data.options.fields) ? data.options.fields : [];
198
+ const pk = Array.isArray(fields) && fields.find(function(f){ return f && (f.primaryKey || (f.uiSchema && f.uiSchema['x-component'] === 'ID')); });
199
+ if (pk && typeof pk.name === 'string') {
200
+ __pkField = pk.name;
201
+ return __pkField;
202
+ }
203
+ } catch (_) {}
204
+ __pkField = 'id';
205
+ return __pkField;
206
+ }
207
+
208
+ const onClick = async (e) => {
209
+ updateMouse(e);
210
+ handleHover();
211
+ if (over && over.userData && over.userData.user) {
212
+ const u = over.userData.user;
213
+ const baseId = (ctx.model && ctx.model.uid) ? ctx.model.uid : String(ctx.model || 'runjs');
214
+ const popupUid = baseId + '-details';
215
+ const pkField = await getPrimaryKeyField();
216
+ var tk = (u && u[pkField]) ? u[pkField] : (u ? (u.id || u.userId || u.pk) : undefined);
217
+ await ctx.openView(popupUid, {
218
+ mode: 'dialog',
219
+ // 让弹窗自动定位当前记录:顶层 filterByTk + 数据源/集合信息
220
+ dataSourceKey: (resource && resource.getDataSourceKey) ? resource.getDataSourceKey() : 'main',
221
+ collectionName: (resource && resource.getResourceName) ? resource.getResourceName() : 'users',
222
+ filterByTk: tk,
223
+ params: { user: u, userId: tk },
224
+ title: (u.nickname || u.username || u.name || 'User') + ' details',
225
+ width: 720,
226
+ });
227
+ }
228
+ };
229
+ container.addEventListener('mousemove', onMouseMove);
230
+ container.addEventListener('click', onClick);
231
+
232
+ // Animation (no rAF/use setInterval)
233
+ let t = 0;
234
+ const tick = () => {
235
+ t += 0.016;
236
+ orbit.rotation.y += 0.005; // slow spin
237
+ stars.rotation.y = t * 0.02;
238
+ // subtle bobbing per item
239
+ for (let i = 0; i < items.length; i++) {
240
+ const m = items[i];
241
+ const a = (i / items.length) * Math.PI * 2;
242
+ m.position.y = Math.sin(a * 2 + t * 1.5) * 0.6;
243
+ }
244
+ renderer.render(scene, camera);
245
+ };
246
+ // 若上一次运行的动画仍在,清理之(仅使用 ctx.model 存储)
247
+ try { if (ctx.model && ctx.model.__usersOrbitTimer) clearInterval(ctx.model.__usersOrbitTimer); } catch (_) {}
248
+ var __timer = setInterval(tick, 16);
249
+ if (ctx.model) ctx.model.__usersOrbitTimer = __timer;
250
+
251
+ // Initial sizing
252
+ (() => {
253
+ const w = container.clientWidth;
254
+ const h = container.clientHeight;
255
+ camera.aspect = w / h;
256
+ camera.updateProjectionMatrix();
257
+ renderer.setSize(w, h);
258
+ })();
259
+
260
+ // 不额外挂载 cleanup;容器被替换后旧 DOM 将被 GC;定时器在下次运行前通过 ctx.model 清理
261
+ `,
262
+ };
263
+
264
+ export default snippet;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSBlockRunJSContext } from '../../../contexts/JSBlockRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSBlockRunJSContext],
15
+ prefix: 'sn-jsb-vue',
16
+ label: 'Embed Vue component',
17
+ description: 'Use ctx.importAsync to load Vue 3 ESM build and render a reactive widget',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '嵌入 Vue 组件',
21
+ description: '通过 ctx.importAsync 加载 Vue 3 ESM 构建并渲染交互组件',
22
+ },
23
+ },
24
+ content: `
25
+ const mountNode = document.createElement('div');
26
+ mountNode.style.padding = '16px';
27
+ mountNode.style.background = '#fff';
28
+ mountNode.style.borderRadius = '8px';
29
+ const target = document.createElement('div');
30
+ target.className = 'nb-vue-counter';
31
+ mountNode.appendChild(target);
32
+ ctx.element.replaceChildren(mountNode);
33
+
34
+ async function bootstrap() {
35
+ const mod = await ctx.importAsync('https://esm.sh/vue@3.4.27/dist/vue.runtime.esm-browser.js');
36
+ const createApp = mod?.createApp;
37
+ const ref = mod?.ref;
38
+ const h = mod?.h;
39
+ if (typeof createApp !== 'function' || typeof ref !== 'function' || typeof h !== 'function') {
40
+ throw new Error('Vue ESM module not available');
41
+ }
42
+
43
+ const Counter = {
44
+ setup() {
45
+ const count = ref(0);
46
+ const increase = () => {
47
+ count.value += 1;
48
+ };
49
+ const openPopup = async () => {
50
+ const popupUid = ctx.model?.uid ? ctx.model.uid + '-popup' : 'vue-popup';
51
+ await ctx.openView(popupUid, {
52
+ mode: 'drawer',
53
+ title: ctx.t('Hello from Vue'),
54
+ params: {
55
+ fromVue: true,
56
+ triggerCount: count.value,
57
+ },
58
+ });
59
+ };
60
+ return () =>
61
+ h(
62
+ 'div',
63
+ { style: 'display:flex;align-items:center;gap:12px;' },
64
+ [
65
+ h(
66
+ 'button',
67
+ {
68
+ style:
69
+ 'padding:6px 12px;border:1px solid #fa8c16;background:#fa8c16;color:#fff;border-radius:4px;cursor:pointer;',
70
+ onClick: increase,
71
+ },
72
+ ctx.t('Increase'),
73
+ ),
74
+ h(
75
+ 'button',
76
+ {
77
+ style:
78
+ 'padding:6px 12px;border:1px solid #1677ff;background:#1677ff;color:#fff;border-radius:4px;cursor:pointer;',
79
+ onClick: openPopup,
80
+ },
81
+ ctx.t('Open popup'),
82
+ ),
83
+ h(
84
+ 'span',
85
+ null,
86
+ ctx.t('Current count') + ': ' + count.value,
87
+ ),
88
+ ],
89
+ );
90
+ },
91
+ };
92
+
93
+ const app = createApp(Counter);
94
+ const mountTarget = ctx.element.querySelector('.nb-vue-counter');
95
+ app.mount(mountTarget || ctx.element);
96
+ }
97
+
98
+ bootstrap().catch((error) => {
99
+ console.error('[RunJS] failed to mount Vue counter', error);
100
+ mountNode.innerHTML = '<div style="color:#c00;">' + (error?.message || ctx.t('Vue initialization failed')) + '</div>';
101
+ });
102
+ `,
103
+ };
104
+
105
+ export default snippet;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSFieldRunJSContext } from '../../../contexts/JSFieldRunJSContext';
12
+ import { FormJSFieldItemRunJSContext } from '../../../contexts/FormJSFieldItemRunJSContext';
13
+
14
+ const snippet: SnippetModule = {
15
+ contexts: [JSFieldRunJSContext, FormJSFieldItemRunJSContext],
16
+ prefix: 'sn-jsf-color',
17
+ label: 'Display number field as colored text',
18
+ description: 'Display numeric values using colors based on their sign',
19
+ locales: {
20
+ 'zh-CN': {
21
+ label: '将数字字段显示为彩色文本',
22
+ description: '根据数值正负设置显示颜色',
23
+ },
24
+ },
25
+ content: `
26
+ // Colorize based on numeric sign
27
+ const n = Number(ctx.value ?? 0);
28
+ const color = Number.isFinite(n) ? (n > 0 ? 'green' : n < 0 ? 'red' : '#999') : '#555';
29
+ ctx.element.innerHTML = '<span style=' + JSON.stringify('color:' + color) + '>' + String(ctx.value ?? '') + '</span>';
30
+ `,
31
+ };
32
+
33
+ export default snippet;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSFieldRunJSContext } from '../../../contexts/JSFieldRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSFieldRunJSContext],
15
+ prefix: 'sn-jsf-copy',
16
+ label: 'Display text field with copy button',
17
+ description: 'Render the text field value with a copy-to-clipboard button',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '将文本字段显示为复制按钮',
21
+ description: '展示字段值并提供快捷复制到剪贴板的按钮',
22
+ },
23
+ },
24
+ content: `
25
+ const text = String(ctx.value ?? '');
26
+ ctx.element.innerHTML = '<a class="nb-copy" style="cursor:pointer;color:#1677ff">' +
27
+ ctx.t('Copy') + '</a>';
28
+
29
+ ctx.element.querySelector('.nb-copy')?.addEventListener('click', async () => {
30
+ if (navigator?.clipboard?.writeText) {
31
+ await navigator.clipboard.writeText(text);
32
+ } else {
33
+ const ta = document.createElement('textarea');
34
+ ta.value = text;
35
+ document.body.appendChild(ta);
36
+ ta.select();
37
+ document.execCommand('copy');
38
+ document.body.removeChild(ta);
39
+ }
40
+ ctx.message.success(ctx.t('Copied'));
41
+ });
42
+ `,
43
+ };
44
+
45
+ export default snippet;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSFieldRunJSContext } from '../../../contexts/JSFieldRunJSContext';
12
+ import { FormJSFieldItemRunJSContext } from '../../../contexts/FormJSFieldItemRunJSContext';
13
+
14
+ const snippet: SnippetModule = {
15
+ contexts: [JSFieldRunJSContext, FormJSFieldItemRunJSContext],
16
+ prefix: 'sn-jsf-num',
17
+ label: 'Display number field as localized number',
18
+ description: 'Format numeric values with locale-aware separators before rendering',
19
+ locales: {
20
+ 'zh-CN': {
21
+ label: '将数字字段显示为本地化格式',
22
+ description: '按本地化格式输出数值',
23
+ },
24
+ },
25
+ content: `
26
+ // Format number using locale
27
+ const n = Number(ctx.value ?? 0);
28
+ ctx.element.innerHTML = String(Number.isFinite(n) ? n.toLocaleString() : ctx.value ?? '');
29
+ `,
30
+ };
31
+
32
+ export default snippet;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSFieldRunJSContext } from '../../../contexts/JSFieldRunJSContext';
12
+ import { FormJSFieldItemRunJSContext } from '../../../contexts/FormJSFieldItemRunJSContext';
13
+
14
+ const snippet: SnippetModule = {
15
+ contexts: [JSFieldRunJSContext, FormJSFieldItemRunJSContext],
16
+ prefix: 'sn-jsf-value',
17
+ label: 'Display text field as highlighted text',
18
+ description: 'Render the current text field value with simple highlight styling',
19
+ locales: {
20
+ 'zh-CN': {
21
+ label: '将文本字段显示为高亮文本',
22
+ description: '将字段值写入容器并添加高亮样式',
23
+ },
24
+ },
25
+ content: `
26
+ const v = String(ctx.value ?? '');
27
+ ctx.element.innerHTML = \`<span class="nb-js-field-value" style="color:#1890ff;font-weight:600">\${v}</span>\`;
28
+ `,
29
+ };
30
+
31
+ export default snippet;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSFieldRunJSContext } from '../../../contexts/JSFieldRunJSContext';
12
+ import { FormJSFieldItemRunJSContext } from '../../../contexts/FormJSFieldItemRunJSContext';
13
+
14
+ const snippet: SnippetModule = {
15
+ contexts: [JSFieldRunJSContext, FormJSFieldItemRunJSContext],
16
+ prefix: 'sn-jsf-percent',
17
+ label: 'Display number field as percentage bar',
18
+ description: 'Render numeric values as a percentage progress bar',
19
+ locales: {
20
+ 'zh-CN': {
21
+ label: '将数字字段显示为百分比进度条',
22
+ description: '将数字格式化为百分比并显示进度条',
23
+ },
24
+ },
25
+ content: `
26
+ const value = Number(ctx.value ?? 0);
27
+
28
+ if (!Number.isFinite(value)) {
29
+ ctx.element.innerHTML = '-';
30
+ return;
31
+ }
32
+
33
+ // Ensure value is between 0 and 100
34
+ const percent = Math.max(0, Math.min(100, value));
35
+
36
+ // Color based on value
37
+ const getColor = (val) => {
38
+ if (val >= 80) return '#52c41a';
39
+ if (val >= 50) return '#faad14';
40
+ return '#f5222d';
41
+ };
42
+
43
+ const color = getColor(percent);
44
+
45
+ ctx.element.innerHTML = \`
46
+ <div style="display: flex; align-items: center; gap: 8px;">
47
+ <div style="flex: 1; height: 8px; background: #f0f0f0; border-radius: 4px; overflow: hidden;">
48
+ <div style="
49
+ width: \${percent}%;
50
+ height: 100%;
51
+ background: \${color};
52
+ transition: width 0.3s ease;
53
+ "></div>
54
+ </div>
55
+ <span style="color: \${color}; font-weight: 500; min-width: 45px; text-align: right;">
56
+ \${percent.toFixed(1)}%
57
+ </span>
58
+ </div>
59
+ \`;
60
+ `,
61
+ };
62
+
63
+ export default snippet;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSFieldRunJSContext } from '../../../contexts/JSFieldRunJSContext';
12
+ import { FormJSFieldItemRunJSContext } from '../../../contexts/FormJSFieldItemRunJSContext';
13
+
14
+ const snippet: SnippetModule = {
15
+ contexts: [JSFieldRunJSContext, FormJSFieldItemRunJSContext],
16
+ prefix: 'sn-jsf-relative-time',
17
+ label: 'Display date field as relative time',
18
+ description: 'Render date values as “3 days ago”, “just now”, etc.',
19
+ locales: {
20
+ 'zh-CN': {
21
+ label: '将日期字段显示为相对时间',
22
+ description: '将日期显示为“3天前”、“刚刚”等相对时间',
23
+ },
24
+ },
25
+ content: `
26
+ const formatRelativeTime = (date) => {
27
+ const now = new Date();
28
+ const diff = now - new Date(date);
29
+ const seconds = Math.floor(diff / 1000);
30
+ const minutes = Math.floor(seconds / 60);
31
+ const hours = Math.floor(minutes / 60);
32
+ const days = Math.floor(hours / 24);
33
+ const months = Math.floor(days / 30);
34
+ const years = Math.floor(days / 365);
35
+
36
+ if (seconds < 60) return ctx.t('just now');
37
+ if (minutes < 60) return ctx.t('{{count}} minutes ago', { count: minutes });
38
+ if (hours < 24) return ctx.t('{{count}} hours ago', { count: hours });
39
+ if (days < 30) return ctx.t('{{count}} days ago', { count: days });
40
+ if (months < 12) return ctx.t('{{count}} months ago', { count: months });
41
+ return ctx.t('{{count}} years ago', { count: years });
42
+ };
43
+
44
+ const dateStr = ctx.value;
45
+ if (!dateStr) {
46
+ ctx.element.innerHTML = '-';
47
+ return;
48
+ }
49
+
50
+ const relativeTime = formatRelativeTime(dateStr);
51
+ const fullDate = new Date(dateStr).toLocaleString();
52
+
53
+ ctx.element.innerHTML = \`
54
+ <span title="\${fullDate}" style="cursor: help; color: #666;">
55
+ \${relativeTime}
56
+ </span>
57
+ \`;
58
+ `,
59
+ };
60
+
61
+ export default snippet;