@keboola/design 10.1.0 → 11.0.1

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 (382) hide show
  1. package/AGENTS.md +2 -0
  2. package/dist/AIKit-Dre37SJr.js +1320 -0
  3. package/dist/AIKit-Dre37SJr.js.map +1 -0
  4. package/dist/Alert-DfZq9kGe.js +133 -0
  5. package/dist/Alert-DfZq9kGe.js.map +1 -0
  6. package/dist/AlertModal-BUC4Es8o.js +222 -0
  7. package/dist/AlertModal-BUC4Es8o.js.map +1 -0
  8. package/dist/AppShell-B5GQN6Zs.js +143 -0
  9. package/dist/AppShell-B5GQN6Zs.js.map +1 -0
  10. package/dist/AutoSaveTextarea-BeuWuszr.js +58 -0
  11. package/dist/AutoSaveTextarea-BeuWuszr.js.map +1 -0
  12. package/dist/Badge-Ch26CXoP.js +195 -0
  13. package/dist/Badge-Ch26CXoP.js.map +1 -0
  14. package/dist/BrandEditor-B8o9zdZO.js +903 -0
  15. package/dist/BrandEditor-B8o9zdZO.js.map +1 -0
  16. package/dist/BrandLogo-CJkRd0F8.js +46 -0
  17. package/dist/BrandLogo-CJkRd0F8.js.map +1 -0
  18. package/dist/Breadcrumb-DJp7WwSv.js +330 -0
  19. package/dist/Breadcrumb-DJp7WwSv.js.map +1 -0
  20. package/dist/Button-nzmDNS2q.js +391 -0
  21. package/dist/Button-nzmDNS2q.js.map +1 -0
  22. package/dist/Calendar-cG5NIJ4O.js +6768 -0
  23. package/dist/Calendar-cG5NIJ4O.js.map +1 -0
  24. package/dist/Card-BAoZ35CV.js +105 -0
  25. package/dist/Card-BAoZ35CV.js.map +1 -0
  26. package/dist/Checkbox-GJ8-srt4.js +97 -0
  27. package/dist/Checkbox-GJ8-srt4.js.map +1 -0
  28. package/dist/Clipboard-CBJZiviP.js +58 -0
  29. package/dist/Clipboard-CBJZiviP.js.map +1 -0
  30. package/dist/ClipboardButton-ez5V3fkk.js +43 -0
  31. package/dist/ClipboardButton-ez5V3fkk.js.map +1 -0
  32. package/dist/CodeEditor-BfQJfbhL.js +952 -0
  33. package/dist/CodeEditor-BfQJfbhL.js.map +1 -0
  34. package/dist/Collapsible-BQXWEOBC.js +34 -0
  35. package/dist/Collapsible-BQXWEOBC.js.map +1 -0
  36. package/dist/ColorInput-Dx8Dsv7Y.js +180 -0
  37. package/dist/ColorInput-Dx8Dsv7Y.js.map +1 -0
  38. package/dist/ColorModeSwitch-CCqj7tjE.js +77 -0
  39. package/dist/ColorModeSwitch-CCqj7tjE.js.map +1 -0
  40. package/dist/Combobox-c_xBjf0P.js +439 -0
  41. package/dist/Combobox-c_xBjf0P.js.map +1 -0
  42. package/dist/Command-CQ_bQsJp.js +102 -0
  43. package/dist/Command-CQ_bQsJp.js.map +1 -0
  44. package/dist/CopyField-BJ96zvXs.js +322 -0
  45. package/dist/CopyField-BJ96zvXs.js.map +1 -0
  46. package/dist/DateInput-CMD3dY-T.js +141 -0
  47. package/dist/DateInput-CMD3dY-T.js.map +1 -0
  48. package/dist/DatePicker-BbFbmsGl.js +24 -0
  49. package/dist/DatePicker-BbFbmsGl.js.map +1 -0
  50. package/dist/DateRangeInput-D3BhiKyk.js +139 -0
  51. package/dist/DateRangeInput-D3BhiKyk.js.map +1 -0
  52. package/dist/DateRangePicker-BiUgtt_M.js +159 -0
  53. package/dist/DateRangePicker-BiUgtt_M.js.map +1 -0
  54. package/dist/DiagramSkeleton-lwBS2YBa.js +11 -0
  55. package/dist/DiagramSkeleton-lwBS2YBa.js.map +1 -0
  56. package/dist/DiffView-ppTIzh2h.js +429 -0
  57. package/dist/DiffView-ppTIzh2h.js.map +1 -0
  58. package/dist/DropdownMenu-B6ZbYvaM.js +327 -0
  59. package/dist/DropdownMenu-B6ZbYvaM.js.map +1 -0
  60. package/dist/FieldBox-D7DYtX_m.js +70 -0
  61. package/dist/FieldBox-D7DYtX_m.js.map +1 -0
  62. package/dist/FileUpload-sXRv7JiY.js +2527 -0
  63. package/dist/FileUpload-sXRv7JiY.js.map +1 -0
  64. package/dist/Form-BDCef6O9.js +371 -0
  65. package/dist/Form-BDCef6O9.js.map +1 -0
  66. package/dist/FormGroup-S9mPNHKH.js +124 -0
  67. package/dist/FormGroup-S9mPNHKH.js.map +1 -0
  68. package/dist/FullScreenModal-CJa2VkJ2.js +96 -0
  69. package/dist/FullScreenModal-CJa2VkJ2.js.map +1 -0
  70. package/dist/HoverCard-WfDkLK1s.js +31 -0
  71. package/dist/HoverCard-WfDkLK1s.js.map +1 -0
  72. package/dist/InputGroup-BJWsI35s.js +292 -0
  73. package/dist/InputGroup-BJWsI35s.js.map +1 -0
  74. package/dist/Kbd-CxHAo1oo.js +111 -0
  75. package/dist/Kbd-CxHAo1oo.js.map +1 -0
  76. package/dist/MarkedText-Ckbft5mw.js +44 -0
  77. package/dist/MarkedText-Ckbft5mw.js.map +1 -0
  78. package/dist/MermaidDiagram-BB06gymm.js +399 -0
  79. package/dist/MermaidDiagram-BB06gymm.js.map +1 -0
  80. package/dist/Modal-BA5Wc3sx.js +185 -0
  81. package/dist/Modal-BA5Wc3sx.js.map +1 -0
  82. package/dist/ModalTitle-C76ke2eo.js +28 -0
  83. package/dist/ModalTitle-C76ke2eo.js.map +1 -0
  84. package/dist/MultiActionButtonGroup-CiBHxsSk.js +33 -0
  85. package/dist/MultiActionButtonGroup-CiBHxsSk.js.map +1 -0
  86. package/dist/Navbar-t16usFZQ.js +322 -0
  87. package/dist/Navbar-t16usFZQ.js.map +1 -0
  88. package/dist/OtpInput-CbbymqYs.js +93 -0
  89. package/dist/OtpInput-CbbymqYs.js.map +1 -0
  90. package/dist/PageHeader-Q3IpCnQd.js +177 -0
  91. package/dist/PageHeader-Q3IpCnQd.js.map +1 -0
  92. package/dist/PageLayout-DSVM-ASz.js +176 -0
  93. package/dist/PageLayout-DSVM-ASz.js.map +1 -0
  94. package/dist/PageToolbar-0_1OBzaZ.js +153 -0
  95. package/dist/PageToolbar-0_1OBzaZ.js.map +1 -0
  96. package/dist/Pagination-CM_Rszz-.js +70 -0
  97. package/dist/Pagination-CM_Rszz-.js.map +1 -0
  98. package/dist/Popconfirm-BGe1jLov.js +170 -0
  99. package/dist/Popconfirm-BGe1jLov.js.map +1 -0
  100. package/dist/Popover-Ca0V6AD1.js +92 -0
  101. package/dist/Popover-Ca0V6AD1.js.map +1 -0
  102. package/dist/RadioGroup-sIveSsNa.js +233 -0
  103. package/dist/RadioGroup-sIveSsNa.js.map +1 -0
  104. package/dist/Resizable-D3vYToZH.js +52 -0
  105. package/dist/Resizable-D3vYToZH.js.map +1 -0
  106. package/dist/Search-3UiqNZRj.js +184 -0
  107. package/dist/Search-3UiqNZRj.js.map +1 -0
  108. package/dist/SearchInput-D2fcOv7E.js +102 -0
  109. package/dist/SearchInput-D2fcOv7E.js.map +1 -0
  110. package/dist/SectionNav--7bw2b6u.js +276 -0
  111. package/dist/SectionNav--7bw2b6u.js.map +1 -0
  112. package/dist/Select-4YX38G5h.js +181 -0
  113. package/dist/Select-4YX38G5h.js.map +1 -0
  114. package/dist/Sheet-BQrX8-h5.js +169 -0
  115. package/dist/Sheet-BQrX8-h5.js.map +1 -0
  116. package/dist/Sidebar-ROaR_AqC.js +799 -0
  117. package/dist/Sidebar-ROaR_AqC.js.map +1 -0
  118. package/dist/Slider-Da_3mS5v.js +127 -0
  119. package/dist/Slider-Da_3mS5v.js.map +1 -0
  120. package/dist/Stepper-C8sm9ZFM.js +325 -0
  121. package/dist/Stepper-C8sm9ZFM.js.map +1 -0
  122. package/dist/Switch-CX2A0v50.js +201 -0
  123. package/dist/Switch-CX2A0v50.js.map +1 -0
  124. package/dist/Table-CvYuTuNU.js +104 -0
  125. package/dist/Table-CvYuTuNU.js.map +1 -0
  126. package/dist/Tabs-EAihyqCt.js +74 -0
  127. package/dist/Tabs-EAihyqCt.js.map +1 -0
  128. package/dist/TextInput-BGed-V13.js +110 -0
  129. package/dist/TextInput-BGed-V13.js.map +1 -0
  130. package/dist/ThemeProvider-QncUrfJn.js +203 -0
  131. package/dist/ThemeProvider-QncUrfJn.js.map +1 -0
  132. package/dist/TimePicker-B_NegL-7.js +98 -0
  133. package/dist/TimePicker-B_NegL-7.js.map +1 -0
  134. package/dist/Timeline-6btyJl4D.js +154 -0
  135. package/dist/Timeline-6btyJl4D.js.map +1 -0
  136. package/dist/Toast-DQSbs3oA.js +49 -0
  137. package/dist/Toast-DQSbs3oA.js.map +1 -0
  138. package/dist/ToggleGroup-Cy_10Mvu.js +47 -0
  139. package/dist/ToggleGroup-Cy_10Mvu.js.map +1 -0
  140. package/dist/Workbench-BzE-Vvd9.js +293 -0
  141. package/dist/Workbench-BzE-Vvd9.js.map +1 -0
  142. package/dist/ZoomableSvg-DG9PnAm8.js +248 -0
  143. package/dist/ZoomableSvg-DG9PnAm8.js.map +1 -0
  144. package/dist/charts.d.ts +124 -111
  145. package/dist/charts.js +303 -249
  146. package/dist/charts.js.map +1 -1
  147. package/dist/classNames-BzrkDnOD.js +9 -0
  148. package/dist/classNames-BzrkDnOD.js.map +1 -0
  149. package/dist/constants-D6JcsD4_.d.ts +41 -0
  150. package/dist/context-KxxeMHbR.js +62 -0
  151. package/dist/context-KxxeMHbR.js.map +1 -0
  152. package/dist/editors.d.ts +180 -173
  153. package/dist/editors.js +747 -420
  154. package/dist/editors.js.map +1 -1
  155. package/dist/escapeStringRegexp-8MxP2knR.js +6 -0
  156. package/dist/escapeStringRegexp-8MxP2knR.js.map +1 -0
  157. package/dist/icons-Cek151jC.js +640 -0
  158. package/dist/icons-Cek151jC.js.map +1 -0
  159. package/dist/icons.d.ts +2 -41
  160. package/dist/icons.js +2 -4
  161. package/dist/index-m-kQEWiY.d.ts +54 -0
  162. package/dist/index.d.ts +6192 -9904
  163. package/dist/index.js +112 -15803
  164. package/dist/internal/blocks/AIKit.js +2 -0
  165. package/dist/internal/blocks/AppShell.js +2 -0
  166. package/dist/internal/blocks/AutoSaveTextarea.js +2 -0
  167. package/dist/internal/blocks/BrandEditor.js +2 -0
  168. package/dist/internal/blocks/ChartPanel.js +46 -0
  169. package/dist/internal/blocks/ChartPanel.js.map +1 -0
  170. package/dist/internal/blocks/ClipboardButton.js +2 -0
  171. package/dist/internal/blocks/ColorInput.js +2 -0
  172. package/dist/internal/blocks/ColorModeSwitch.js +2 -0
  173. package/dist/internal/blocks/Command.js +2 -0
  174. package/dist/internal/blocks/CopyField.js +2 -0
  175. package/dist/internal/blocks/DashboardHero.js +59 -0
  176. package/dist/internal/blocks/DashboardHero.js.map +1 -0
  177. package/dist/internal/blocks/DateInput.js +2 -0
  178. package/dist/internal/blocks/DateRangeInput.js +2 -0
  179. package/dist/internal/blocks/EmptyConfigurationActionCard.js +16 -0
  180. package/dist/internal/blocks/EmptyConfigurationActionCard.js.map +1 -0
  181. package/dist/internal/blocks/EmptyState.js +142 -0
  182. package/dist/internal/blocks/EmptyState.js.map +1 -0
  183. package/dist/internal/blocks/ErrorState.js +179 -0
  184. package/dist/internal/blocks/ErrorState.js.map +1 -0
  185. package/dist/internal/blocks/ExportMenu.js +41 -0
  186. package/dist/internal/blocks/ExportMenu.js.map +1 -0
  187. package/dist/internal/blocks/Form.js +2 -0
  188. package/dist/internal/blocks/FormGroup.js +2 -0
  189. package/dist/internal/blocks/GoogleButton.js +95 -0
  190. package/dist/internal/blocks/GoogleButton.js.map +1 -0
  191. package/dist/internal/blocks/MicrosoftButton.js +64 -0
  192. package/dist/internal/blocks/MicrosoftButton.js.map +1 -0
  193. package/dist/internal/blocks/MultiActionButtonGroup.js +2 -0
  194. package/dist/internal/blocks/MultiCombobox.js +188 -0
  195. package/dist/internal/blocks/MultiCombobox.js.map +1 -0
  196. package/dist/internal/blocks/NumberInput.js +44 -0
  197. package/dist/internal/blocks/NumberInput.js.map +1 -0
  198. package/dist/internal/blocks/OtpInput.js +2 -0
  199. package/dist/internal/blocks/PageHeader.js +2 -0
  200. package/dist/internal/blocks/PageLayout.js +2 -0
  201. package/dist/internal/blocks/PageToolbar.js +2 -0
  202. package/dist/internal/blocks/PasswordInput.js +97 -0
  203. package/dist/internal/blocks/PasswordInput.js.map +1 -0
  204. package/dist/internal/blocks/SearchInput.js +2 -0
  205. package/dist/internal/blocks/SearchInputWithNavigation.js +65 -0
  206. package/dist/internal/blocks/SearchInputWithNavigation.js.map +1 -0
  207. package/dist/internal/blocks/SectionNav.js +2 -0
  208. package/dist/internal/blocks/SplitButton.js +46 -0
  209. package/dist/internal/blocks/SplitButton.js.map +1 -0
  210. package/dist/internal/blocks/StatCard.js +97 -0
  211. package/dist/internal/blocks/StatCard.js.map +1 -0
  212. package/dist/internal/blocks/TextInput.js +2 -0
  213. package/dist/internal/blocks/Textarea.js +32 -0
  214. package/dist/internal/blocks/Textarea.js.map +1 -0
  215. package/dist/internal/blocks/TimeInput.js +77 -0
  216. package/dist/internal/blocks/TimeInput.js.map +1 -0
  217. package/dist/internal/components/Alert.js +2 -0
  218. package/dist/internal/components/AlertModal.js +2 -0
  219. package/dist/internal/components/Avatar.js +53 -0
  220. package/dist/internal/components/Avatar.js.map +1 -0
  221. package/dist/internal/components/Badge.js +2 -0
  222. package/dist/internal/components/BrandLogo.js +2 -0
  223. package/dist/internal/components/Breadcrumb.js +2 -0
  224. package/dist/internal/components/Button.js +2 -0
  225. package/dist/internal/components/ButtonGroup.js +66 -0
  226. package/dist/internal/components/ButtonGroup.js.map +1 -0
  227. package/dist/internal/components/Calendar.js +2 -0
  228. package/dist/internal/components/Card.js +2 -0
  229. package/dist/internal/components/Checkbox.js +2 -0
  230. package/dist/internal/components/Clipboard.js +2 -0
  231. package/dist/internal/components/Collapsible.js +2 -0
  232. package/dist/internal/components/CollapsiblePanel.js +87 -0
  233. package/dist/internal/components/CollapsiblePanel.js.map +1 -0
  234. package/dist/internal/components/Combobox.js +2 -0
  235. package/dist/internal/components/DatePicker.js +2 -0
  236. package/dist/internal/components/DateRangePicker.js +2 -0
  237. package/dist/internal/components/DiffView.js +2 -0
  238. package/dist/internal/components/DotsLoader.js +18 -0
  239. package/dist/internal/components/DotsLoader.js.map +1 -0
  240. package/dist/internal/components/DropdownMenu.js +2 -0
  241. package/dist/internal/components/EmptySearchContent.js +12 -0
  242. package/dist/internal/components/EmptySearchContent.js.map +1 -0
  243. package/dist/internal/components/FileUpload.js +2 -0
  244. package/dist/internal/components/FullScreenModal.js +2 -0
  245. package/dist/internal/components/HelpBlock.js +25 -0
  246. package/dist/internal/components/HelpBlock.js.map +1 -0
  247. package/dist/internal/components/HoverCard.js +2 -0
  248. package/dist/internal/components/InputGroup.js +2 -0
  249. package/dist/internal/components/Kbd.js +2 -0
  250. package/dist/internal/components/Label.js +39 -0
  251. package/dist/internal/components/Label.js.map +1 -0
  252. package/dist/internal/components/Link.js +22 -0
  253. package/dist/internal/components/Link.js.map +1 -0
  254. package/dist/internal/components/MarkedText.js +2 -0
  255. package/dist/internal/components/MergeEditor/ConflictStatus/ConflictStatusIndicator.js +20 -0
  256. package/dist/internal/components/MergeEditor/ConflictStatus/ConflictStatusIndicator.js.map +1 -0
  257. package/dist/internal/components/MergeEditor/PaneHeader.js +13 -0
  258. package/dist/internal/components/MergeEditor/PaneHeader.js.map +1 -0
  259. package/dist/internal/components/MergeEditor/constants.js +18 -0
  260. package/dist/internal/components/MergeEditor/constants.js.map +1 -0
  261. package/dist/internal/components/MergeEditor/useMergeDiff.js +2 -0
  262. package/dist/internal/components/Modal.js +2 -0
  263. package/dist/internal/components/Navbar.js +2 -0
  264. package/dist/internal/components/Pagination.js +2 -0
  265. package/dist/internal/components/PanelWithDetails.js +31 -0
  266. package/dist/internal/components/PanelWithDetails.js.map +1 -0
  267. package/dist/internal/components/Popconfirm.js +2 -0
  268. package/dist/internal/components/Popover.js +2 -0
  269. package/dist/internal/components/Progress.js +47 -0
  270. package/dist/internal/components/Progress.js.map +1 -0
  271. package/dist/internal/components/RadioGroup.js +2 -0
  272. package/dist/internal/components/Resizable.js +2 -0
  273. package/dist/internal/components/ScrollArea.js +42 -0
  274. package/dist/internal/components/ScrollArea.js.map +1 -0
  275. package/dist/internal/components/Search.js +2 -0
  276. package/dist/internal/components/Select.js +2 -0
  277. package/dist/internal/components/Separator.js +84 -0
  278. package/dist/internal/components/Separator.js.map +1 -0
  279. package/dist/internal/components/Sheet.js +2 -0
  280. package/dist/internal/components/Sidebar.js +2 -0
  281. package/dist/internal/components/Skeleton/Skeleton.js +39 -0
  282. package/dist/internal/components/Skeleton/Skeleton.js.map +1 -0
  283. package/dist/internal/components/Skeleton/SkeletonList.js +41 -0
  284. package/dist/internal/components/Skeleton/SkeletonList.js.map +1 -0
  285. package/dist/internal/components/Slider.js +2 -0
  286. package/dist/internal/components/SpotlightBackdrop.js +132 -0
  287. package/dist/internal/components/SpotlightBackdrop.js.map +1 -0
  288. package/dist/internal/components/Stepper.js +2 -0
  289. package/dist/internal/components/Switch.js +2 -0
  290. package/dist/internal/components/Table.js +2 -0
  291. package/dist/internal/components/Tabs.js +2 -0
  292. package/dist/internal/components/ThemeProvider.js +3 -0
  293. package/dist/internal/components/TimePicker.js +2 -0
  294. package/dist/internal/components/Timeline.js +2 -0
  295. package/dist/internal/components/Toast.js +3 -0
  296. package/dist/internal/components/Toggle.js +169 -0
  297. package/dist/internal/components/Toggle.js.map +1 -0
  298. package/dist/internal/components/ToggleGroup.js +2 -0
  299. package/dist/internal/components/Tooltip.js +2 -0
  300. package/dist/internal/components/Truncated.js +45 -0
  301. package/dist/internal/components/Truncated.js.map +1 -0
  302. package/dist/internal/components/Workbench.js +2 -0
  303. package/dist/internal/components/ZoomableSvg.js +2 -0
  304. package/dist/internal/hooks/useAutosizeInput.js +77 -0
  305. package/dist/internal/hooks/useAutosizeInput.js.map +1 -0
  306. package/dist/internal/hooks/useScrollbarPosition.js +45 -0
  307. package/dist/internal/hooks/useScrollbarPosition.js.map +1 -0
  308. package/dist/internal/hooks/useStableCallback.js +29 -0
  309. package/dist/internal/hooks/useStableCallback.js.map +1 -0
  310. package/dist/internal/utils/mergeRefs.js +20 -0
  311. package/dist/internal/utils/mergeRefs.js.map +1 -0
  312. package/dist/internal/utils.js +5 -0
  313. package/dist/markdown-editor.d.ts +72 -72
  314. package/dist/markdown-editor.js +1122 -1193
  315. package/dist/markdown-editor.js.map +1 -1
  316. package/dist/mermaid.d.ts +12 -12
  317. package/dist/mermaid.js +2 -10
  318. package/dist/rjsf.d.ts +33 -34
  319. package/dist/rjsf.js +1543 -1600
  320. package/dist/rjsf.js.map +1 -1
  321. package/dist/rolldown-runtime-Bdc48AWt.js +33 -0
  322. package/dist/styles-DSUP_-9Z.js +158 -0
  323. package/dist/styles-DSUP_-9Z.js.map +1 -0
  324. package/dist/styles.css +1 -1
  325. package/dist/testing.d.ts +8 -7
  326. package/dist/testing.js +36 -16
  327. package/dist/testing.js.map +1 -1
  328. package/dist/themeTokens-BNg98Mu9.js +85 -0
  329. package/dist/themeTokens-BNg98Mu9.js.map +1 -0
  330. package/dist/toast-CjkURw0M.js +184 -0
  331. package/dist/toast-CjkURw0M.js.map +1 -0
  332. package/dist/useColorSchemeState-CYqcUfSH.js +61 -0
  333. package/dist/useColorSchemeState-CYqcUfSH.js.map +1 -0
  334. package/dist/useControllableState-M6494mCT.js +31 -0
  335. package/dist/useControllableState-M6494mCT.js.map +1 -0
  336. package/dist/useElement-DkF6esWL.js +15 -0
  337. package/dist/useElement-DkF6esWL.js.map +1 -0
  338. package/dist/useMergeDiff-CvowEXJ1.js +465 -0
  339. package/dist/useMergeDiff-CvowEXJ1.js.map +1 -0
  340. package/dist/utils-D0c5VAyF.js +308 -0
  341. package/dist/utils-D0c5VAyF.js.map +1 -0
  342. package/package.json +10 -9
  343. package/src/styles.css +35 -7
  344. package/src/theme.css +64 -0
  345. package/dist/MermaidDiagram-EOKJHQQV.js +0 -10
  346. package/dist/MermaidDiagram-EOKJHQQV.js.map +0 -1
  347. package/dist/chunk-63NSN2VL.js +0 -274
  348. package/dist/chunk-63NSN2VL.js.map +0 -1
  349. package/dist/chunk-6FPEI4EM.js +0 -6683
  350. package/dist/chunk-6FPEI4EM.js.map +0 -1
  351. package/dist/chunk-7PUUHEJQ.js +0 -1313
  352. package/dist/chunk-7PUUHEJQ.js.map +0 -1
  353. package/dist/chunk-BOHNXTMM.js +0 -606
  354. package/dist/chunk-BOHNXTMM.js.map +0 -1
  355. package/dist/chunk-C3L3TBBT.js +0 -242
  356. package/dist/chunk-C3L3TBBT.js.map +0 -1
  357. package/dist/chunk-CTCFYWJC.js +0 -407
  358. package/dist/chunk-CTCFYWJC.js.map +0 -1
  359. package/dist/chunk-ESBL3IPF.js +0 -23
  360. package/dist/chunk-ESBL3IPF.js.map +0 -1
  361. package/dist/chunk-IJTHFNNJ.js +0 -261
  362. package/dist/chunk-IJTHFNNJ.js.map +0 -1
  363. package/dist/chunk-JP7PNHLH.js +0 -40
  364. package/dist/chunk-JP7PNHLH.js.map +0 -1
  365. package/dist/chunk-KPNAW5MU.js +0 -229
  366. package/dist/chunk-KPNAW5MU.js.map +0 -1
  367. package/dist/chunk-L37JJ6MR.js +0 -152
  368. package/dist/chunk-L37JJ6MR.js.map +0 -1
  369. package/dist/chunk-Q7NWXLCT.js +0 -90
  370. package/dist/chunk-Q7NWXLCT.js.map +0 -1
  371. package/dist/chunk-SYIEF644.js +0 -1016
  372. package/dist/chunk-SYIEF644.js.map +0 -1
  373. package/dist/chunk-VMFSRV5H.js +0 -16
  374. package/dist/chunk-VMFSRV5H.js.map +0 -1
  375. package/dist/chunk-VPPM7UUQ.js +0 -47
  376. package/dist/chunk-VPPM7UUQ.js.map +0 -1
  377. package/dist/chunk-XV3UUOYF.js +0 -845
  378. package/dist/chunk-XV3UUOYF.js.map +0 -1
  379. package/dist/constants-D3gaMY-W.d.ts +0 -39
  380. package/dist/icons.js.map +0 -1
  381. package/dist/index.js.map +0 -1
  382. package/dist/mermaid.js.map +0 -1
package/dist/rjsf.js CHANGED
@@ -1,1655 +1,1598 @@
1
- import { debounce, Combobox, DateInput, RadioGroup, Checkbox, PasswordInput, Alert, CollapsiblePanel, Tabs, TabsContent, Link } from './chunk-6FPEI4EM.js';
2
- import { TextInput, Textarea, NumberInput, FormGroup, Label } from './chunk-SYIEF644.js';
3
- import { isLanguageMode, CodeEditor } from './chunk-7PUUHEJQ.js';
4
- import './chunk-Q7NWXLCT.js';
5
- import './chunk-L37JJ6MR.js';
6
- import './chunk-ESBL3IPF.js';
7
- import { Button } from './chunk-CTCFYWJC.js';
8
- import { Trash2, Info, BookOpen } from './chunk-BOHNXTMM.js';
9
- import { Tooltip } from './chunk-63NSN2VL.js';
10
- import './chunk-JP7PNHLH.js';
11
- import { createContext, use, useMemo, useRef, useState, useEffect, useCallback, isValidElement } from 'react';
12
- import Form from '@rjsf/core';
13
- import validator from '@rjsf/validator-ajv8';
14
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
15
- import DOMPurify from 'dompurify';
16
-
17
- var RenderMarkdownContext = createContext((source) => source);
18
- var RenderMarkdownProvider = RenderMarkdownContext;
19
- var useRenderMarkdown = () => use(RenderMarkdownContext);
20
- var isValidJson = (raw) => {
21
- try {
22
- const parsed = JSON.parse(raw);
23
- return Boolean(parsed && typeof parsed === "object");
24
- } catch {
25
- return false;
26
- }
1
+ import { Tooltip, debounce } from "./utils-D0c5VAyF.js";
2
+ import { BookOpen, Info, Trash2 } from "./icons-Cek151jC.js";
3
+ import { Button } from "./Button-nzmDNS2q.js";
4
+ import { Label } from "./internal/components/Label.js";
5
+ import { Link } from "./internal/components/Link.js";
6
+ import { TextInput } from "./TextInput-BGed-V13.js";
7
+ import { RadioGroup } from "./RadioGroup-sIveSsNa.js";
8
+ import { Checkbox } from "./Checkbox-GJ8-srt4.js";
9
+ import { Combobox } from "./Combobox-c_xBjf0P.js";
10
+ import { Textarea } from "./internal/blocks/Textarea.js";
11
+ import { DateInput } from "./DateInput-CMD3dY-T.js";
12
+ import { NumberInput } from "./internal/blocks/NumberInput.js";
13
+ import { PasswordInput } from "./internal/blocks/PasswordInput.js";
14
+ import { FormGroup } from "./FormGroup-S9mPNHKH.js";
15
+ import { Alert } from "./Alert-DfZq9kGe.js";
16
+ import { CollapsiblePanel } from "./internal/components/CollapsiblePanel.js";
17
+ import { Tabs, TabsContent } from "./Tabs-EAihyqCt.js";
18
+ import { CodeEditor, isLanguageMode } from "./CodeEditor-BfQJfbhL.js";
19
+ import { createContext, isValidElement, use, useCallback, useEffect, useMemo, useRef, useState } from "react";
20
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
21
+ import DOMPurify from "dompurify";
22
+ import Form from "@rjsf/core";
23
+ import validator from "@rjsf/validator-ajv8";
24
+ //#region src/blocks/RjsfSchemaEditor/markdownContext.ts
25
+ /** Falls back to plain text when the host app doesn't provide a markdown renderer. */
26
+ const RenderMarkdownContext = createContext((source) => source);
27
+ const RenderMarkdownProvider = RenderMarkdownContext;
28
+ const useRenderMarkdown = () => use(RenderMarkdownContext);
29
+ //#endregion
30
+ //#region src/blocks/RjsfSchemaEditor/widgets/CodeEditorWidget.tsx
31
+ const isValidJson = (raw) => {
32
+ try {
33
+ const parsed = JSON.parse(raw);
34
+ return Boolean(parsed && typeof parsed === "object");
35
+ } catch {
36
+ return false;
37
+ }
27
38
  };
28
- var sanitize = (val) => {
29
- if (typeof val === "object" && val !== null) return JSON.stringify(val, null, " ");
30
- return String(val ?? "");
39
+ const sanitize = (val) => {
40
+ if (typeof val === "object" && val !== null) return JSON.stringify(val, null, " ");
41
+ return String(val ?? "");
31
42
  };
32
- var CodeEditorWidget = ({
33
- id,
34
- value,
35
- onChange,
36
- disabled,
37
- readonly,
38
- options
39
- }) => {
40
- const editorOptions = options.editor ?? {};
41
- const rawMode = editorOptions.mode ?? "application/json";
42
- const mode = isLanguageMode(rawMode) ? rawMode : "application/json";
43
- const isJsonMode = mode === "application/json";
44
- const isReadOnly = disabled || readonly || !!editorOptions.readOnly;
45
- const [text, setText] = useState(() => sanitize(value));
46
- useEffect(() => {
47
- setText((currentText) => {
48
- const sanitized = sanitize(value);
49
- if (currentText === sanitized) return currentText;
50
- if (isJsonMode && isValidJson(currentText)) {
51
- try {
52
- if (JSON.stringify(JSON.parse(currentText)) === JSON.stringify(typeof value === "object" ? value : JSON.parse(sanitized))) {
53
- return currentText;
54
- }
55
- } catch {
56
- }
57
- }
58
- return sanitized;
59
- });
60
- }, [value, isJsonMode]);
61
- const handleChange = (raw) => {
62
- setText(raw);
63
- if (isJsonMode && isValidJson(raw)) {
64
- onChange(JSON.parse(raw));
65
- } else {
66
- onChange(raw);
67
- }
68
- };
69
- const help = isJsonMode && !isReadOnly && options.encryptionHint !== false ? /* @__PURE__ */ jsxs(Fragment, { children: [
70
- "Properties prefixed with ",
71
- /* @__PURE__ */ jsx("code", { children: "#" }),
72
- " sign will be encrypted on save. Already encrypted strings will persist."
73
- ] }) : null;
74
- return /* @__PURE__ */ jsx("div", { id, children: isReadOnly ? /* @__PURE__ */ jsx(
75
- CodeEditor,
76
- {
77
- variant: "field",
78
- value: text,
79
- mode,
80
- readOnly: true,
81
- withCopyButton: true,
82
- withLineNumbers: editorOptions.lineNumbers !== false
83
- }
84
- ) : /* @__PURE__ */ jsx(
85
- CodeEditor,
86
- {
87
- variant: "field",
88
- value: text,
89
- mode,
90
- onChange: handleChange,
91
- withCopyButton: true,
92
- withLineNumbers: editorOptions.lineNumbers !== false,
93
- help
94
- }
95
- ) });
43
+ const CodeEditorWidget = ({ id, value, onChange, disabled, readonly, options }) => {
44
+ const editorOptions = options.editor ?? {};
45
+ const rawMode = editorOptions.mode ?? "application/json";
46
+ const mode = isLanguageMode(rawMode) ? rawMode : "application/json";
47
+ const isJsonMode = mode === "application/json";
48
+ const isReadOnly = disabled || readonly || !!editorOptions.readOnly;
49
+ const [text, setText] = useState(() => sanitize(value));
50
+ useEffect(() => {
51
+ setText((currentText) => {
52
+ const sanitized = sanitize(value);
53
+ if (currentText === sanitized) return currentText;
54
+ if (isJsonMode && isValidJson(currentText)) try {
55
+ if (JSON.stringify(JSON.parse(currentText)) === JSON.stringify(typeof value === "object" ? value : JSON.parse(sanitized))) return currentText;
56
+ } catch {}
57
+ return sanitized;
58
+ });
59
+ }, [value, isJsonMode]);
60
+ const handleChange = (raw) => {
61
+ setText(raw);
62
+ if (isJsonMode && isValidJson(raw)) onChange(JSON.parse(raw));
63
+ else onChange(raw);
64
+ };
65
+ const help = isJsonMode && !isReadOnly && options.encryptionHint !== false ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
66
+ "Properties prefixed with ",
67
+ /* @__PURE__ */ jsx("code", { children: "#" }),
68
+ " sign will be encrypted on save. Already encrypted strings will persist."
69
+ ] }) : null;
70
+ return /* @__PURE__ */ jsx("div", {
71
+ id,
72
+ children: isReadOnly ? /* @__PURE__ */ jsx(CodeEditor, {
73
+ variant: "field",
74
+ value: text,
75
+ mode,
76
+ readOnly: true,
77
+ withCopyButton: true,
78
+ withLineNumbers: editorOptions.lineNumbers !== false
79
+ }) : /* @__PURE__ */ jsx(CodeEditor, {
80
+ variant: "field",
81
+ value: text,
82
+ mode,
83
+ onChange: handleChange,
84
+ withCopyButton: true,
85
+ withLineNumbers: editorOptions.lineNumbers !== false,
86
+ help
87
+ })
88
+ });
96
89
  };
97
- var CodeEditorField = ({
98
- fieldPathId,
99
- formData,
100
- onChange,
101
- disabled,
102
- readonly,
103
- uiSchema
104
- }) => {
105
- const uiOptions = uiSchema?.["ui:options"];
106
- return /* @__PURE__ */ jsx(
107
- CodeEditorWidget,
108
- {
109
- id: fieldPathId.$id,
110
- value: formData,
111
- onChange: (val) => onChange(val, fieldPathId.path),
112
- disabled: !!disabled,
113
- readonly: !!readonly,
114
- options: uiOptions ?? {}
115
- }
116
- );
90
+ //#endregion
91
+ //#region src/blocks/RjsfSchemaEditor/fields/CodeEditorField.tsx
92
+ /**
93
+ * Field wrapper for CodeEditorWidget when used with type: "object".
94
+ * RJSF only applies ui:widget to primitive types, so object-typed
95
+ * code editors need a custom field that delegates to the widget.
96
+ */
97
+ const CodeEditorField = ({ fieldPathId, formData, onChange, disabled, readonly, uiSchema }) => {
98
+ const uiOptions = uiSchema?.["ui:options"];
99
+ return /* @__PURE__ */ jsx(CodeEditorWidget, {
100
+ id: fieldPathId.$id,
101
+ value: formData,
102
+ onChange: (val) => onChange(val, fieldPathId.path),
103
+ disabled: !!disabled,
104
+ readonly: !!readonly,
105
+ options: uiOptions ?? {}
106
+ });
117
107
  };
118
-
119
- // src/blocks/RjsfSchemaEditor/fieldHelpers.ts
120
- var noop = () => {
108
+ //#endregion
109
+ //#region src/blocks/RjsfSchemaEditor/fieldHelpers.ts
110
+ /** No-op function reused as onBlur/onFocus stub in custom fields. */
111
+ const noop = () => {};
112
+ const NullField = () => null;
113
+ /** RJSF always registers SchemaField; the fallback only satisfies the indexed-access type. */
114
+ const getSchemaField = (registry) => registry.fields.SchemaField ?? NullField;
115
+ /** Stub props shared by all custom SchemaField call-sites (onBlur, onFocus, errorSchema). */
116
+ const SCHEMA_FIELD_STUBS = {
117
+ onBlur: noop,
118
+ onFocus: noop,
119
+ errorSchema: {}
121
120
  };
122
- var NullField = () => null;
123
- var getSchemaField = (registry) => registry.fields.SchemaField ?? NullField;
124
- var SCHEMA_FIELD_STUBS = {
125
- onBlur: noop,
126
- onFocus: noop,
127
- errorSchema: {}
121
+ /**
122
+ * Resolves a dot-path against an object (e.g. "_metadata_.table.columns").
123
+ *
124
+ * json-editor watch paths may be prefixed with the schema `id` (e.g.
125
+ * "rootschema.endpoints.contact"). The prefix is not a real data key — it
126
+ * identifies the schema root. When the first segment doesn't exist in `data`
127
+ * we retry without it so components using this convention still resolve.
128
+ */
129
+ const resolveByPath = (path, data) => {
130
+ const parts = path.split(".");
131
+ const walk = (segments) => {
132
+ let current = data;
133
+ for (const part of segments) {
134
+ if (current == null || typeof current !== "object") return void 0;
135
+ current = current[part];
136
+ }
137
+ return current;
138
+ };
139
+ const result = walk(parts);
140
+ const [first] = parts;
141
+ if (result !== void 0 || first === void 0 || parts.length <= 1) return result;
142
+ if (!(first in data)) return walk(parts.slice(1));
143
+ return result;
128
144
  };
129
- var resolveByPath = (path, data) => {
130
- const parts = path.split(".");
131
- const walk = (segments) => {
132
- let current = data;
133
- for (const part of segments) {
134
- if (current == null || typeof current !== "object") return void 0;
135
- current = current[part];
136
- }
137
- return current;
138
- };
139
- const result = walk(parts);
140
- const [first] = parts;
141
- if (result !== void 0 || first === void 0 || parts.length <= 1) return result;
142
- if (!(first in data)) return walk(parts.slice(1));
143
- return result;
145
+ /**
146
+ * Whether a `template-watch` field is the invisible computed-helper variant.
147
+ *
148
+ * - `template-watch` replaces `ui:widget: 'hidden'`, so `ui:options.hidden` carries the schema's
149
+ * `options.hidden` instead.
150
+ * - The field stays mounted either way; only its wrapper is hidden.
151
+ */
152
+ const isHiddenTemplateWatch = (uiSchema) => {
153
+ if (uiSchema?.["ui:widget"] !== "template-watch") return false;
154
+ return !!uiSchema["ui:options"]?.hidden;
144
155
  };
145
- var extractProperty = (template) => {
146
- const match = /\{\{item\.(\w+)\}\}/.exec(template);
147
- return match?.[1] ?? "";
156
+ /**
157
+ * Extracts a property name from a simple Mustache-like template.
158
+ * e.g. "{{item.field_name}}" → "field_name"
159
+ */
160
+ const extractProperty = (template) => {
161
+ return /\{\{item\.(\w+)\}\}/.exec(template)?.[1] ?? "";
148
162
  };
149
- var buildDynamicOptions = (watch, enumSource, rootFormData) => {
150
- if (typeof enumSource === "string") {
151
- const watchPath = watch[enumSource];
152
- if (!watchPath) return [];
153
- const sourceData = resolveByPath(watchPath, rootFormData);
154
- if (!Array.isArray(sourceData)) return [];
155
- return sourceData.map((item) => {
156
- const val = String(item ?? "");
157
- return { value: val, label: val };
158
- });
159
- }
160
- if (Array.isArray(enumSource) && enumSource.length > 0) {
161
- if (enumSource.length > 1) {
162
- console.warn("[RJSF] Multiple enumSource entries are not supported, only the first is used.");
163
- }
164
- const source = enumSource[0];
165
- const watchPath = watch[source.source];
166
- if (!watchPath) return [];
167
- const sourceData = resolveByPath(watchPath, rootFormData);
168
- if (!Array.isArray(sourceData)) return [];
169
- const valueProp = extractProperty(source.value);
170
- const titleProp = extractProperty(source.title);
171
- return sourceData.filter((item) => item != null && typeof item === "object").map((item) => ({
172
- value: String(item[valueProp] ?? ""),
173
- label: String(item[titleProp] ?? item[valueProp] ?? "")
174
- }));
175
- }
176
- return [];
163
+ /**
164
+ * Builds select options from watched form data and enumSource config.
165
+ *
166
+ * Supports two json-editor enumSource formats:
167
+ * 1. String: `enumSource: "varName"` — use the watched array directly as string values
168
+ * 2. Array: `enumSource: [{ source, value, title }]` — map items through templates
169
+ */
170
+ const buildDynamicOptions = (watch, enumSource, rootFormData) => {
171
+ if (typeof enumSource === "string") {
172
+ const watchPath = watch[enumSource];
173
+ if (!watchPath) return [];
174
+ const sourceData = resolveByPath(watchPath, rootFormData);
175
+ if (!Array.isArray(sourceData)) return [];
176
+ return sourceData.map((item) => {
177
+ const val = String(item ?? "");
178
+ return {
179
+ value: val,
180
+ label: val
181
+ };
182
+ });
183
+ }
184
+ if (Array.isArray(enumSource) && enumSource.length > 0) {
185
+ if (enumSource.length > 1) console.warn("[RJSF] Multiple enumSource entries are not supported, only the first is used.");
186
+ const source = enumSource[0];
187
+ const watchPath = watch[source.source];
188
+ if (!watchPath) return [];
189
+ const sourceData = resolveByPath(watchPath, rootFormData);
190
+ if (!Array.isArray(sourceData)) return [];
191
+ const valueProp = extractProperty(source.value);
192
+ const titleProp = extractProperty(source.title);
193
+ return sourceData.filter((item) => item != null && typeof item === "object").map((item) => ({
194
+ value: String(item[valueProp] ?? ""),
195
+ label: String(item[titleProp] ?? item[valueProp] ?? "")
196
+ }));
197
+ }
198
+ return [];
177
199
  };
178
- var childFieldPathId = (parentFieldPathId, ...segments) => ({
179
- $id: [parentFieldPathId?.$id ?? "root", ...segments].join("_"),
180
- path: [...parentFieldPathId?.path ?? [], ...segments]
200
+ /**
201
+ * Builds a child `fieldPathId` for a nested SchemaField.
202
+ * Joins segments with "_" for the $id and appends them to the path array.
203
+ */
204
+ const childFieldPathId = (parentFieldPathId, ...segments) => ({
205
+ $id: [parentFieldPathId?.$id ?? "root", ...segments].join("_"),
206
+ path: [...parentFieldPathId?.path ?? [], ...segments]
181
207
  });
182
- var sortByPropertyOrder = (properties) => Object.entries(properties).sort(
183
- ([, a], [, b]) => (a.propertyOrder ?? Number.MAX_SAFE_INTEGER) - (b.propertyOrder ?? Number.MAX_SAFE_INTEGER)
184
- ).map(([key]) => key);
185
- var SchemaDescription = ({ description }) => {
186
- if (!description) return null;
187
- return /* @__PURE__ */ jsx(
188
- "p",
189
- {
190
- className: "tw:text-xs tw:text-neutral-400",
191
- dangerouslySetInnerHTML: { __html: DOMPurify.sanitize(description) }
192
- }
193
- );
208
+ /**
209
+ * Sorts object entries by `propertyOrder`, falling back to MAX_SAFE_INTEGER
210
+ * for properties without an explicit order.
211
+ */
212
+ const sortByPropertyOrder = (properties) => Object.entries(properties).sort(([, a], [, b]) => (a.propertyOrder ?? Number.MAX_SAFE_INTEGER) - (b.propertyOrder ?? Number.MAX_SAFE_INTEGER)).map(([key]) => key);
213
+ //#endregion
214
+ //#region src/blocks/RjsfSchemaEditor/SchemaDescription.tsx
215
+ /** Renders a schema description with sanitized HTML support (links, formatting, etc.). */
216
+ const SchemaDescription = ({ description }) => {
217
+ if (!description) return null;
218
+ return /* @__PURE__ */ jsx("p", {
219
+ className: "tw:text-xs tw:text-neutral-400",
220
+ dangerouslySetInnerHTML: { __html: DOMPurify.sanitize(description) }
221
+ });
194
222
  };
195
- var GridObjectField = ({
196
- schema,
197
- uiSchema = {},
198
- formData,
199
- onChange,
200
- disabled,
201
- readonly,
202
- registry,
203
- fieldPathId
204
- }) => {
205
- const properties = schema.properties ?? {};
206
- const data = formData ?? {};
207
- const SchemaField = getSchemaField(registry);
208
- const dataRef = useRef(data);
209
- dataRef.current = data;
210
- const fieldPath = fieldPathId?.path;
211
- const onPropertyChange = useCallback(
212
- // oxlint-disable-next-line @typescript-eslint/no-explicit-any
213
- (key) => (value, _childPath, errorSchema, id) => {
214
- onChange({ ...dataRef.current, [key]: value }, fieldPath, errorSchema, id);
215
- },
216
- [onChange, fieldPath]
217
- );
218
- const uiOptions = uiSchema["ui:options"];
219
- const hasCollapsed = uiOptions?.collapsed !== void 0;
220
- const collapsed = !!uiOptions?.collapsed;
221
- const disableCollapse = !!uiOptions?.disableCollapse;
222
- const sortedKeys = sortByPropertyOrder(properties);
223
- if (sortedKeys.length === 0) return null;
224
- const gridContent = /* @__PURE__ */ jsx("div", { className: "tw:grid tw:grid-cols-12 tw:gap-4 tw:[&>div:empty]:hidden", children: sortedKeys.map((key) => {
225
- const gridCols = properties[key]?.options?.grid_columns ?? 12;
226
- const gridBreak = !!properties[key]?.options?.grid_break;
227
- return /* @__PURE__ */ jsx(
228
- "div",
229
- {
230
- style: {
231
- gridColumn: gridBreak ? "1 / -1" : `span ${Math.min(gridCols, 12)}`
232
- },
233
- children: /* @__PURE__ */ jsx(
234
- SchemaField,
235
- {
236
- name: key,
237
- schema: schema.properties[key],
238
- uiSchema: uiSchema[key] ?? {},
239
- formData: data[key],
240
- ...SCHEMA_FIELD_STUBS,
241
- fieldPathId: childFieldPathId(fieldPathId, key),
242
- registry,
243
- onChange: onPropertyChange(key),
244
- disabled: !!disabled,
245
- readonly: !!readonly
246
- }
247
- )
248
- },
249
- key
250
- );
251
- }) });
252
- if (hasCollapsed && !disableCollapse) {
253
- const hasValues = Object.values(data).some(
254
- (v) => v !== void 0 && v !== null && v !== "" && v !== false
255
- );
256
- const defaultExpanded = hasValues ? !collapsed : true;
257
- return /* @__PURE__ */ jsxs(
258
- CollapsiblePanel,
259
- {
260
- className: "tw:rounded-lg",
261
- header: schema.title || "Settings",
262
- defaultExpanded,
263
- headerClassName: "tw:rounded-lg",
264
- bodyClassName: "tw:flex tw:flex-col tw:gap-4",
265
- children: [
266
- /* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }),
267
- gridContent
268
- ]
269
- }
270
- );
271
- }
272
- if (schema.title) {
273
- return /* @__PURE__ */ jsxs("div", { className: "tw:rounded-lg tw:border tw:border-solid tw:border-neutral-200 tw:p-4", children: [
274
- /* @__PURE__ */ jsx("h3", { className: "tw:mb-3 tw:text-base tw:font-medium tw:text-neutral-800", children: schema.title }),
275
- /* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }),
276
- gridContent
277
- ] });
278
- }
279
- return /* @__PURE__ */ jsxs("div", { className: "tw:flex tw:flex-col tw:gap-4", children: [
280
- /* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }),
281
- gridContent
282
- ] });
223
+ //#endregion
224
+ //#region src/blocks/RjsfSchemaEditor/fields/GridObjectField.tsx
225
+ /**
226
+ * Custom field that renders an object's properties in a responsive grid layout.
227
+ * Used for schema objects with `format: "grid"` or `"grid-strict"`.
228
+ * json-editor uses a 12-column grid; each property can specify `options.grid_columns`.
229
+ * Supports `options.collapsed` for collapsible sections.
230
+ */
231
+ const GridObjectField = ({ schema, uiSchema = {}, formData, onChange, disabled, readonly, registry, fieldPathId }) => {
232
+ const properties = schema.properties ?? {};
233
+ const data = formData ?? {};
234
+ const SchemaField = getSchemaField(registry);
235
+ const dataRef = useRef(data);
236
+ dataRef.current = data;
237
+ const fieldPath = fieldPathId?.path;
238
+ const onPropertyChange = useCallback((key) => (value, _childPath, errorSchema, id) => {
239
+ onChange({
240
+ ...dataRef.current,
241
+ [key]: value
242
+ }, fieldPath, errorSchema, id);
243
+ }, [onChange, fieldPath]);
244
+ const uiOptions = uiSchema["ui:options"];
245
+ const hasCollapsed = uiOptions?.collapsed !== void 0;
246
+ const collapsed = !!uiOptions?.collapsed;
247
+ const disableCollapse = !!uiOptions?.disableCollapse;
248
+ const sortedKeys = sortByPropertyOrder(properties);
249
+ if (sortedKeys.length === 0) return null;
250
+ const gridContent = /* @__PURE__ */ jsx("div", {
251
+ className: "tw:grid tw:grid-cols-12 tw:gap-4 tw:[&>div:empty]:hidden",
252
+ children: sortedKeys.map((key) => {
253
+ const gridCols = properties[key]?.options?.grid_columns ?? 12;
254
+ const gridBreak = !!properties[key]?.options?.grid_break;
255
+ return /* @__PURE__ */ jsx("div", {
256
+ style: { gridColumn: gridBreak ? "1 / -1" : `span ${Math.min(gridCols, 12)}` },
257
+ children: /* @__PURE__ */ jsx(SchemaField, {
258
+ name: key,
259
+ schema: schema.properties[key],
260
+ uiSchema: uiSchema[key] ?? {},
261
+ formData: data[key],
262
+ ...SCHEMA_FIELD_STUBS,
263
+ fieldPathId: childFieldPathId(fieldPathId, key),
264
+ registry,
265
+ onChange: onPropertyChange(key),
266
+ disabled: !!disabled,
267
+ readonly: !!readonly
268
+ })
269
+ }, key);
270
+ })
271
+ });
272
+ if (hasCollapsed && !disableCollapse) {
273
+ const defaultExpanded = Object.values(data).some((v) => v !== void 0 && v !== null && v !== "" && v !== false) ? !collapsed : true;
274
+ return /* @__PURE__ */ jsxs(CollapsiblePanel, {
275
+ className: "tw:rounded-lg",
276
+ header: schema.title || "Settings",
277
+ defaultExpanded,
278
+ headerClassName: "tw:rounded-lg",
279
+ bodyClassName: "tw:flex tw:flex-col tw:gap-4",
280
+ children: [/* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }), gridContent]
281
+ });
282
+ }
283
+ if (schema.title) return /* @__PURE__ */ jsxs("div", {
284
+ className: "tw:rounded-lg tw:border tw:border-solid tw:border-neutral-200 tw:p-4",
285
+ children: [
286
+ /* @__PURE__ */ jsx("h3", {
287
+ className: "tw:mb-3 tw:text-base tw:font-medium tw:text-neutral-800",
288
+ children: schema.title
289
+ }),
290
+ /* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }),
291
+ gridContent
292
+ ]
293
+ });
294
+ return /* @__PURE__ */ jsxs("div", {
295
+ className: "tw:flex tw:flex-col tw:gap-4",
296
+ children: [/* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }), gridContent]
297
+ });
283
298
  };
284
- var VALID_ALERT_TYPES = /* @__PURE__ */ new Set(["info", "warning", "error", "success"]);
285
- var InfoField = ({ schema, uiSchema }) => {
286
- if (!schema.title && !schema.description) return null;
287
- const uiOptions = uiSchema?.["ui:options"];
288
- const alertType = String(uiOptions?.alertType ?? "info");
289
- const variant = VALID_ALERT_TYPES.has(alertType) ? alertType : "info";
290
- return /* @__PURE__ */ jsx("div", { className: "tw:my-3", children: /* @__PURE__ */ jsx(Alert, { variant, title: schema.title, children: schema.description }) });
299
+ //#endregion
300
+ //#region src/blocks/RjsfSchemaEditor/fields/InfoField.tsx
301
+ const VALID_ALERT_TYPES = /* @__PURE__ */ new Set([
302
+ "info",
303
+ "warning",
304
+ "error",
305
+ "success"
306
+ ]);
307
+ /**
308
+ * Custom field that renders static informational text.
309
+ * Used for schema properties with `format: "info"`.
310
+ * Displays title and description as a read-only alert.
311
+ * Supports `options.alert_type` to control the alert variant
312
+ * (`"info"` (default), `"warning"`, `"error"`, `"success"`).
313
+ */
314
+ const InfoField = ({ schema, uiSchema }) => {
315
+ if (!schema.title && !schema.description) return null;
316
+ const uiOptions = uiSchema?.["ui:options"];
317
+ const alertType = String(uiOptions?.alertType ?? "info");
318
+ const variant = VALID_ALERT_TYPES.has(alertType) ? alertType : "info";
319
+ return /* @__PURE__ */ jsx("div", {
320
+ className: "tw:my-3",
321
+ children: /* @__PURE__ */ jsx(Alert, {
322
+ variant,
323
+ title: schema.title,
324
+ children: schema.description
325
+ })
326
+ });
291
327
  };
292
- var TooltipIcon = ({ rawHelp }) => {
293
- const renderMarkdown = useRenderMarkdown();
294
- return /* @__PURE__ */ jsx(Tooltip, { placement: "top", variant: "explanatory", tooltip: renderMarkdown(rawHelp), triggerAsChild: true, children: /* @__PURE__ */ jsx("span", { className: "tw:cursor-help tw:text-neutral-400", children: /* @__PURE__ */ jsx(Info, { className: "tw:size-4" }) }) });
328
+ //#endregion
329
+ //#region src/blocks/RjsfSchemaEditor/TooltipIcon.tsx
330
+ const TooltipIcon = ({ rawHelp }) => {
331
+ const renderMarkdown = useRenderMarkdown();
332
+ return /* @__PURE__ */ jsx(Tooltip, {
333
+ placement: "top",
334
+ variant: "explanatory",
335
+ tooltip: renderMarkdown(rawHelp),
336
+ triggerAsChild: true,
337
+ children: /* @__PURE__ */ jsx("span", {
338
+ className: "tw:cursor-help tw:text-neutral-400",
339
+ children: /* @__PURE__ */ jsx(Info, { className: "tw:size-4" })
340
+ })
341
+ });
295
342
  };
296
- var defaultValueFor = (prop) => {
297
- if (prop.default !== void 0) return prop.default;
298
- if (prop.type === "boolean") return false;
299
- if (prop.type === "string") return "";
300
- return void 0;
343
+ //#endregion
344
+ //#region src/blocks/RjsfSchemaEditor/fields/TableArrayField.tsx
345
+ /** Default value for a freshly added cell/item, honouring the schema default. */
346
+ const defaultValueFor = (prop) => {
347
+ if (prop.default !== void 0) return prop.default;
348
+ if (prop.type === "boolean") return false;
349
+ if (prop.type === "string") return "";
301
350
  };
302
- var TableArrayField = ({
303
- schema,
304
- uiSchema = {},
305
- formData,
306
- onChange,
307
- disabled,
308
- readonly,
309
- registry,
310
- fieldPathId
311
- }) => {
312
- const items = formData ?? [];
313
- const itemSchema = schema.items;
314
- const properties = itemSchema?.properties ?? {};
315
- const itemUiSchema = uiSchema.items ?? {};
316
- const SchemaField = getSchemaField(registry);
317
- const sortedKeys = sortByPropertyOrder(properties);
318
- const isPrimitiveItems = sortedKeys.length === 0 && itemSchema != null;
319
- const isReadOnly = disabled || readonly;
320
- const fieldPath = fieldPathId?.path ?? [];
321
- const itemsRef = useRef(items);
322
- itemsRef.current = items;
323
- const handleCellChange = (rowIndex, key, value) => {
324
- const newItems = [...itemsRef.current];
325
- newItems[rowIndex] = { ...newItems[rowIndex], [key]: value };
326
- onChange(newItems, fieldPath);
327
- };
328
- const handleItemChange = (rowIndex, value) => {
329
- const newItems = [...itemsRef.current];
330
- newItems[rowIndex] = value;
331
- onChange(newItems, fieldPath);
332
- };
333
- const handleRemoveRow = (rowIndex) => {
334
- onChange(
335
- itemsRef.current.filter((_, i) => i !== rowIndex),
336
- fieldPath
337
- );
338
- };
339
- const handleAddRow = () => {
340
- if (isPrimitiveItems) {
341
- onChange(
342
- [
343
- ...itemsRef.current,
344
- defaultValueFor({
345
- type: itemSchema?.type,
346
- default: itemSchema?.default
347
- })
348
- ],
349
- fieldPath
350
- );
351
- return;
352
- }
353
- const newItem = {};
354
- for (const key of sortedKeys) {
355
- newItem[key] = defaultValueFor(properties[key] ?? {});
356
- }
357
- onChange([...itemsRef.current, newItem], fieldPath);
358
- };
359
- const withHiddenLabel = (base) => ({
360
- ...base,
361
- "ui:options": {
362
- ...base["ui:options"],
363
- label: false
364
- }
365
- });
366
- const getCellUiSchema = (key) => withHiddenLabel(itemUiSchema[key] ?? {});
367
- const table = items.length > 0 && /* @__PURE__ */ jsxs("table", { className: "tw:w-full tw:table-fixed tw:border-collapse tw:text-sm", children: [
368
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
369
- isPrimitiveItems ? /* @__PURE__ */ jsx("th", { className: "tw:border-b tw:border-neutral-200 tw:p-2 tw:text-left tw:text-xs tw:font-medium tw:text-neutral-600", children: itemSchema?.title ?? "" }) : sortedKeys.map((key) => /* @__PURE__ */ jsx(
370
- "th",
371
- {
372
- className: "tw:border-b tw:border-neutral-200 tw:p-2 tw:text-left tw:text-xs tw:font-medium tw:text-neutral-600",
373
- children: properties[key]?.title ?? key
374
- },
375
- key
376
- )),
377
- !isReadOnly && /* @__PURE__ */ jsx("th", { className: "tw:w-20" })
378
- ] }) }),
379
- /* @__PURE__ */ jsx("tbody", { children: items.map((item, rowIndex) => /* @__PURE__ */ jsxs("tr", { className: "tw:border-b tw:border-neutral-100", children: [
380
- isPrimitiveItems ? /* @__PURE__ */ jsx("td", { className: "tw:px-2 tw:py-1.5 tw:[&>div]:mb-0", children: /* @__PURE__ */ jsx(
381
- SchemaField,
382
- {
383
- name: String(rowIndex),
384
- schema: itemSchema,
385
- uiSchema: withHiddenLabel(itemUiSchema),
386
- formData: item,
387
- ...SCHEMA_FIELD_STUBS,
388
- fieldPathId: childFieldPathId(fieldPathId, rowIndex),
389
- registry,
390
- onChange: (val) => handleItemChange(rowIndex, val),
391
- disabled: !!disabled,
392
- readonly: !!readonly
393
- }
394
- ) }) : sortedKeys.map((key) => /* @__PURE__ */ jsx("td", { className: "tw:px-2 tw:py-1.5 tw:[&>div]:mb-0", children: /* @__PURE__ */ jsx(
395
- SchemaField,
396
- {
397
- name: key,
398
- schema: properties[key],
399
- uiSchema: getCellUiSchema(key),
400
- formData: item[key],
401
- ...SCHEMA_FIELD_STUBS,
402
- fieldPathId: childFieldPathId(fieldPathId, rowIndex, key),
403
- registry,
404
- onChange: (val) => handleCellChange(rowIndex, key, val),
405
- disabled: !!disabled,
406
- readonly: !!readonly
407
- }
408
- ) }, key)),
409
- !isReadOnly && /* @__PURE__ */ jsx("td", { className: "tw:px-2 tw:py-1.5 tw:text-right", children: /* @__PURE__ */ jsx(
410
- Button,
411
- {
412
- variant: "invisible",
413
- size: "icon",
414
- onClick: () => handleRemoveRow(rowIndex),
415
- "aria-label": "Remove row",
416
- children: /* @__PURE__ */ jsx(Trash2, { className: "tw:size-4" })
417
- }
418
- ) })
419
- ] }, rowIndex)) })
420
- ] });
421
- const addButton = !isReadOnly && /* @__PURE__ */ jsxs(Button, { variant: "outline", onClick: handleAddRow, children: [
422
- "Add ",
423
- itemSchema?.title || "Item"
424
- ] });
425
- if (schema.title) {
426
- const tooltip = uiSchema["ui:help"];
427
- return /* @__PURE__ */ jsxs(
428
- CollapsiblePanel,
429
- {
430
- className: "tw:rounded-lg",
431
- headerClassName: "tw:rounded-lg",
432
- header: /* @__PURE__ */ jsxs("span", { className: "tw:inline-flex tw:items-center tw:gap-1", children: [
433
- schema.title,
434
- tooltip && /* @__PURE__ */ jsx(TooltipIcon, { rawHelp: tooltip })
435
- ] }),
436
- defaultExpanded: true,
437
- bodyClassName: "tw:flex tw:flex-col tw:gap-4",
438
- children: [
439
- /* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }),
440
- table,
441
- addButton
442
- ]
443
- }
444
- );
445
- }
446
- return /* @__PURE__ */ jsxs("div", { className: "tw:flex tw:flex-col tw:gap-4", children: [
447
- /* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }),
448
- table,
449
- addButton
450
- ] });
351
+ /**
352
+ * Custom field that renders an array as a table.
353
+ * Used for schema arrays with `format: "table"`.
354
+ *
355
+ * - Array of objects: each item is a row, each property a column.
356
+ * - Array of primitives (e.g. `items: { type: 'string' }`): each item is a
357
+ * single-column row holding the value itself.
358
+ *
359
+ * Cells are rendered via RJSF's SchemaField so all registered widgets are used.
360
+ */
361
+ const TableArrayField = ({ schema, uiSchema = {}, formData, onChange, disabled, readonly, registry, fieldPathId }) => {
362
+ const items = formData ?? [];
363
+ const itemSchema = schema.items;
364
+ const properties = itemSchema?.properties ?? {};
365
+ const itemUiSchema = uiSchema.items ?? {};
366
+ const SchemaField = getSchemaField(registry);
367
+ const sortedKeys = sortByPropertyOrder(properties);
368
+ const isPrimitiveItems = sortedKeys.length === 0 && itemSchema != null;
369
+ const isReadOnly = disabled || readonly;
370
+ const fieldPath = fieldPathId?.path ?? [];
371
+ const itemsRef = useRef(items);
372
+ itemsRef.current = items;
373
+ const handleCellChange = (rowIndex, key, value) => {
374
+ const newItems = [...itemsRef.current];
375
+ newItems[rowIndex] = {
376
+ ...newItems[rowIndex],
377
+ [key]: value
378
+ };
379
+ onChange(newItems, fieldPath);
380
+ };
381
+ const handleItemChange = (rowIndex, value) => {
382
+ const newItems = [...itemsRef.current];
383
+ newItems[rowIndex] = value;
384
+ onChange(newItems, fieldPath);
385
+ };
386
+ const handleRemoveRow = (rowIndex) => {
387
+ onChange(itemsRef.current.filter((_, i) => i !== rowIndex), fieldPath);
388
+ };
389
+ const handleAddRow = () => {
390
+ if (isPrimitiveItems) {
391
+ onChange([...itemsRef.current, defaultValueFor({
392
+ type: itemSchema?.type,
393
+ default: itemSchema?.default
394
+ })], fieldPath);
395
+ return;
396
+ }
397
+ const newItem = {};
398
+ for (const key of sortedKeys) newItem[key] = defaultValueFor(properties[key] ?? {});
399
+ onChange([...itemsRef.current, newItem], fieldPath);
400
+ };
401
+ const withHiddenLabel = (base) => ({
402
+ ...base,
403
+ "ui:options": {
404
+ ...base["ui:options"],
405
+ label: false
406
+ }
407
+ });
408
+ const getCellUiSchema = (key) => withHiddenLabel(itemUiSchema[key] ?? {});
409
+ const table = items.length > 0 && /* @__PURE__ */ jsxs("table", {
410
+ className: "tw:w-full tw:table-fixed tw:border-collapse tw:text-sm",
411
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [isPrimitiveItems ? /* @__PURE__ */ jsx("th", {
412
+ className: "tw:border-b tw:border-neutral-200 tw:p-2 tw:text-left tw:text-xs tw:font-medium tw:text-neutral-600",
413
+ children: itemSchema?.title ?? ""
414
+ }) : sortedKeys.map((key) => /* @__PURE__ */ jsx("th", {
415
+ className: "tw:border-b tw:border-neutral-200 tw:p-2 tw:text-left tw:text-xs tw:font-medium tw:text-neutral-600",
416
+ children: properties[key]?.title ?? key
417
+ }, key)), !isReadOnly && /* @__PURE__ */ jsx("th", { className: "tw:w-20" })] }) }), /* @__PURE__ */ jsx("tbody", { children: items.map((item, rowIndex) => /* @__PURE__ */ jsxs("tr", {
418
+ className: "tw:border-b tw:border-neutral-100",
419
+ children: [isPrimitiveItems ? /* @__PURE__ */ jsx("td", {
420
+ className: "tw:px-2 tw:py-1.5 tw:[&>div]:mb-0",
421
+ children: /* @__PURE__ */ jsx(SchemaField, {
422
+ name: String(rowIndex),
423
+ schema: itemSchema,
424
+ uiSchema: withHiddenLabel(itemUiSchema),
425
+ formData: item,
426
+ ...SCHEMA_FIELD_STUBS,
427
+ fieldPathId: childFieldPathId(fieldPathId, rowIndex),
428
+ registry,
429
+ onChange: (val) => handleItemChange(rowIndex, val),
430
+ disabled: !!disabled,
431
+ readonly: !!readonly
432
+ })
433
+ }) : sortedKeys.map((key) => /* @__PURE__ */ jsx("td", {
434
+ className: "tw:px-2 tw:py-1.5 tw:[&>div]:mb-0",
435
+ children: /* @__PURE__ */ jsx(SchemaField, {
436
+ name: key,
437
+ schema: properties[key],
438
+ uiSchema: getCellUiSchema(key),
439
+ formData: item[key],
440
+ ...SCHEMA_FIELD_STUBS,
441
+ fieldPathId: childFieldPathId(fieldPathId, rowIndex, key),
442
+ registry,
443
+ onChange: (val) => handleCellChange(rowIndex, key, val),
444
+ disabled: !!disabled,
445
+ readonly: !!readonly
446
+ })
447
+ }, key)), !isReadOnly && /* @__PURE__ */ jsx("td", {
448
+ className: "tw:px-2 tw:py-1.5 tw:text-right",
449
+ children: /* @__PURE__ */ jsx(Button, {
450
+ variant: "invisible",
451
+ size: "icon",
452
+ onClick: () => handleRemoveRow(rowIndex),
453
+ "aria-label": "Remove row",
454
+ children: /* @__PURE__ */ jsx(Trash2, { className: "tw:size-4" })
455
+ })
456
+ })]
457
+ }, rowIndex)) })]
458
+ });
459
+ const addButton = !isReadOnly && /* @__PURE__ */ jsxs(Button, {
460
+ variant: "outline",
461
+ onClick: handleAddRow,
462
+ children: ["Add ", itemSchema?.title || "Item"]
463
+ });
464
+ if (schema.title) {
465
+ const tooltip = uiSchema["ui:help"];
466
+ return /* @__PURE__ */ jsxs(CollapsiblePanel, {
467
+ className: "tw:rounded-lg",
468
+ headerClassName: "tw:rounded-lg",
469
+ header: /* @__PURE__ */ jsxs("span", {
470
+ className: "tw:inline-flex tw:items-center tw:gap-1",
471
+ children: [schema.title, tooltip && /* @__PURE__ */ jsx(TooltipIcon, { rawHelp: tooltip })]
472
+ }),
473
+ defaultExpanded: true,
474
+ bodyClassName: "tw:flex tw:flex-col tw:gap-4",
475
+ children: [
476
+ /* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }),
477
+ table,
478
+ addButton
479
+ ]
480
+ });
481
+ }
482
+ return /* @__PURE__ */ jsxs("div", {
483
+ className: "tw:flex tw:flex-col tw:gap-4",
484
+ children: [
485
+ /* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }),
486
+ table,
487
+ addButton
488
+ ]
489
+ });
451
490
  };
452
- var TabsObjectField = ({
453
- schema,
454
- uiSchema = {},
455
- formData,
456
- onChange,
457
- disabled,
458
- readonly,
459
- registry,
460
- fieldPathId
461
- }) => {
462
- const properties = schema.properties ?? {};
463
- const data = formData ?? {};
464
- const SchemaField = getSchemaField(registry);
465
- const dataRef = useRef(data);
466
- dataRef.current = data;
467
- const onPropertyChange = useCallback(
468
- // oxlint-disable-next-line @typescript-eslint/no-explicit-any
469
- (key) => (value, path, errorSchema, id) => {
470
- onChange({ ...dataRef.current, [key]: value }, path, errorSchema, id);
471
- },
472
- [onChange]
473
- );
474
- const sortedKeys = sortByPropertyOrder(properties);
475
- const [activeTab, setActiveTab] = useState(sortedKeys[0] ?? "");
476
- if (sortedKeys.length === 0) return null;
477
- const triggers = sortedKeys.map((key) => ({
478
- value: key,
479
- title: properties[key]?.title ?? key
480
- }));
481
- return /* @__PURE__ */ jsxs("div", { className: "tw:flex tw:flex-col tw:gap-4", children: [
482
- schema.title && /* @__PURE__ */ jsx("h3", { className: "tw:text-base tw:font-medium tw:text-neutral-800", children: schema.title }),
483
- /* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }),
484
- /* @__PURE__ */ jsx(Tabs, { triggers, value: activeTab, onValueChange: setActiveTab, compact: true, children: sortedKeys.map((key) => /* @__PURE__ */ jsx(TabsContent, { value: key, children: /* @__PURE__ */ jsx(
485
- SchemaField,
486
- {
487
- name: key,
488
- schema: schema.properties[key],
489
- uiSchema: uiSchema[key] ?? {},
490
- formData: data[key],
491
- ...SCHEMA_FIELD_STUBS,
492
- fieldPathId: childFieldPathId(fieldPathId, key),
493
- registry,
494
- onChange: onPropertyChange(key),
495
- disabled: !!disabled,
496
- readonly: !!readonly
497
- }
498
- ) }, key)) })
499
- ] });
491
+ //#endregion
492
+ //#region src/blocks/RjsfSchemaEditor/fields/TabsObjectField.tsx
493
+ /**
494
+ * Custom field that renders an object's properties as tabs.
495
+ * Used for schema objects with `format: "tabs"`, `"tabs-top"`, or `"categories"`.
496
+ * Each property becomes a tab panel.
497
+ */
498
+ const TabsObjectField = ({ schema, uiSchema = {}, formData, onChange, disabled, readonly, registry, fieldPathId }) => {
499
+ const properties = schema.properties ?? {};
500
+ const data = formData ?? {};
501
+ const SchemaField = getSchemaField(registry);
502
+ const dataRef = useRef(data);
503
+ dataRef.current = data;
504
+ const onPropertyChange = useCallback((key) => (value, path, errorSchema, id) => {
505
+ onChange({
506
+ ...dataRef.current,
507
+ [key]: value
508
+ }, path, errorSchema, id);
509
+ }, [onChange]);
510
+ const sortedKeys = sortByPropertyOrder(properties);
511
+ const [activeTab, setActiveTab] = useState(sortedKeys[0] ?? "");
512
+ if (sortedKeys.length === 0) return null;
513
+ const triggers = sortedKeys.map((key) => ({
514
+ value: key,
515
+ title: properties[key]?.title ?? key
516
+ }));
517
+ return /* @__PURE__ */ jsxs("div", {
518
+ className: "tw:flex tw:flex-col tw:gap-4",
519
+ children: [
520
+ schema.title && /* @__PURE__ */ jsx("h3", {
521
+ className: "tw:text-base tw:font-medium tw:text-neutral-800",
522
+ children: schema.title
523
+ }),
524
+ /* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }),
525
+ /* @__PURE__ */ jsx(Tabs, {
526
+ triggers,
527
+ value: activeTab,
528
+ onValueChange: setActiveTab,
529
+ compact: true,
530
+ children: sortedKeys.map((key) => /* @__PURE__ */ jsx(TabsContent, {
531
+ value: key,
532
+ children: /* @__PURE__ */ jsx(SchemaField, {
533
+ name: key,
534
+ schema: schema.properties[key],
535
+ uiSchema: uiSchema[key] ?? {},
536
+ formData: data[key],
537
+ ...SCHEMA_FIELD_STUBS,
538
+ fieldPathId: childFieldPathId(fieldPathId, key),
539
+ registry,
540
+ onChange: onPropertyChange(key),
541
+ disabled: !!disabled,
542
+ readonly: !!readonly
543
+ })
544
+ }, key))
545
+ })
546
+ ]
547
+ });
500
548
  };
501
- var ArrayFieldItemTemplate = ({
502
- children,
503
- index,
504
- totalItems,
505
- schema,
506
- hasToolbar,
507
- disabled,
508
- readonly,
509
- buttonsProps
510
- }) => {
511
- const isObject = schema.type === "object";
512
- const canRemove = hasToolbar && buttonsProps.hasRemove && !disabled && !readonly;
513
- if (isObject) {
514
- const itemTitle = `${schema.title || "Item"} ${index + 1}`;
515
- const defaultExpanded = totalItems <= 1;
516
- return /* @__PURE__ */ jsx(
517
- CollapsiblePanel,
518
- {
519
- className: "tw:rounded-lg",
520
- headerClassName: "tw:rounded-lg",
521
- header: /* @__PURE__ */ jsxs("div", { className: "tw:flex tw:w-full tw:items-center tw:justify-between", children: [
522
- /* @__PURE__ */ jsx("span", { children: itemTitle }),
523
- canRemove && /* @__PURE__ */ jsx(
524
- "div",
525
- {
526
- role: "presentation",
527
- onClick: (e) => e.stopPropagation(),
528
- onKeyUp: (e) => e.stopPropagation(),
529
- children: /* @__PURE__ */ jsx(
530
- Button,
531
- {
532
- variant: "invisible",
533
- size: "icon",
534
- "aria-label": `Remove ${itemTitle}`,
535
- onClick: buttonsProps.onRemoveItem,
536
- children: /* @__PURE__ */ jsx(Trash2, { className: "tw:size-4" })
537
- }
538
- )
539
- }
540
- )
541
- ] }),
542
- defaultExpanded,
543
- children: /* @__PURE__ */ jsx("div", { className: "tw:flex tw:flex-col tw:gap-4", children })
544
- }
545
- );
546
- }
547
- return /* @__PURE__ */ jsx("div", { className: "tw:rounded-lg tw:border tw:border-solid tw:border-neutral-200 tw:bg-white tw:p-4", children: /* @__PURE__ */ jsxs("div", { className: "tw:flex tw:items-start tw:gap-3", children: [
548
- /* @__PURE__ */ jsx("div", { className: "tw:flex tw:flex-1 tw:flex-col tw:gap-4", children }),
549
- canRemove && /* @__PURE__ */ jsx(
550
- Button,
551
- {
552
- variant: "outline",
553
- size: "small",
554
- className: "tw:mt-5 tw:shrink-0",
555
- onClick: buttonsProps.onRemoveItem,
556
- children: "Delete"
557
- }
558
- )
559
- ] }) });
549
+ //#endregion
550
+ //#region src/blocks/RjsfSchemaEditor/templates/ArrayFieldItemTemplate.tsx
551
+ const ArrayFieldItemTemplate = ({ children, index, totalItems, schema, hasToolbar, disabled, readonly, buttonsProps }) => {
552
+ const isObject = schema.type === "object";
553
+ const canRemove = hasToolbar && buttonsProps.hasRemove && !disabled && !readonly;
554
+ if (isObject) {
555
+ const itemTitle = `${schema.title || "Item"} ${index + 1}`;
556
+ const defaultExpanded = totalItems <= 1;
557
+ return /* @__PURE__ */ jsx(CollapsiblePanel, {
558
+ className: "tw:rounded-lg",
559
+ headerClassName: "tw:rounded-lg",
560
+ header: /* @__PURE__ */ jsxs("div", {
561
+ className: "tw:flex tw:w-full tw:items-center tw:justify-between",
562
+ children: [/* @__PURE__ */ jsx("span", { children: itemTitle }), canRemove && /* @__PURE__ */ jsx("div", {
563
+ role: "presentation",
564
+ onClick: (e) => e.stopPropagation(),
565
+ onKeyUp: (e) => e.stopPropagation(),
566
+ children: /* @__PURE__ */ jsx(Button, {
567
+ variant: "invisible",
568
+ size: "icon",
569
+ "aria-label": `Remove ${itemTitle}`,
570
+ onClick: buttonsProps.onRemoveItem,
571
+ children: /* @__PURE__ */ jsx(Trash2, { className: "tw:size-4" })
572
+ })
573
+ })]
574
+ }),
575
+ defaultExpanded,
576
+ children: /* @__PURE__ */ jsx("div", {
577
+ className: "tw:flex tw:flex-col tw:gap-4",
578
+ children
579
+ })
580
+ });
581
+ }
582
+ return /* @__PURE__ */ jsx("div", {
583
+ className: "tw:rounded-lg tw:border tw:border-solid tw:border-neutral-200 tw:bg-white tw:p-4",
584
+ children: /* @__PURE__ */ jsxs("div", {
585
+ className: "tw:flex tw:items-start tw:gap-3",
586
+ children: [/* @__PURE__ */ jsx("div", {
587
+ className: "tw:flex tw:flex-1 tw:flex-col tw:gap-4",
588
+ children
589
+ }), canRemove && /* @__PURE__ */ jsx(Button, {
590
+ variant: "outline",
591
+ size: "small",
592
+ className: "tw:mt-5 tw:shrink-0",
593
+ onClick: buttonsProps.onRemoveItem,
594
+ children: "Delete"
595
+ })]
596
+ })
597
+ });
560
598
  };
561
- var ArrayFieldTemplate = ({
562
- items,
563
- canAdd,
564
- onAddClick,
565
- title,
566
- schema,
567
- disabled,
568
- readonly
569
- }) => {
570
- const isReadOnly = disabled || readonly;
571
- const itemLabel = typeof schema.items === "object" && schema.items !== null && !Array.isArray(schema.items) ? schema.items.title || "Item" : "Item";
572
- return /* @__PURE__ */ jsxs("div", { className: "tw:flex tw:flex-col tw:gap-4", children: [
573
- (title || schema.description) && /* @__PURE__ */ jsxs("div", { children: [
574
- title && /* @__PURE__ */ jsx("h3", { className: "tw:text-base tw:font-medium tw:text-neutral-800", children: title }),
575
- schema.description && /* @__PURE__ */ jsx("p", { className: "tw:mt-1 tw:text-xs tw:text-neutral-400", children: schema.description })
576
- ] }),
577
- items,
578
- canAdd && !isReadOnly && /* @__PURE__ */ jsxs(Button, { variant: "outline", onClick: onAddClick, children: [
579
- "Add ",
580
- itemLabel
581
- ] })
582
- ] });
599
+ //#endregion
600
+ //#region src/blocks/RjsfSchemaEditor/templates/ArrayFieldTemplate.tsx
601
+ const ArrayFieldTemplate = ({ items, canAdd, onAddClick, title, schema, disabled, readonly }) => {
602
+ const isReadOnly = disabled || readonly;
603
+ const itemLabel = typeof schema.items === "object" && schema.items !== null && !Array.isArray(schema.items) ? schema.items.title || "Item" : "Item";
604
+ return /* @__PURE__ */ jsxs("div", {
605
+ className: "tw:flex tw:flex-col tw:gap-4",
606
+ children: [
607
+ (title || schema.description) && /* @__PURE__ */ jsxs("div", { children: [title && /* @__PURE__ */ jsx("h3", {
608
+ className: "tw:text-base tw:font-medium tw:text-neutral-800",
609
+ children: title
610
+ }), schema.description && /* @__PURE__ */ jsx("p", {
611
+ className: "tw:mt-1 tw:text-xs tw:text-neutral-400",
612
+ children: schema.description
613
+ })] }),
614
+ items,
615
+ canAdd && !isReadOnly && /* @__PURE__ */ jsxs(Button, {
616
+ variant: "outline",
617
+ onClick: onAddClick,
618
+ children: ["Add ", itemLabel]
619
+ })
620
+ ]
621
+ });
583
622
  };
584
- var DescriptionFieldTemplate = ({ description, id }) => {
585
- if (!description) return null;
586
- if (isValidElement(description)) {
587
- return /* @__PURE__ */ jsx("div", { id, children: description });
588
- }
589
- return /* @__PURE__ */ jsx(
590
- "p",
591
- {
592
- id,
593
- className: "tw:text-xs tw:text-neutral-400",
594
- dangerouslySetInnerHTML: { __html: DOMPurify.sanitize(String(description)) }
595
- }
596
- );
623
+ //#endregion
624
+ //#region src/blocks/RjsfSchemaEditor/templates/DescriptionFieldTemplate.tsx
625
+ /**
626
+ * Custom description template that renders HTML in schema descriptions.
627
+ * Uses DOMPurify to sanitize the HTML before rendering.
628
+ * Schema descriptions are authored by component developers and may contain
629
+ * links (<a>), formatting (<strong>, <code>, <br>), etc.
630
+ */
631
+ const DescriptionFieldTemplate = ({ description, id }) => {
632
+ if (!description) return null;
633
+ if (isValidElement(description)) return /* @__PURE__ */ jsx("div", {
634
+ id,
635
+ children: description
636
+ });
637
+ return /* @__PURE__ */ jsx("p", {
638
+ id,
639
+ className: "tw:text-xs tw:text-neutral-400",
640
+ dangerouslySetInnerHTML: { __html: DOMPurify.sanitize(String(description)) }
641
+ });
597
642
  };
598
- var ErrorListTemplate = ({ errors }) => {
599
- if (!errors.length) return null;
600
- return /* @__PURE__ */ jsx("div", { className: "tw:mb-4", children: errors.map((error) => /* @__PURE__ */ jsx("p", { className: "tw:text-xs tw:text-error-500", children: error.message }, `${error.property}:${error.message}`)) });
643
+ //#endregion
644
+ //#region src/blocks/RjsfSchemaEditor/templates/ErrorListTemplate.tsx
645
+ const ErrorListTemplate = ({ errors }) => {
646
+ if (!errors.length) return null;
647
+ return /* @__PURE__ */ jsx("div", {
648
+ className: "tw:mb-4",
649
+ children: errors.map((error) => /* @__PURE__ */ jsx("p", {
650
+ className: "tw:text-xs tw:text-error-500",
651
+ children: error.message
652
+ }, `${error.property}:${error.message}`))
653
+ });
601
654
  };
602
- var RootFormDataContext = createContext({});
603
- var RootFormDataProvider = RootFormDataContext;
604
- var useRootFormData = () => use(RootFormDataContext);
605
- var resolveByPath2 = (parts, data) => {
606
- let current = data;
607
- for (const part of parts) {
608
- if (current == null || typeof current !== "object") return void 0;
609
- current = current[part];
610
- }
611
- return current;
655
+ //#endregion
656
+ //#region src/blocks/RjsfSchemaEditor/RootFormDataContext.ts
657
+ const RootFormDataContext = createContext({});
658
+ const RootFormDataProvider = RootFormDataContext;
659
+ const useRootFormData = () => use(RootFormDataContext);
660
+ //#endregion
661
+ //#region src/blocks/RjsfSchemaEditor/templates/FieldTemplate.tsx
662
+ /**
663
+ * Resolves a dot-path against an object.
664
+ */
665
+ const resolveByPath$1 = (parts, data) => {
666
+ let current = data;
667
+ for (const part of parts) {
668
+ if (current == null || typeof current !== "object") return void 0;
669
+ current = current[part];
670
+ }
671
+ return current;
612
672
  };
613
- var resolveDependencyValue = (path, formData, parentPath) => {
614
- if (path.startsWith("root.")) {
615
- return resolveByPath2(path.replace(/^root\./, "").split("."), formData);
616
- }
617
- const parent = resolveByPath2(parentPath.map(String), formData);
618
- if (parent && typeof parent === "object") {
619
- const sibling = resolveByPath2(path.split("."), parent);
620
- if (sibling !== void 0) return sibling;
621
- }
622
- return resolveByPath2(path.split("."), formData);
673
+ /**
674
+ * Resolves a dependency path against form data.
675
+ *
676
+ * - Paths starting with "root." are resolved from the root form data
677
+ * - Other paths are resolved as siblings (relative to the parent object)
678
+ */
679
+ const resolveDependencyValue = (path, formData, parentPath) => {
680
+ if (path.startsWith("root.")) return resolveByPath$1(path.replace(/^root\./, "").split("."), formData);
681
+ const parent = resolveByPath$1(parentPath.map(String), formData);
682
+ if (parent && typeof parent === "object") {
683
+ const sibling = resolveByPath$1(path.split("."), parent);
684
+ if (sibling !== void 0) return sibling;
685
+ }
686
+ return resolveByPath$1(path.split("."), formData);
623
687
  };
624
- var evaluateDependencies = (dependencies, formData, parentPath) => {
625
- for (const [path, expected] of Object.entries(dependencies)) {
626
- const actual = resolveDependencyValue(path, formData, parentPath);
627
- if (Array.isArray(expected)) {
628
- if (!expected.includes(actual)) return false;
629
- } else if (expected === "") {
630
- if (actual !== "" && actual !== void 0 && actual !== null) return false;
631
- } else {
632
- if (actual !== expected) return false;
633
- }
634
- }
635
- return true;
688
+ /**
689
+ * Evaluates json-editor `options.dependencies` against current form data.
690
+ * Returns true if the field should be visible.
691
+ *
692
+ * Rules (matching old json-editor behavior):
693
+ * - `{ "field": "value" }` — show when field equals value
694
+ * - `{ "field": ["a", "b"] }` — show when field is one of the values
695
+ * - `{ "field": "" }` — show when field is empty/falsy
696
+ * - Multiple entries are AND-ed: all conditions must match
697
+ */
698
+ const evaluateDependencies = (dependencies, formData, parentPath) => {
699
+ for (const [path, expected] of Object.entries(dependencies)) {
700
+ const actual = resolveDependencyValue(path, formData, parentPath);
701
+ if (Array.isArray(expected)) {
702
+ if (!expected.includes(actual)) return false;
703
+ } else if (expected === "") {
704
+ if (actual !== "" && actual !== void 0 && actual !== null) return false;
705
+ } else if (actual !== expected) return false;
706
+ }
707
+ return true;
636
708
  };
637
- var DocumentationLinkIcon = ({
638
- documentation
639
- }) => /* @__PURE__ */ jsx(
640
- Tooltip,
641
- {
642
- placement: "top",
643
- variant: "explanatory",
644
- tooltip: documentation.tooltip ?? "Open documentation",
645
- triggerAsChild: true,
646
- children: /* @__PURE__ */ jsx(Link, { href: documentation.link, children: /* @__PURE__ */ jsx("span", { className: "tw:cursor-pointer tw:text-neutral-400 tw:hover:text-neutral-600", children: /* @__PURE__ */ jsx(BookOpen, { className: "tw:size-4" }) }) })
647
- }
648
- );
649
- var FieldTemplateBody = ({
650
- id,
651
- label,
652
- rawHelp,
653
- rawDescription,
654
- rawErrors,
655
- children,
656
- schema,
657
- uiSchema,
658
- displayLabel
659
- }) => {
660
- const widget = uiSchema?.["ui:widget"];
661
- if (widget === "test-connection" || widget === "sync-action") {
662
- return /* @__PURE__ */ jsx(Fragment, { children });
663
- }
664
- if (schema.type === "object") {
665
- return /* @__PURE__ */ jsx(Fragment, { children });
666
- }
667
- if (schema.type === "array" && !uiSchema?.["ui:widget"]) {
668
- return /* @__PURE__ */ jsx(Fragment, { children });
669
- }
670
- const uiOptions = uiSchema?.["ui:options"];
671
- const documentation = uiOptions?.documentation;
672
- const hasErrors = rawErrors && rawErrors.length > 0;
673
- const isCheckbox = schema.type === "boolean" && uiSchema?.["ui:widget"] !== "select";
674
- const showLabel = displayLabel && label && !isCheckbox;
675
- const hasHelpIcons = Boolean(rawHelp || documentation);
676
- const helpIcons = /* @__PURE__ */ jsxs(Fragment, { children: [
677
- rawHelp && /* @__PURE__ */ jsx(TooltipIcon, { rawHelp }),
678
- documentation && /* @__PURE__ */ jsx(DocumentationLinkIcon, { documentation })
679
- ] });
680
- return /* @__PURE__ */ jsxs(FormGroup, { state: hasErrors ? "error" : "default", children: [
681
- showLabel && /* @__PURE__ */ jsx(Label, { htmlFor: id, children: /* @__PURE__ */ jsxs("span", { className: "tw:inline-flex tw:items-center tw:gap-1", children: [
682
- label,
683
- helpIcons
684
- ] }) }),
685
- !showLabel && !isCheckbox && hasHelpIcons && /* @__PURE__ */ jsx("div", { className: "tw:flex tw:items-center tw:gap-1", children: helpIcons }),
686
- isCheckbox && hasHelpIcons ? /* @__PURE__ */ jsxs("div", { className: "tw:flex tw:items-center tw:gap-1", children: [
687
- children,
688
- helpIcons
689
- ] }) : children,
690
- rawDescription && /* @__PURE__ */ jsx(FormGroup.Help, { children: /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: DOMPurify.sanitize(rawDescription) } }) }),
691
- hasErrors && /* @__PURE__ */ jsx(FormGroup.Help, { children: rawErrors.join(". ") })
692
- ] });
709
+ const DocumentationLinkIcon = ({ documentation }) => /* @__PURE__ */ jsx(Tooltip, {
710
+ placement: "top",
711
+ variant: "explanatory",
712
+ tooltip: documentation.tooltip ?? "Open documentation",
713
+ triggerAsChild: true,
714
+ children: /* @__PURE__ */ jsx(Link, {
715
+ href: documentation.link,
716
+ children: /* @__PURE__ */ jsx("span", {
717
+ className: "tw:cursor-pointer tw:text-neutral-400 tw:hover:text-neutral-600",
718
+ children: /* @__PURE__ */ jsx(BookOpen, { className: "tw:size-4" })
719
+ })
720
+ })
721
+ });
722
+ /**
723
+ * Renders the field's FormGroup wrapper, label, help, and errors.
724
+ * Does NOT subscribe to RootFormDataContext — that subscription only happens
725
+ * inside FieldTemplateWithDependencies, so fields without dependencies don't
726
+ * re-render on every form-state change.
727
+ */
728
+ const FieldTemplateBody = ({ id, label, rawHelp, rawDescription, rawErrors, children, schema, uiSchema, displayLabel }) => {
729
+ const widget = uiSchema?.["ui:widget"];
730
+ if (widget === "test-connection" || widget === "sync-action") return /* @__PURE__ */ jsx(Fragment$1, { children });
731
+ if (schema.type === "object") return /* @__PURE__ */ jsx(Fragment$1, { children });
732
+ if (schema.type === "array" && !uiSchema?.["ui:widget"]) return /* @__PURE__ */ jsx(Fragment$1, { children });
733
+ const documentation = (uiSchema?.["ui:options"])?.documentation;
734
+ const hasErrors = rawErrors && rawErrors.length > 0;
735
+ const isCheckbox = schema.type === "boolean" && uiSchema?.["ui:widget"] !== "select";
736
+ const showLabel = displayLabel && label && !isCheckbox;
737
+ const hasHelpIcons = Boolean(rawHelp || documentation);
738
+ const helpIcons = /* @__PURE__ */ jsxs(Fragment$1, { children: [rawHelp && /* @__PURE__ */ jsx(TooltipIcon, { rawHelp }), documentation && /* @__PURE__ */ jsx(DocumentationLinkIcon, { documentation })] });
739
+ return /* @__PURE__ */ jsxs(FormGroup, {
740
+ state: hasErrors ? "error" : "default",
741
+ children: [
742
+ showLabel && /* @__PURE__ */ jsx(Label, {
743
+ htmlFor: id,
744
+ children: /* @__PURE__ */ jsxs("span", {
745
+ className: "tw:inline-flex tw:items-center tw:gap-1",
746
+ children: [label, helpIcons]
747
+ })
748
+ }),
749
+ !showLabel && !isCheckbox && hasHelpIcons && /* @__PURE__ */ jsx("div", {
750
+ className: "tw:flex tw:items-center tw:gap-1",
751
+ children: helpIcons
752
+ }),
753
+ isCheckbox && hasHelpIcons ? /* @__PURE__ */ jsxs("div", {
754
+ className: "tw:flex tw:items-center tw:gap-1",
755
+ children: [children, helpIcons]
756
+ }) : children,
757
+ rawDescription && /* @__PURE__ */ jsx(FormGroup.Help, { children: /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: DOMPurify.sanitize(rawDescription) } }) }),
758
+ hasErrors && /* @__PURE__ */ jsx(FormGroup.Help, { children: rawErrors.join(". ") })
759
+ ]
760
+ });
693
761
  };
694
- var FieldTemplateWithDependencies = ({
695
- dependencies,
696
- ...props
697
- }) => {
698
- const rootFormData = useRootFormData();
699
- const parentPath = props.fieldPathId.path.slice(0, -1);
700
- if (!evaluateDependencies(dependencies, rootFormData, parentPath)) {
701
- return null;
702
- }
703
- return /* @__PURE__ */ jsx(FieldTemplateBody, { ...props });
762
+ /**
763
+ * Wraps FieldTemplateBody with a root-form-data subscription used to evaluate
764
+ * conditional visibility (options.dependencies). Subscribing here — instead of
765
+ * unconditionally in FieldTemplate — keeps fields without dependencies out of
766
+ * the RootFormDataContext consumer set, so they don't re-render on every
767
+ * keystroke. Critical for forms with many fields (e.g. column_mapping tables).
768
+ */
769
+ const FieldTemplateWithDependencies = ({ dependencies, keepMounted, ...props }) => {
770
+ const rootFormData = useRootFormData();
771
+ const parentPath = props.fieldPathId.path.slice(0, -1);
772
+ if (!evaluateDependencies(dependencies, rootFormData, parentPath)) return keepMounted ? /* @__PURE__ */ jsx("div", {
773
+ className: "tw:hidden",
774
+ children: props.children
775
+ }) : null;
776
+ return /* @__PURE__ */ jsx(FieldTemplateBody, { ...props });
704
777
  };
705
- var FieldTemplate = (props) => {
706
- if (props.hidden) return /* @__PURE__ */ jsx("div", { className: "tw:hidden", children: props.children });
707
- if (props.uiSchema?.["ui:widget"] === "template-watch") {
708
- return /* @__PURE__ */ jsx("div", { className: "tw:hidden", children: props.children });
709
- }
710
- const uiOptions = props.uiSchema?.["ui:options"];
711
- const dependencies = uiOptions?.dependencies;
712
- if (dependencies) {
713
- return /* @__PURE__ */ jsx(FieldTemplateWithDependencies, { dependencies, ...props });
714
- }
715
- return /* @__PURE__ */ jsx(FieldTemplateBody, { ...props });
778
+ const FieldTemplate = (props) => {
779
+ if (props.hidden) return /* @__PURE__ */ jsx("div", {
780
+ className: "tw:hidden",
781
+ children: props.children
782
+ });
783
+ const uiOptions = props.uiSchema?.["ui:options"];
784
+ if (isHiddenTemplateWatch(props.uiSchema)) return /* @__PURE__ */ jsx("div", {
785
+ className: "tw:hidden",
786
+ children: props.children
787
+ });
788
+ const dependencies = uiOptions?.dependencies;
789
+ if (dependencies) return /* @__PURE__ */ jsx(FieldTemplateWithDependencies, {
790
+ dependencies,
791
+ keepMounted: props.uiSchema?.["ui:widget"] === "template-watch",
792
+ ...props
793
+ });
794
+ return /* @__PURE__ */ jsx(FieldTemplateBody, { ...props });
716
795
  };
717
- var ObjectFieldTemplate = ({
718
- title,
719
- description,
720
- properties,
721
- formData,
722
- uiSchema,
723
- schema,
724
- fieldPathId
725
- }) => {
726
- const isRoot = !fieldPathId?.path?.length;
727
- const uiOptions = uiSchema?.["ui:options"];
728
- const hasCollapsed = uiOptions?.collapsed !== void 0;
729
- const collapsed = !!uiOptions?.collapsed;
730
- const disableCollapse = !!uiOptions?.disableCollapse;
731
- const lastPathSegment = fieldPathId?.path?.at(-1);
732
- const isArrayItem = typeof lastPathSegment === "number";
733
- const childSchemas = schema.properties;
734
- const isContainerSchema = (s) => {
735
- if (!s) return false;
736
- if (s.properties || s.items) return true;
737
- if (Array.isArray(s.type)) return s.type.includes("object") || s.type.includes("array");
738
- return s.type === "object" || s.type === "array";
739
- };
740
- const visibleProperties = properties.filter((prop) => {
741
- const childUi = uiSchema?.[prop.name];
742
- if (childUi?.["ui:widget"] !== "hidden") return true;
743
- return !isContainerSchema(childSchemas?.[prop.name]);
744
- });
745
- const isHiddenMount = (name) => {
746
- const w = uiSchema?.[name]?.["ui:widget"];
747
- return w === "hidden" || w === "template-watch";
748
- };
749
- const renderChildren = (props) => props.map((prop) => /* @__PURE__ */ jsx("div", { className: isHiddenMount(prop.name) ? "tw:hidden" : void 0, children: prop.content }, prop.name));
750
- if (isRoot) {
751
- return /* @__PURE__ */ jsx("div", { className: "tw:flex tw:flex-col tw:gap-4 tw:[&>div:empty]:hidden", children: renderChildren(visibleProperties) });
752
- }
753
- const childrenContent = renderChildren(visibleProperties);
754
- if (hasCollapsed && !disableCollapse) {
755
- const data = formData ?? {};
756
- const hasValues = Object.values(data).some(
757
- (v) => v !== void 0 && v !== null && v !== "" && v !== false
758
- );
759
- const defaultExpanded = hasValues ? !collapsed : true;
760
- return /* @__PURE__ */ jsxs(
761
- CollapsiblePanel,
762
- {
763
- className: "tw:rounded-lg",
764
- headerClassName: "tw:rounded-lg",
765
- header: title || "Settings",
766
- defaultExpanded,
767
- bodyClassName: "tw:flex tw:flex-col tw:gap-4 tw:[&>div:empty]:hidden",
768
- children: [
769
- description,
770
- childrenContent
771
- ]
772
- }
773
- );
774
- }
775
- if (isArrayItem) {
776
- return /* @__PURE__ */ jsx("div", { className: "tw:flex tw:flex-col tw:gap-4 tw:[&>div:empty]:hidden", children: childrenContent });
777
- }
778
- return /* @__PURE__ */ jsxs("div", { className: "tw:rounded-lg tw:border tw:border-solid tw:border-neutral-200 tw:bg-white tw:p-4", children: [
779
- title && /* @__PURE__ */ jsx("h3", { className: "tw:mb-2 tw:text-base tw:font-medium tw:text-neutral-800", children: title }),
780
- description && /* @__PURE__ */ jsx("p", { className: "tw:mb-3 tw:text-xs tw:text-neutral-400", children: description }),
781
- /* @__PURE__ */ jsx("div", { className: "tw:flex tw:flex-col tw:gap-4 tw:[&>div:empty]:hidden", children: childrenContent })
782
- ] });
796
+ //#endregion
797
+ //#region src/blocks/RjsfSchemaEditor/templates/ObjectFieldTemplate.tsx
798
+ const ObjectFieldTemplate = ({ title, description, properties, formData, uiSchema, schema, fieldPathId }) => {
799
+ const isRoot = !fieldPathId?.path?.length;
800
+ const uiOptions = uiSchema?.["ui:options"];
801
+ const hasCollapsed = uiOptions?.collapsed !== void 0;
802
+ const collapsed = !!uiOptions?.collapsed;
803
+ const disableCollapse = !!uiOptions?.disableCollapse;
804
+ const isArrayItem = typeof fieldPathId?.path?.at(-1) === "number";
805
+ const childSchemas = schema.properties;
806
+ const isContainerSchema = (s) => {
807
+ if (!s) return false;
808
+ if (s.properties || s.items) return true;
809
+ if (Array.isArray(s.type)) return s.type.includes("object") || s.type.includes("array");
810
+ return s.type === "object" || s.type === "array";
811
+ };
812
+ const visibleProperties = properties.filter((prop) => {
813
+ if (uiSchema?.[prop.name]?.["ui:widget"] !== "hidden") return true;
814
+ return !isContainerSchema(childSchemas?.[prop.name]);
815
+ });
816
+ const isHiddenMount = (name) => {
817
+ const childUi = uiSchema?.[name];
818
+ return childUi?.["ui:widget"] === "hidden" || isHiddenTemplateWatch(childUi);
819
+ };
820
+ const renderChildren = (props) => props.map((prop) => /* @__PURE__ */ jsx("div", {
821
+ className: isHiddenMount(prop.name) ? "tw:hidden" : void 0,
822
+ children: prop.content
823
+ }, prop.name));
824
+ if (isRoot) return /* @__PURE__ */ jsx("div", {
825
+ className: "tw:flex tw:flex-col tw:gap-4 tw:[&>div:empty]:hidden",
826
+ children: renderChildren(visibleProperties)
827
+ });
828
+ const childrenContent = renderChildren(visibleProperties);
829
+ if (hasCollapsed && !disableCollapse) {
830
+ const defaultExpanded = Object.values(formData ?? {}).some((v) => v !== void 0 && v !== null && v !== "" && v !== false) ? !collapsed : true;
831
+ return /* @__PURE__ */ jsxs(CollapsiblePanel, {
832
+ className: "tw:rounded-lg",
833
+ headerClassName: "tw:rounded-lg",
834
+ header: title || "Settings",
835
+ defaultExpanded,
836
+ bodyClassName: "tw:flex tw:flex-col tw:gap-4 tw:[&>div:empty]:hidden",
837
+ children: [description, childrenContent]
838
+ });
839
+ }
840
+ if (isArrayItem) return /* @__PURE__ */ jsx("div", {
841
+ className: "tw:flex tw:flex-col tw:gap-4 tw:[&>div:empty]:hidden",
842
+ children: childrenContent
843
+ });
844
+ return /* @__PURE__ */ jsxs("div", {
845
+ className: "tw:rounded-lg tw:border tw:border-solid tw:border-neutral-200 tw:bg-white tw:p-4",
846
+ children: [
847
+ title && /* @__PURE__ */ jsx("h3", {
848
+ className: "tw:mb-2 tw:text-base tw:font-medium tw:text-neutral-800",
849
+ children: title
850
+ }),
851
+ description && /* @__PURE__ */ jsx("p", {
852
+ className: "tw:mb-3 tw:text-xs tw:text-neutral-400",
853
+ children: description
854
+ }),
855
+ /* @__PURE__ */ jsx("div", {
856
+ className: "tw:flex tw:flex-col tw:gap-4 tw:[&>div:empty]:hidden",
857
+ children: childrenContent
858
+ })
859
+ ]
860
+ });
783
861
  };
784
- var CheckboxWidget = ({
785
- id,
786
- value,
787
- onChange,
788
- disabled,
789
- readonly,
790
- label,
791
- hideLabel
792
- }) => {
793
- const checked = !!value;
794
- return /* @__PURE__ */ jsx(Checkbox, { id, checked, onCheckedChange: onChange, disabled: disabled || readonly, children: hideLabel ? void 0 : label });
862
+ //#endregion
863
+ //#region src/blocks/RjsfSchemaEditor/widgets/CheckboxWidget.tsx
864
+ const CheckboxWidget = ({ id, value, onChange, disabled, readonly, label, hideLabel }) => {
865
+ return /* @__PURE__ */ jsx(Checkbox, {
866
+ id,
867
+ checked: !!value,
868
+ onCheckedChange: onChange,
869
+ disabled: disabled || readonly,
870
+ children: hideLabel ? void 0 : label
871
+ });
795
872
  };
796
- var DateWidget = ({
797
- id,
798
- value,
799
- onChange,
800
- onBlur,
801
- onFocus,
802
- disabled,
803
- readonly,
804
- placeholder,
805
- rawErrors
806
- }) => {
807
- const dateValue = (() => {
808
- if (!value) return null;
809
- const parts = value.split("-").map(Number);
810
- const [year, month, day] = parts;
811
- if (parts.length !== 3 || parts.some(Number.isNaN)) return null;
812
- if (year === void 0 || month === void 0 || day === void 0) return null;
813
- return new Date(year, month - 1, day);
814
- })();
815
- const isValid = dateValue && !Number.isNaN(dateValue.getTime());
816
- return /* @__PURE__ */ jsx(
817
- DateInput,
818
- {
819
- id,
820
- value: isValid ? dateValue : null,
821
- onValueChange: (date) => {
822
- if (!date) {
823
- onChange(void 0);
824
- return;
825
- }
826
- const year = date.getFullYear();
827
- const month = String(date.getMonth() + 1).padStart(2, "0");
828
- const day = String(date.getDate()).padStart(2, "0");
829
- onChange(`${year}-${month}-${day}`);
830
- },
831
- onBlur: () => onBlur(id, value),
832
- onFocus: () => onFocus(id, value),
833
- disabled: disabled || readonly,
834
- placeholder: placeholder || "Select a date",
835
- state: rawErrors?.length ? "error" : "default",
836
- variant: "secondary"
837
- }
838
- );
873
+ //#endregion
874
+ //#region src/blocks/RjsfSchemaEditor/widgets/DateWidget.tsx
875
+ const DateWidget = ({ id, value, onChange, onBlur, onFocus, disabled, readonly, placeholder, rawErrors }) => {
876
+ const dateValue = (() => {
877
+ if (!value) return null;
878
+ const parts = value.split("-").map(Number);
879
+ const [year, month, day] = parts;
880
+ if (parts.length !== 3 || parts.some(Number.isNaN)) return null;
881
+ if (year === void 0 || month === void 0 || day === void 0) return null;
882
+ return new Date(year, month - 1, day);
883
+ })();
884
+ const isValid = dateValue && !Number.isNaN(dateValue.getTime());
885
+ return /* @__PURE__ */ jsx(DateInput, {
886
+ id,
887
+ value: isValid ? dateValue : null,
888
+ onValueChange: (date) => {
889
+ if (!date) {
890
+ onChange(void 0);
891
+ return;
892
+ }
893
+ onChange(`${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`);
894
+ },
895
+ onBlur: () => onBlur(id, value),
896
+ onFocus: () => onFocus(id, value),
897
+ disabled: disabled || readonly,
898
+ placeholder: placeholder || "Select a date",
899
+ state: rawErrors?.length ? "error" : "default",
900
+ variant: "secondary"
901
+ });
839
902
  };
840
- var DynamicSelectWidget = ({
841
- value,
842
- onChange,
843
- disabled,
844
- readonly,
845
- options: widgetOptions
846
- }) => {
847
- const data = useRootFormData();
848
- const watch = widgetOptions.watch;
849
- const enumSource = widgetOptions.enumSource;
850
- const dynamicItems = watch ? buildDynamicOptions(watch, enumSource, data) : [];
851
- const stringValue = value == null ? "" : String(value);
852
- const matched = dynamicItems.find((item) => item.value === stringValue);
853
- const fallbackItem = !matched && stringValue !== "" ? { value: stringValue, label: stringValue } : null;
854
- const selectedItem = matched ?? fallbackItem;
855
- const items = fallbackItem ? [fallbackItem, ...dynamicItems] : dynamicItems;
856
- return /* @__PURE__ */ jsx(
857
- Combobox,
858
- {
859
- variant: "secondary",
860
- items,
861
- value: selectedItem,
862
- disabled: disabled || readonly,
863
- onValueChange: (selected) => onChange(selected?.value ?? "")
864
- }
865
- );
903
+ //#endregion
904
+ //#region src/blocks/RjsfSchemaEditor/widgets/DynamicSelectWidget.tsx
905
+ /**
906
+ * Widget for fields using json-editor's enumSource/watch pattern.
907
+ * Reads options dynamically from the root form data based on watched paths.
908
+ */
909
+ const DynamicSelectWidget = ({ value, onChange, disabled, readonly, options: widgetOptions }) => {
910
+ const data = useRootFormData();
911
+ const watch = widgetOptions.watch;
912
+ const enumSource = widgetOptions.enumSource;
913
+ const dynamicItems = watch ? buildDynamicOptions(watch, enumSource, data) : [];
914
+ const stringValue = value == null ? "" : String(value);
915
+ const matched = dynamicItems.find((item) => item.value === stringValue);
916
+ const fallbackItem = !matched && stringValue !== "" ? {
917
+ value: stringValue,
918
+ label: stringValue
919
+ } : null;
920
+ const selectedItem = matched ?? fallbackItem;
921
+ const items = fallbackItem ? [fallbackItem, ...dynamicItems] : dynamicItems;
922
+ return /* @__PURE__ */ jsx(Combobox, {
923
+ variant: "secondary",
924
+ items,
925
+ value: selectedItem,
926
+ disabled: disabled || readonly,
927
+ onValueChange: (selected) => onChange(selected?.value ?? "")
928
+ });
866
929
  };
867
- var NumberWidget = ({
868
- id,
869
- value,
870
- onChange,
871
- onBlur,
872
- onFocus,
873
- disabled,
874
- readonly,
875
- placeholder,
876
- schema,
877
- rawErrors
878
- }) => {
879
- return /* @__PURE__ */ jsx(
880
- NumberInput,
881
- {
882
- id,
883
- value: value ?? null,
884
- onValueChange: (num) => onChange(num ?? void 0),
885
- onBlur: () => onBlur(id, value),
886
- onFocus: () => onFocus(id, value),
887
- disabled: disabled || readonly,
888
- placeholder,
889
- min: schema.minimum,
890
- max: schema.maximum,
891
- step: schema.multipleOf,
892
- state: rawErrors?.length ? "error" : "default",
893
- variant: "secondary"
894
- }
895
- );
930
+ //#endregion
931
+ //#region src/blocks/RjsfSchemaEditor/widgets/NumberWidget.tsx
932
+ const NumberWidget = ({ id, value, onChange, onBlur, onFocus, disabled, readonly, placeholder, schema, rawErrors }) => {
933
+ return /* @__PURE__ */ jsx(NumberInput, {
934
+ id,
935
+ value: value ?? null,
936
+ onValueChange: (num) => onChange(num ?? void 0),
937
+ onBlur: () => onBlur(id, value),
938
+ onFocus: () => onFocus(id, value),
939
+ disabled: disabled || readonly,
940
+ placeholder,
941
+ min: schema.minimum,
942
+ max: schema.maximum,
943
+ step: schema.multipleOf,
944
+ state: rawErrors?.length ? "error" : "default",
945
+ variant: "secondary"
946
+ });
896
947
  };
897
- var PasswordWidget = ({
898
- id,
899
- value,
900
- onChange,
901
- onBlur,
902
- onFocus,
903
- disabled,
904
- readonly,
905
- placeholder,
906
- rawErrors
907
- }) => {
908
- const stringValue = value == null ? "" : String(value);
909
- return /* @__PURE__ */ jsx(
910
- PasswordInput,
911
- {
912
- id,
913
- value: stringValue,
914
- onValueChange: onChange,
915
- onBlur: () => onBlur(id, value),
916
- onFocus: () => onFocus(id, value),
917
- disabled: disabled || readonly,
918
- placeholder,
919
- allowPasswordToggle: true,
920
- state: rawErrors?.length ? "error" : "default",
921
- variant: "secondary"
922
- }
923
- );
948
+ //#endregion
949
+ //#region src/blocks/RjsfSchemaEditor/widgets/PasswordWidget.tsx
950
+ const PasswordWidget = ({ id, value, onChange, onBlur, onFocus, disabled, readonly, placeholder, rawErrors }) => {
951
+ return /* @__PURE__ */ jsx(PasswordInput, {
952
+ id,
953
+ value: value == null ? "" : String(value),
954
+ onValueChange: onChange,
955
+ onBlur: () => onBlur(id, value),
956
+ onFocus: () => onFocus(id, value),
957
+ disabled: disabled || readonly,
958
+ placeholder,
959
+ allowPasswordToggle: true,
960
+ state: rawErrors?.length ? "error" : "default",
961
+ variant: "secondary"
962
+ });
924
963
  };
925
- var RadioWidget = ({ id, value, onChange, disabled, readonly, options }) => {
926
- const enumOptions = options.enumOptions ?? [];
927
- return /* @__PURE__ */ jsx(
928
- RadioGroup,
929
- {
930
- id,
931
- value: value ?? "",
932
- onValueChange: onChange,
933
- disabled: disabled || readonly,
934
- orientation: "vertical",
935
- children: enumOptions.map((opt) => /* @__PURE__ */ jsx(RadioGroup.Item, { value: opt.value, children: opt.label }, opt.value))
936
- }
937
- );
964
+ //#endregion
965
+ //#region src/blocks/RjsfSchemaEditor/widgets/RadioWidget.tsx
966
+ const RadioWidget = ({ id, value, onChange, disabled, readonly, options }) => {
967
+ const enumOptions = options.enumOptions ?? [];
968
+ return /* @__PURE__ */ jsx(RadioGroup, {
969
+ id,
970
+ value: value ?? "",
971
+ onValueChange: onChange,
972
+ disabled: disabled || readonly,
973
+ orientation: "vertical",
974
+ children: enumOptions.map((opt) => /* @__PURE__ */ jsx(RadioGroup.Item, {
975
+ value: opt.value,
976
+ children: opt.label
977
+ }, opt.value))
978
+ });
938
979
  };
939
- var SelectWidget = ({
940
- value,
941
- schema,
942
- onChange,
943
- disabled,
944
- readonly,
945
- options,
946
- placeholder,
947
- required
948
- }) => {
949
- const enumOptions = options.enumOptions ?? [];
950
- const isBoolean = schema.type === "boolean";
951
- const items = enumOptions.map((o) => ({
952
- value: String(o.value ?? ""),
953
- label: o.label
954
- }));
955
- const selectedItem = items.find((item) => item.value === (value == null ? "" : String(value)));
956
- return /* @__PURE__ */ jsx(
957
- Combobox,
958
- {
959
- variant: "secondary",
960
- items,
961
- value: selectedItem ?? null,
962
- allowClear: !required,
963
- disabled: disabled || readonly,
964
- placeholder,
965
- onValueChange: (selected) => {
966
- const selectedValue = selected?.value ?? "";
967
- if (isBoolean) {
968
- onChange(selectedValue === "true");
969
- return;
970
- }
971
- onChange(selectedValue);
972
- }
973
- }
974
- );
980
+ //#endregion
981
+ //#region src/blocks/RjsfSchemaEditor/widgets/SelectWidget.tsx
982
+ const SelectWidget = ({ value, schema, onChange, disabled, readonly, options, placeholder, required }) => {
983
+ const enumOptions = options.enumOptions ?? [];
984
+ const isBoolean = schema.type === "boolean";
985
+ const items = enumOptions.map((o) => ({
986
+ value: String(o.value ?? ""),
987
+ label: o.label
988
+ }));
989
+ const selectedItem = items.find((item) => item.value === (value == null ? "" : String(value)));
990
+ return /* @__PURE__ */ jsx(Combobox, {
991
+ variant: "secondary",
992
+ items,
993
+ value: selectedItem ?? null,
994
+ allowClear: !required,
995
+ disabled: disabled || readonly,
996
+ placeholder,
997
+ onValueChange: (selected) => {
998
+ const selectedValue = selected?.value ?? "";
999
+ if (isBoolean) {
1000
+ onChange(selectedValue === "true");
1001
+ return;
1002
+ }
1003
+ onChange(selectedValue);
1004
+ }
1005
+ });
975
1006
  };
976
- var resolveTemplate = (template, watch, rootFormData) => {
977
- return template.replace(/\{\{(\w+)\}\}/g, (_, varName) => {
978
- const watchPath = watch[varName];
979
- if (!watchPath) return "";
980
- const value = resolveByPath(watchPath, rootFormData);
981
- return value == null ? "" : String(value);
982
- });
1007
+ //#endregion
1008
+ //#region src/blocks/RjsfSchemaEditor/widgets/TemplateWatchWidget.tsx
1009
+ /**
1010
+ * Renders a watched value as text.
1011
+ *
1012
+ * - Objects and arrays are serialized as JSON; anything else goes through `String`.
1013
+ * - `null` and `undefined` render as an empty string.
1014
+ */
1015
+ const stringify = (value) => {
1016
+ if (value == null) return "";
1017
+ if (typeof value === "object") return JSON.stringify(value);
1018
+ return String(value);
983
1019
  };
984
- var TemplateWatchWidget = ({ value, onChange, options: widgetOptions }) => {
985
- const data = useRootFormData();
986
- const watch = widgetOptions.watch;
987
- const template = widgetOptions.template;
988
- const computed = watch && template ? resolveTemplate(template, watch, data) : value ?? "";
989
- const lastSetRef = useRef(String(value ?? ""));
990
- useEffect(() => {
991
- const computedStr = String(computed);
992
- if (computedStr !== lastSetRef.current) {
993
- lastSetRef.current = computedStr;
994
- onChange(computedStr);
995
- }
996
- }, [computed, onChange]);
997
- return null;
1020
+ /**
1021
+ * Resolves a json-editor `template` string by substituting watched variables.
1022
+ * e.g. template="{{val}}" with watch={ val: "some.path" } → resolves "some.path" from form data.
1023
+ */
1024
+ const resolveTemplate = (template, watch, rootFormData) => {
1025
+ return template.replace(/\{\{(\w+)\}\}/g, (_, varName) => {
1026
+ const watchPath = watch[varName];
1027
+ if (!watchPath) return "";
1028
+ return stringify(resolveByPath(watchPath, rootFormData));
1029
+ });
998
1030
  };
999
- var TextareaWidget = ({
1000
- id,
1001
- value,
1002
- onChange,
1003
- onBlur,
1004
- onFocus,
1005
- disabled,
1006
- readonly,
1007
- placeholder,
1008
- options,
1009
- rawErrors
1010
- }) => {
1011
- const rows = options.rows ?? 5;
1012
- const stringValue = value == null ? "" : String(value);
1013
- return /* @__PURE__ */ jsx(
1014
- Textarea,
1015
- {
1016
- id,
1017
- value: stringValue,
1018
- onValueChange: onChange,
1019
- onBlur: () => onBlur(id, value),
1020
- onFocus: () => onFocus(id, value),
1021
- disabled: disabled || readonly,
1022
- placeholder,
1023
- minRows: rows,
1024
- state: rawErrors?.length ? "error" : "default",
1025
- variant: "secondary"
1026
- }
1027
- );
1031
+ /**
1032
+ * Widget for json-editor's `template`/`watch` pattern (without `enumSource`).
1033
+ * Computes a value from watched form data paths and keeps the field in sync.
1034
+ *
1035
+ * - With `options.hidden` it renders nothing — a helper for cross-object dependencies.
1036
+ * - Without it, the value is shown in a read-only input; `FieldTemplate` supplies the label.
1037
+ */
1038
+ const TemplateWatchWidget = ({ id, value, onChange, disabled, readonly, rawErrors, options: widgetOptions }) => {
1039
+ const data = useRootFormData();
1040
+ const watch = widgetOptions.watch;
1041
+ const template = widgetOptions.template;
1042
+ const computed = watch && template ? resolveTemplate(template, watch, data) : stringify(value);
1043
+ const lastSetRef = useRef(stringify(value));
1044
+ useEffect(() => {
1045
+ if (computed !== lastSetRef.current) {
1046
+ lastSetRef.current = computed;
1047
+ onChange(computed);
1048
+ }
1049
+ }, [computed, onChange]);
1050
+ if (widgetOptions.hidden) return null;
1051
+ return /* @__PURE__ */ jsx(TextInput, {
1052
+ id,
1053
+ value: computed,
1054
+ readOnly: true,
1055
+ disabled: disabled || readonly,
1056
+ state: rawErrors?.length ? "error" : "default",
1057
+ variant: "secondary"
1058
+ });
1028
1059
  };
1029
- var TextWidget = ({
1030
- id,
1031
- value,
1032
- onChange,
1033
- onBlur,
1034
- onFocus,
1035
- disabled,
1036
- readonly,
1037
- placeholder,
1038
- schema,
1039
- options,
1040
- rawErrors
1041
- }) => {
1042
- const stringValue = value == null ? "" : typeof value === "object" ? "" : String(value);
1043
- const shouldTrim = !!options.trim;
1044
- return /* @__PURE__ */ jsx(
1045
- TextInput,
1046
- {
1047
- id,
1048
- value: stringValue,
1049
- onChange: (e) => {
1050
- const v = e.target.value;
1051
- onChange(shouldTrim ? v.trim() : v);
1052
- },
1053
- onBlur: () => onBlur(id, value),
1054
- onFocus: () => onFocus(id, value),
1055
- disabled: disabled || readonly,
1056
- placeholder,
1057
- type: schema.format === "email" ? "email" : "text",
1058
- state: rawErrors?.length ? "error" : "default",
1059
- variant: "secondary"
1060
- }
1061
- );
1060
+ //#endregion
1061
+ //#region src/blocks/RjsfSchemaEditor/widgets/TextareaWidget.tsx
1062
+ const TextareaWidget = ({ id, value, onChange, onBlur, onFocus, disabled, readonly, placeholder, options, rawErrors }) => {
1063
+ const rows = options.rows ?? 5;
1064
+ return /* @__PURE__ */ jsx(Textarea, {
1065
+ id,
1066
+ value: value == null ? "" : String(value),
1067
+ onValueChange: onChange,
1068
+ onBlur: () => onBlur(id, value),
1069
+ onFocus: () => onFocus(id, value),
1070
+ disabled: disabled || readonly,
1071
+ placeholder,
1072
+ minRows: rows,
1073
+ state: rawErrors?.length ? "error" : "default",
1074
+ variant: "secondary"
1075
+ });
1062
1076
  };
1063
-
1064
- // src/blocks/RjsfSchemaEditor/registry.ts
1065
- var StubWidget = () => null;
1066
- var StubField = () => null;
1067
- var defaultFields = {
1068
- tableArray: TableArrayField,
1069
- tabsObject: TabsObjectField,
1070
- gridObject: GridObjectField,
1071
- codeEditor: CodeEditorField,
1072
- info: InfoField,
1073
- sshForm: StubField
1077
+ //#endregion
1078
+ //#region src/blocks/RjsfSchemaEditor/widgets/TextWidget.tsx
1079
+ const TextWidget = ({ id, value, onChange, onBlur, onFocus, disabled, readonly, placeholder, schema, options, rawErrors }) => {
1080
+ const stringValue = value == null ? "" : typeof value === "object" ? "" : String(value);
1081
+ const shouldTrim = !!options.trim;
1082
+ return /* @__PURE__ */ jsx(TextInput, {
1083
+ id,
1084
+ value: stringValue,
1085
+ onChange: (e) => {
1086
+ const v = e.target.value;
1087
+ onChange(shouldTrim ? v.trim() : v);
1088
+ },
1089
+ onBlur: () => onBlur(id, value),
1090
+ onFocus: () => onFocus(id, value),
1091
+ disabled: disabled || readonly,
1092
+ placeholder,
1093
+ type: schema.format === "email" ? "email" : "text",
1094
+ state: rawErrors?.length ? "error" : "default",
1095
+ variant: "secondary"
1096
+ });
1074
1097
  };
1075
- var defaultWidgets = {
1076
- // Override RJSF defaults with design system components
1077
- TextWidget,
1078
- UpDownWidget: NumberWidget,
1079
- TextareaWidget,
1080
- PasswordWidget,
1081
- SelectWidget,
1082
- CheckboxWidget,
1083
- RadioWidget,
1084
- // RJSF maps standard formats to dedicated widgets
1085
- EmailWidget: TextWidget,
1086
- URLWidget: TextWidget,
1087
- DateWidget,
1088
- DateTimeWidget: TextWidget,
1089
- // Custom widgets mapped via uiSchema
1090
- "code-editor": CodeEditorWidget,
1091
- "dynamic-select": DynamicSelectWidget,
1092
- "template-watch": TemplateWatchWidget,
1093
- // Host-coupled widgets — injected by the host app
1094
- "test-connection": StubWidget,
1095
- "sync-action": StubWidget,
1096
- "async-select": StubWidget,
1097
- "async-multi-select": StubWidget
1098
+ //#endregion
1099
+ //#region src/blocks/RjsfSchemaEditor/registry.ts
1100
+ const StubWidget = () => null;
1101
+ const StubField = () => null;
1102
+ const defaultFields = {
1103
+ tableArray: TableArrayField,
1104
+ tabsObject: TabsObjectField,
1105
+ gridObject: GridObjectField,
1106
+ codeEditor: CodeEditorField,
1107
+ info: InfoField,
1108
+ sshForm: StubField
1098
1109
  };
1099
- var defaultTemplates = {
1100
- FieldTemplate,
1101
- ObjectFieldTemplate,
1102
- DescriptionFieldTemplate,
1103
- ArrayFieldTemplate,
1104
- ArrayFieldItemTemplate,
1105
- ErrorListTemplate
1110
+ const defaultWidgets = {
1111
+ TextWidget,
1112
+ UpDownWidget: NumberWidget,
1113
+ TextareaWidget,
1114
+ PasswordWidget,
1115
+ SelectWidget,
1116
+ CheckboxWidget,
1117
+ RadioWidget,
1118
+ EmailWidget: TextWidget,
1119
+ URLWidget: TextWidget,
1120
+ DateWidget,
1121
+ DateTimeWidget: TextWidget,
1122
+ "code-editor": CodeEditorWidget,
1123
+ "dynamic-select": DynamicSelectWidget,
1124
+ "template-watch": TemplateWatchWidget,
1125
+ "test-connection": StubWidget,
1126
+ "sync-action": StubWidget,
1127
+ "async-select": StubWidget,
1128
+ "async-multi-select": StubWidget
1106
1129
  };
1107
-
1108
- // src/blocks/RjsfSchemaEditor/schemaUtils.ts
1109
- var resolveRef = (propSchema, definitions) => {
1110
- if (!propSchema.$ref || !definitions) return propSchema;
1111
- const refPath = String(propSchema.$ref).replace("#/definitions/", "");
1112
- const resolved = definitions[refPath];
1113
- if (!resolved) return propSchema;
1114
- const { $ref, ...overrides } = propSchema;
1115
- return { ...resolved, ...overrides };
1130
+ const defaultTemplates = {
1131
+ FieldTemplate,
1132
+ ObjectFieldTemplate,
1133
+ DescriptionFieldTemplate,
1134
+ ArrayFieldTemplate,
1135
+ ArrayFieldItemTemplate,
1136
+ ErrorListTemplate
1116
1137
  };
1117
- var generateUiSchema = (schema, readOnly = false, definitions, globalConfig, hasProtectedDefaultBranch = false) => {
1118
- const uiSchema = {};
1119
- const defs = definitions ?? schema.definitions;
1120
- if (readOnly) {
1121
- uiSchema["ui:disabled"] = true;
1122
- }
1123
- const properties = schema.properties;
1124
- if (!properties) ; else {
1125
- for (const [key, rawPropSchema] of Object.entries(properties)) {
1126
- const propSchema = resolveRef(rawPropSchema, defs);
1127
- const format = propSchema.format;
1128
- const type = propSchema.type ?? (propSchema.properties ? "object" : void 0);
1129
- const options = propSchema.options;
1130
- const fieldUi = {};
1131
- if (options?.hidden) {
1132
- fieldUi["ui:widget"] = "hidden";
1133
- }
1134
- if (type === "array" && format === "table") {
1135
- fieldUi["ui:field"] = "tableArray";
1136
- }
1137
- if (type === "array" && format === "checkbox") {
1138
- fieldUi["ui:widget"] = "checkboxes";
1139
- }
1140
- if (format === "radio" && propSchema.enum) {
1141
- fieldUi["ui:widget"] = "radio";
1142
- }
1143
- if (type === "object" && (format === "tabs" || format === "tabs-top" || format === "categories")) {
1144
- fieldUi["ui:field"] = "tabsObject";
1145
- }
1146
- if (type === "object" && (format === "grid" || format === "grid-strict")) {
1147
- fieldUi["ui:field"] = "gridObject";
1148
- }
1149
- if (format === "info") {
1150
- fieldUi["ui:field"] = "info";
1151
- if (options?.alert_type) {
1152
- fieldUi["ui:options"] = {
1153
- ...fieldUi["ui:options"],
1154
- alertType: options.alert_type
1155
- };
1156
- }
1157
- }
1158
- if (type === "button" && format === "test-connection") {
1159
- fieldUi["ui:widget"] = "test-connection";
1160
- fieldUi["ui:options"] = options ?? {};
1161
- } else if (type === "button" && format === "sync-action") {
1162
- fieldUi["ui:widget"] = "sync-action";
1163
- fieldUi["ui:options"] = options ?? {};
1164
- } else if ((type === "string" || type === "object") && format === "editor") {
1165
- if (type === "object") {
1166
- fieldUi["ui:field"] = "codeEditor";
1167
- } else {
1168
- fieldUi["ui:widget"] = "code-editor";
1169
- }
1170
- fieldUi["ui:options"] = {
1171
- editor: options?.editor ?? {},
1172
- // A JSON editor stores parsed keys, so `#` prefixes really are encrypted here.
1173
- // Fields whose JSON is not Keboola configuration (a query filter tree, a payload
1174
- // template) opt out with `encryption_hint: false` — encrypting a key there would
1175
- // hand the component ciphertext it cannot use.
1176
- encryptionHint: options?.encryption_hint !== false
1177
- };
1178
- } else if (type === "object" && format === "ssh-editor") {
1179
- fieldUi["ui:field"] = "sshForm";
1180
- fieldUi["ui:options"] = { only_keys: !!options?.only_keys };
1181
- } else if (type === "string" && format === "password") {
1182
- if (!hasProtectedDefaultBranch) {
1183
- fieldUi["ui:widget"] = "password";
1184
- }
1185
- } else if (type === "string" && format === "textarea") {
1186
- fieldUi["ui:widget"] = "textarea";
1187
- if (options?.input_height) {
1188
- fieldUi["ui:options"] = {
1189
- ...fieldUi["ui:options"],
1190
- rows: parseInputHeightToRows(String(options.input_height))
1191
- };
1192
- }
1193
- } else if (type === "string" && format === "trim") {
1194
- fieldUi["ui:options"] = {
1195
- ...fieldUi["ui:options"],
1196
- trim: true
1197
- };
1198
- } else if (isDynamicSelectSchema(propSchema)) {
1199
- fieldUi["ui:widget"] = "dynamic-select";
1200
- fieldUi["ui:options"] = {
1201
- ...fieldUi["ui:options"],
1202
- watch: propSchema.watch,
1203
- enumSource: propSchema.enumSource,
1204
- tags: !!options?.tags
1205
- };
1206
- } else if (isMultiSelectSchema(propSchema)) {
1207
- const items = propSchema.items;
1208
- const itemsOptions = items?.options;
1209
- fieldUi["ui:widget"] = "async-multi-select";
1210
- fieldUi["ui:options"] = {
1211
- async: options?.async ?? itemsOptions?.async ?? null,
1212
- creatable: !!options?.creatable || !!options?.tags,
1213
- placeholder: String(
1214
- options?.inputAttributes?.placeholder ?? ""
1215
- ),
1216
- // Pass dynamic source from items for enumSource/watch multi-selects
1217
- ...items?.watch && { watch: items.watch },
1218
- ...items?.enumSource && { enumSource: items.enumSource }
1219
- };
1220
- } else if (isAsyncSelectSchema(propSchema)) {
1221
- fieldUi["ui:widget"] = "async-select";
1222
- fieldUi["ui:options"] = {
1223
- async: options?.async ?? null,
1224
- creatable: !!options?.creatable,
1225
- placeholder: String(
1226
- options?.inputAttributes?.placeholder ?? ""
1227
- )
1228
- };
1229
- }
1230
- if (isTemplateWatchSchema(propSchema)) {
1231
- fieldUi["ui:widget"] = "template-watch";
1232
- fieldUi["ui:options"] = {
1233
- ...fieldUi["ui:options"],
1234
- watch: propSchema.watch,
1235
- template: propSchema.template
1236
- };
1237
- }
1238
- if (type === "boolean" && options?.enum_titles) {
1239
- fieldUi["ui:widget"] = "select";
1240
- }
1241
- if (options?.collapsed !== void 0) {
1242
- fieldUi["ui:options"] = {
1243
- ...fieldUi["ui:options"],
1244
- collapsed: !!options.collapsed
1245
- };
1246
- }
1247
- if (options?.disable_collapse) {
1248
- fieldUi["ui:options"] = {
1249
- ...fieldUi["ui:options"],
1250
- disableCollapse: true
1251
- };
1252
- }
1253
- if (options?.dependencies) {
1254
- fieldUi["ui:options"] = {
1255
- ...fieldUi["ui:options"],
1256
- dependencies: options.dependencies
1257
- };
1258
- }
1259
- if (options?.grid_break) {
1260
- fieldUi["ui:options"] = {
1261
- ...fieldUi["ui:options"],
1262
- gridBreak: true
1263
- };
1264
- }
1265
- if (options?.enabled === false) {
1266
- fieldUi["ui:disabled"] = true;
1267
- }
1268
- const globalValue = globalConfig?.[key];
1269
- if (globalValue !== void 0) {
1270
- if (typeof globalValue !== "object" || globalValue === null || Array.isArray(globalValue)) {
1271
- fieldUi["ui:disabled"] = true;
1272
- }
1273
- }
1274
- if (options?.tooltip) {
1275
- fieldUi["ui:help"] = String(options.tooltip);
1276
- }
1277
- if (options?.documentation?.link) {
1278
- fieldUi["ui:options"] = {
1279
- ...fieldUi["ui:options"],
1280
- documentation: options?.documentation
1281
- };
1282
- }
1283
- if (options?.inputAttributes?.placeholder && !fieldUi["ui:widget"]) {
1284
- fieldUi["ui:placeholder"] = String(
1285
- options?.inputAttributes?.placeholder
1286
- );
1287
- }
1288
- if (options?.enum_titles && propSchema.enum) {
1289
- fieldUi["ui:options"] = {
1290
- ...fieldUi["ui:options"],
1291
- enumNames: options.enum_titles
1292
- };
1293
- }
1294
- if (type === "array") {
1295
- const arrayOpts = {};
1296
- if (options?.disable_array_add) arrayOpts.addable = false;
1297
- if (options?.disable_array_delete) arrayOpts.removable = false;
1298
- if (options?.disable_array_reorder) arrayOpts.orderable = false;
1299
- if (Object.keys(arrayOpts).length > 0) {
1300
- fieldUi["ui:options"] = {
1301
- ...fieldUi["ui:options"],
1302
- ...arrayOpts
1303
- };
1304
- }
1305
- const itemsEnumTitles = propSchema.items?.options?.enum_titles;
1306
- if (Array.isArray(itemsEnumTitles)) {
1307
- fieldUi.items = { "ui:options": { enumNames: itemsEnumTitles } };
1308
- }
1309
- }
1310
- if (type === "object" && propSchema.properties) {
1311
- const nestedGlobal = globalValue && typeof globalValue === "object" && !Array.isArray(globalValue) ? globalValue : void 0;
1312
- const nested = generateUiSchema(
1313
- propSchema,
1314
- readOnly,
1315
- defs,
1316
- nestedGlobal,
1317
- hasProtectedDefaultBranch
1318
- );
1319
- Object.assign(fieldUi, nested);
1320
- }
1321
- if (type === "array" && propSchema.items?.properties) {
1322
- const itemsUi = generateUiSchema(
1323
- propSchema.items,
1324
- readOnly,
1325
- defs,
1326
- void 0,
1327
- hasProtectedDefaultBranch
1328
- );
1329
- if (Object.keys(itemsUi).length > 0) {
1330
- fieldUi.items = itemsUi;
1331
- }
1332
- }
1333
- if ((propSchema.enumSource || propSchema.watch) && !fieldUi["ui:widget"]) {
1334
- console.warn(
1335
- `[RJSF] Property "${key}" uses enumSource/watch which is not yet supported. It will render as a plain input.`
1336
- );
1337
- }
1338
- if (Object.keys(fieldUi).length > 0) {
1339
- uiSchema[key] = fieldUi;
1340
- }
1341
- }
1342
- const orderedEntries = Object.entries(properties).filter(([, prop]) => prop.propertyOrder !== void 0).sort(
1343
- ([, a], [, b]) => (a.propertyOrder ?? Number.MAX_SAFE_INTEGER) - (b.propertyOrder ?? Number.MAX_SAFE_INTEGER)
1344
- );
1345
- if (orderedEntries.length > 0) {
1346
- uiSchema["ui:order"] = [...orderedEntries.map(([key]) => key), "*"];
1347
- }
1348
- }
1349
- for (const combiner of ["allOf", "anyOf", "oneOf"]) {
1350
- const schemas = schema[combiner];
1351
- if (schemas) {
1352
- for (const subSchema of schemas) {
1353
- const subUi = generateUiSchema(
1354
- subSchema,
1355
- readOnly,
1356
- void 0,
1357
- void 0,
1358
- hasProtectedDefaultBranch
1359
- );
1360
- Object.assign(uiSchema, subUi);
1361
- }
1362
- }
1363
- }
1364
- for (const branch of ["if", "then", "else"]) {
1365
- const branchSchema = schema[branch];
1366
- if (branchSchema?.properties) {
1367
- const branchUi = generateUiSchema(
1368
- branchSchema,
1369
- readOnly,
1370
- void 0,
1371
- void 0,
1372
- hasProtectedDefaultBranch
1373
- );
1374
- Object.assign(uiSchema, branchUi);
1375
- }
1376
- }
1377
- return uiSchema;
1138
+ //#endregion
1139
+ //#region src/blocks/RjsfSchemaEditor/schemaUtils.ts
1140
+ /**
1141
+ * Resolves a $ref reference against the schema definitions, merging any
1142
+ * sibling overrides (title, options, etc.) on top of the resolved schema.
1143
+ */
1144
+ const resolveRef = (propSchema, definitions) => {
1145
+ if (!propSchema.$ref || !definitions) return propSchema;
1146
+ const resolved = definitions[String(propSchema.$ref).replace("#/definitions/", "")];
1147
+ if (!resolved) return propSchema;
1148
+ const { $ref, ...overrides } = propSchema;
1149
+ return {
1150
+ ...resolved,
1151
+ ...overrides
1152
+ };
1378
1153
  };
1379
- var isDynamicSelectSchema = (schema) => {
1380
- return !!(schema.enumSource && schema.watch && schema.type === "string");
1154
+ /**
1155
+ * Walks a JSON Schema and generates a RJSF uiSchema based on custom `format` and `options` properties.
1156
+ * This maps the legacy @json-editor/json-editor conventions to RJSF widget references.
1157
+ */
1158
+ const generateUiSchema = (schema, readOnly = false, definitions, globalConfig, hasProtectedDefaultBranch = false) => {
1159
+ const uiSchema = {};
1160
+ const defs = definitions ?? schema.definitions;
1161
+ if (readOnly) uiSchema["ui:disabled"] = true;
1162
+ const properties = schema.properties;
1163
+ if (!properties) {} else {
1164
+ for (const [key, rawPropSchema] of Object.entries(properties)) {
1165
+ const propSchema = resolveRef(rawPropSchema, defs);
1166
+ const format = propSchema.format;
1167
+ const type = propSchema.type ?? (propSchema.properties ? "object" : void 0);
1168
+ const options = propSchema.options;
1169
+ const fieldUi = {};
1170
+ if (options?.hidden) fieldUi["ui:widget"] = "hidden";
1171
+ if (type === "array" && format === "table") fieldUi["ui:field"] = "tableArray";
1172
+ if (type === "array" && format === "checkbox") fieldUi["ui:widget"] = "checkboxes";
1173
+ if (format === "radio" && propSchema.enum) fieldUi["ui:widget"] = "radio";
1174
+ if (type === "object" && (format === "tabs" || format === "tabs-top" || format === "categories")) fieldUi["ui:field"] = "tabsObject";
1175
+ if (type === "object" && (format === "grid" || format === "grid-strict")) fieldUi["ui:field"] = "gridObject";
1176
+ if (format === "info") {
1177
+ fieldUi["ui:field"] = "info";
1178
+ if (options?.alert_type) fieldUi["ui:options"] = {
1179
+ ...fieldUi["ui:options"],
1180
+ alertType: options.alert_type
1181
+ };
1182
+ }
1183
+ if (type === "button" && format === "test-connection") {
1184
+ fieldUi["ui:widget"] = "test-connection";
1185
+ fieldUi["ui:options"] = options ?? {};
1186
+ } else if (type === "button" && format === "sync-action") {
1187
+ fieldUi["ui:widget"] = "sync-action";
1188
+ fieldUi["ui:options"] = options ?? {};
1189
+ } else if ((type === "string" || type === "object") && format === "editor") {
1190
+ if (type === "object") fieldUi["ui:field"] = "codeEditor";
1191
+ else fieldUi["ui:widget"] = "code-editor";
1192
+ fieldUi["ui:options"] = {
1193
+ editor: options?.editor ?? {},
1194
+ encryptionHint: options?.encryption_hint !== false
1195
+ };
1196
+ } else if (type === "object" && format === "ssh-editor") {
1197
+ fieldUi["ui:field"] = "sshForm";
1198
+ fieldUi["ui:options"] = { only_keys: !!options?.only_keys };
1199
+ } else if (type === "string" && format === "password") {
1200
+ if (!hasProtectedDefaultBranch) fieldUi["ui:widget"] = "password";
1201
+ } else if (type === "string" && format === "textarea") {
1202
+ fieldUi["ui:widget"] = "textarea";
1203
+ if (options?.input_height) fieldUi["ui:options"] = {
1204
+ ...fieldUi["ui:options"],
1205
+ rows: parseInputHeightToRows(String(options.input_height))
1206
+ };
1207
+ } else if (type === "string" && format === "trim") fieldUi["ui:options"] = {
1208
+ ...fieldUi["ui:options"],
1209
+ trim: true
1210
+ };
1211
+ else if (isDynamicSelectSchema(propSchema)) {
1212
+ fieldUi["ui:widget"] = "dynamic-select";
1213
+ fieldUi["ui:options"] = {
1214
+ ...fieldUi["ui:options"],
1215
+ watch: propSchema.watch,
1216
+ enumSource: propSchema.enumSource,
1217
+ tags: !!options?.tags
1218
+ };
1219
+ } else if (isMultiSelectSchema(propSchema)) {
1220
+ const items = propSchema.items;
1221
+ const itemsOptions = items?.options;
1222
+ fieldUi["ui:widget"] = "async-multi-select";
1223
+ fieldUi["ui:options"] = {
1224
+ async: options?.async ?? itemsOptions?.async ?? null,
1225
+ creatable: !!options?.creatable || !!options?.tags,
1226
+ placeholder: String((options?.inputAttributes)?.placeholder ?? ""),
1227
+ ...items?.watch && { watch: items.watch },
1228
+ ...items?.enumSource && { enumSource: items.enumSource }
1229
+ };
1230
+ } else if (isAsyncSelectSchema(propSchema)) {
1231
+ fieldUi["ui:widget"] = "async-select";
1232
+ fieldUi["ui:options"] = {
1233
+ async: options?.async ?? null,
1234
+ creatable: !!options?.creatable,
1235
+ placeholder: String((options?.inputAttributes)?.placeholder ?? "")
1236
+ };
1237
+ }
1238
+ if (isTemplateWatchSchema(propSchema)) {
1239
+ fieldUi["ui:widget"] = "template-watch";
1240
+ fieldUi["ui:options"] = {
1241
+ ...fieldUi["ui:options"],
1242
+ watch: propSchema.watch,
1243
+ template: propSchema.template,
1244
+ hidden: !!options?.hidden || isContainerType(propSchema)
1245
+ };
1246
+ }
1247
+ if (type === "boolean" && options?.enum_titles) fieldUi["ui:widget"] = "select";
1248
+ if (options?.collapsed !== void 0) fieldUi["ui:options"] = {
1249
+ ...fieldUi["ui:options"],
1250
+ collapsed: !!options.collapsed
1251
+ };
1252
+ if (options?.disable_collapse) fieldUi["ui:options"] = {
1253
+ ...fieldUi["ui:options"],
1254
+ disableCollapse: true
1255
+ };
1256
+ if (options?.dependencies) fieldUi["ui:options"] = {
1257
+ ...fieldUi["ui:options"],
1258
+ dependencies: options.dependencies
1259
+ };
1260
+ if (options?.grid_break) fieldUi["ui:options"] = {
1261
+ ...fieldUi["ui:options"],
1262
+ gridBreak: true
1263
+ };
1264
+ if (options?.enabled === false) fieldUi["ui:disabled"] = true;
1265
+ const globalValue = globalConfig?.[key];
1266
+ if (globalValue !== void 0) {
1267
+ if (typeof globalValue !== "object" || globalValue === null || Array.isArray(globalValue)) fieldUi["ui:disabled"] = true;
1268
+ }
1269
+ if (options?.tooltip) fieldUi["ui:help"] = String(options.tooltip);
1270
+ if ((options?.documentation)?.link) fieldUi["ui:options"] = {
1271
+ ...fieldUi["ui:options"],
1272
+ documentation: options?.documentation
1273
+ };
1274
+ if ((options?.inputAttributes)?.placeholder && !fieldUi["ui:widget"]) fieldUi["ui:placeholder"] = String((options?.inputAttributes)?.placeholder);
1275
+ if (options?.enum_titles && propSchema.enum) fieldUi["ui:options"] = {
1276
+ ...fieldUi["ui:options"],
1277
+ enumNames: options.enum_titles
1278
+ };
1279
+ if (type === "array") {
1280
+ const arrayOpts = {};
1281
+ if (options?.disable_array_add) arrayOpts.addable = false;
1282
+ if (options?.disable_array_delete) arrayOpts.removable = false;
1283
+ if (options?.disable_array_reorder) arrayOpts.orderable = false;
1284
+ if (Object.keys(arrayOpts).length > 0) fieldUi["ui:options"] = {
1285
+ ...fieldUi["ui:options"],
1286
+ ...arrayOpts
1287
+ };
1288
+ const itemsEnumTitles = (propSchema.items?.options)?.enum_titles;
1289
+ if (Array.isArray(itemsEnumTitles)) fieldUi.items = { "ui:options": { enumNames: itemsEnumTitles } };
1290
+ }
1291
+ if (type === "object" && propSchema.properties) {
1292
+ const nested = generateUiSchema(propSchema, readOnly, defs, globalValue && typeof globalValue === "object" && !Array.isArray(globalValue) ? globalValue : void 0, hasProtectedDefaultBranch);
1293
+ Object.assign(fieldUi, nested);
1294
+ }
1295
+ if (type === "array" && propSchema.items?.properties) {
1296
+ const itemsUi = generateUiSchema(propSchema.items, readOnly, defs, void 0, hasProtectedDefaultBranch);
1297
+ if (Object.keys(itemsUi).length > 0) fieldUi.items = itemsUi;
1298
+ }
1299
+ if ((propSchema.enumSource || propSchema.watch) && !fieldUi["ui:widget"]) console.warn(`[RJSF] Property "${key}" uses enumSource/watch which is not yet supported. It will render as a plain input.`);
1300
+ if (Object.keys(fieldUi).length > 0) uiSchema[key] = fieldUi;
1301
+ }
1302
+ const orderedEntries = Object.entries(properties).filter(([, prop]) => prop.propertyOrder !== void 0).sort(([, a], [, b]) => (a.propertyOrder ?? Number.MAX_SAFE_INTEGER) - (b.propertyOrder ?? Number.MAX_SAFE_INTEGER));
1303
+ if (orderedEntries.length > 0) uiSchema["ui:order"] = [...orderedEntries.map(([key]) => key), "*"];
1304
+ }
1305
+ for (const combiner of [
1306
+ "allOf",
1307
+ "anyOf",
1308
+ "oneOf"
1309
+ ]) {
1310
+ const schemas = schema[combiner];
1311
+ if (schemas) for (const subSchema of schemas) {
1312
+ const subUi = generateUiSchema(subSchema, readOnly, void 0, void 0, hasProtectedDefaultBranch);
1313
+ Object.assign(uiSchema, subUi);
1314
+ }
1315
+ }
1316
+ for (const branch of [
1317
+ "if",
1318
+ "then",
1319
+ "else"
1320
+ ]) {
1321
+ const branchSchema = schema[branch];
1322
+ if (branchSchema?.properties) {
1323
+ const branchUi = generateUiSchema(branchSchema, readOnly, void 0, void 0, hasProtectedDefaultBranch);
1324
+ Object.assign(uiSchema, branchUi);
1325
+ }
1326
+ }
1327
+ return uiSchema;
1381
1328
  };
1382
- var isTemplateWatchSchema = (schema) => {
1383
- return !!(schema.template && schema.watch && !schema.enumSource);
1329
+ const isDynamicSelectSchema = (schema) => {
1330
+ return !!(schema.enumSource && schema.watch && schema.type === "string");
1384
1331
  };
1385
- var isAsyncSelectSchema = (schema) => {
1386
- return !!(schema.options?.async || schema.options?.creatable);
1332
+ const isTemplateWatchSchema = (schema) => {
1333
+ return !!(schema.template && schema.watch && !schema.enumSource);
1387
1334
  };
1388
- var isMultiSelectSchema = (schema) => {
1389
- const items = schema.items;
1390
- return !!(items && schema.uniqueItems && schema.type === "array" && schema.format !== "checkbox" && !Array.isArray(items) && ["string", "number", "integer"].includes(items.type) && (items.enum || items.enumSource || schema.options?.tags));
1335
+ /**
1336
+ * Whether a schema describes an object or an array.
1337
+ *
1338
+ * - `properties` or `items` imply the type even when json-editor omits it.
1339
+ * - `type` may be a union, e.g. `['object', 'null']`.
1340
+ */
1341
+ const isContainerType = (schema) => {
1342
+ if (schema.properties || schema.items) return true;
1343
+ const { type } = schema;
1344
+ if (Array.isArray(type)) return type.includes("object") || type.includes("array");
1345
+ return type === "object" || type === "array";
1391
1346
  };
1392
- var parseInputHeightToRows = (height) => {
1393
- const px = parseInt(height, 10);
1394
- if (Number.isNaN(px) || px <= 0) return 5;
1395
- return Math.max(2, Math.round(px / 20));
1347
+ const isAsyncSelectSchema = (schema) => {
1348
+ return !!(schema.options?.async || schema.options?.creatable);
1396
1349
  };
1397
- var CUSTOM_FORMATS = [
1398
- "table",
1399
- "editor",
1400
- "ssh-editor",
1401
- "trim",
1402
- "textarea",
1403
- "grid",
1404
- "grid-strict",
1405
- "tabs",
1406
- "tabs-top",
1407
- "categories",
1408
- "info",
1409
- "select",
1410
- "checkbox",
1411
- "json",
1412
- "button",
1413
- "radio"
1350
+ const isMultiSelectSchema = (schema) => {
1351
+ const items = schema.items;
1352
+ return !!(items && schema.uniqueItems && schema.type === "array" && schema.format !== "checkbox" && !Array.isArray(items) && [
1353
+ "string",
1354
+ "number",
1355
+ "integer"
1356
+ ].includes(items.type) && (items.enum || items.enumSource || schema.options?.tags));
1357
+ };
1358
+ /**
1359
+ * Cleans up non-standard properties from a schema before passing to RJSF/AJV.
1360
+ * RJSF is strict about unknown keywords, and our schemas contain json-editor-specific
1361
+ * extensions (format: 'button', options, etc.).
1362
+ */
1363
+ /** Convert CSS height like "100px" to approximate textarea rows */
1364
+ const parseInputHeightToRows = (height) => {
1365
+ const px = parseInt(height, 10);
1366
+ if (Number.isNaN(px) || px <= 0) return 5;
1367
+ return Math.max(2, Math.round(px / 20));
1368
+ };
1369
+ const CUSTOM_FORMATS = [
1370
+ "table",
1371
+ "editor",
1372
+ "ssh-editor",
1373
+ "trim",
1374
+ "textarea",
1375
+ "grid",
1376
+ "grid-strict",
1377
+ "tabs",
1378
+ "tabs-top",
1379
+ "categories",
1380
+ "info",
1381
+ "select",
1382
+ "checkbox",
1383
+ "json",
1384
+ "button",
1385
+ "radio"
1414
1386
  ];
1415
- var sanitizeSchema = (schema, definitions, isConditionalBranch = false) => {
1416
- const cleaned = { ...schema };
1417
- const defs = definitions ?? cleaned.definitions;
1418
- if (Array.isArray(cleaned.enum) && cleaned.enum.length === 0) {
1419
- delete cleaned.enum;
1420
- }
1421
- if (Array.isArray(cleaned.enum) && cleaned.enum.length > 0 && (cleaned.type === "string" || cleaned.type === "integer" || cleaned.type === "number")) {
1422
- if (cleaned.default === void 0) {
1423
- cleaned.default = cleaned.enum[0];
1424
- } else if (!cleaned.enum.includes(cleaned.default)) {
1425
- delete cleaned.default;
1426
- }
1427
- }
1428
- if (cleaned.properties && !cleaned.type) {
1429
- cleaned.type = "object";
1430
- }
1431
- if (cleaned.required === true) {
1432
- delete cleaned.required;
1433
- }
1434
- if (CUSTOM_FORMATS.includes(cleaned.format)) {
1435
- delete cleaned.format;
1436
- }
1437
- const properties = cleaned.properties;
1438
- if (properties) {
1439
- const sanitizedProps = {};
1440
- const required = cleaned.required ?? [];
1441
- const sanitizedRequired = [];
1442
- for (const [key, rawPropSchema] of Object.entries(properties)) {
1443
- const propSchema = resolveRef(rawPropSchema, defs);
1444
- if (propSchema.type === "button") {
1445
- sanitizedProps[key] = {
1446
- type: "string",
1447
- title: propSchema.title,
1448
- ...propSchema.propertyOrder !== void 0 && {
1449
- propertyOrder: propSchema.propertyOrder
1450
- },
1451
- ...propSchema.description !== void 0 && { description: propSchema.description }
1452
- };
1453
- continue;
1454
- }
1455
- if (propSchema.type === "boolean" && propSchema.options?.enum_titles) {
1456
- const titles = propSchema.options.enum_titles;
1457
- const sanitized = sanitizeSchema(propSchema, defs);
1458
- const enumValues = propSchema.enum ?? [true, false];
1459
- sanitized.oneOf = enumValues.map((value, index) => ({
1460
- const: value,
1461
- title: titles[index] ?? (value ? "Yes" : "No")
1462
- }));
1463
- sanitizedProps[key] = sanitized;
1464
- if (required.includes(key) || propSchema.required === true) {
1465
- if (!sanitizedRequired.includes(key)) sanitizedRequired.push(key);
1466
- }
1467
- continue;
1468
- }
1469
- sanitizedProps[key] = sanitizeSchema(propSchema, defs);
1470
- if (required.includes(key) || propSchema.required === true) {
1471
- if (!sanitizedRequired.includes(key)) sanitizedRequired.push(key);
1472
- }
1473
- }
1474
- cleaned.properties = sanitizedProps;
1475
- if (sanitizedRequired.length > 0) {
1476
- cleaned.required = sanitizedRequired;
1477
- }
1478
- if (!isConditionalBranch && cleaned.additionalProperties === void 0 && !cleaned.if) {
1479
- cleaned.additionalProperties = false;
1480
- }
1481
- }
1482
- for (const combiner of ["allOf", "anyOf", "oneOf"]) {
1483
- const schemas = cleaned[combiner];
1484
- if (schemas) {
1485
- cleaned[combiner] = schemas.map((s) => sanitizeSchema(s, defs));
1486
- }
1487
- }
1488
- for (const branch of ["if", "then", "else"]) {
1489
- const branchSchema = cleaned[branch];
1490
- if (branchSchema) {
1491
- cleaned[branch] = sanitizeSchema(branchSchema, defs, true);
1492
- }
1493
- }
1494
- if (cleaned.items && typeof cleaned.items === "object" && !Array.isArray(cleaned.items)) {
1495
- cleaned.items = sanitizeSchema(cleaned.items, defs);
1496
- }
1497
- return cleaned;
1387
+ const sanitizeSchema = (schema, definitions, isConditionalBranch = false) => {
1388
+ const cleaned = { ...schema };
1389
+ const defs = definitions ?? cleaned.definitions;
1390
+ if (Array.isArray(cleaned.enum) && cleaned.enum.length === 0) delete cleaned.enum;
1391
+ if (Array.isArray(cleaned.enum) && cleaned.enum.length > 0 && (cleaned.type === "string" || cleaned.type === "integer" || cleaned.type === "number")) {
1392
+ if (cleaned.default === void 0) cleaned.default = cleaned.enum[0];
1393
+ else if (!cleaned.enum.includes(cleaned.default)) delete cleaned.default;
1394
+ }
1395
+ if (cleaned.properties && !cleaned.type) cleaned.type = "object";
1396
+ if (cleaned.required === true) delete cleaned.required;
1397
+ if (CUSTOM_FORMATS.includes(cleaned.format)) delete cleaned.format;
1398
+ const properties = cleaned.properties;
1399
+ if (properties) {
1400
+ const sanitizedProps = {};
1401
+ const required = cleaned.required ?? [];
1402
+ const sanitizedRequired = [];
1403
+ for (const [key, rawPropSchema] of Object.entries(properties)) {
1404
+ const propSchema = resolveRef(rawPropSchema, defs);
1405
+ if (propSchema.type === "button") {
1406
+ sanitizedProps[key] = {
1407
+ type: "string",
1408
+ title: propSchema.title,
1409
+ ...propSchema.propertyOrder !== void 0 && { propertyOrder: propSchema.propertyOrder },
1410
+ ...propSchema.description !== void 0 && { description: propSchema.description }
1411
+ };
1412
+ continue;
1413
+ }
1414
+ if (propSchema.type === "boolean" && propSchema.options?.enum_titles) {
1415
+ const titles = propSchema.options.enum_titles;
1416
+ const sanitized = sanitizeSchema(propSchema, defs);
1417
+ sanitized.oneOf = (propSchema.enum ?? [true, false]).map((value, index) => ({
1418
+ const: value,
1419
+ title: titles[index] ?? (value ? "Yes" : "No")
1420
+ }));
1421
+ sanitizedProps[key] = sanitized;
1422
+ if (required.includes(key) || propSchema.required === true) {
1423
+ if (!sanitizedRequired.includes(key)) sanitizedRequired.push(key);
1424
+ }
1425
+ continue;
1426
+ }
1427
+ sanitizedProps[key] = sanitizeSchema(propSchema, defs);
1428
+ if (required.includes(key) || propSchema.required === true) {
1429
+ if (!sanitizedRequired.includes(key)) sanitizedRequired.push(key);
1430
+ }
1431
+ }
1432
+ cleaned.properties = sanitizedProps;
1433
+ if (sanitizedRequired.length > 0) cleaned.required = sanitizedRequired;
1434
+ if (!isConditionalBranch && cleaned.additionalProperties === void 0 && !cleaned.if) cleaned.additionalProperties = false;
1435
+ }
1436
+ for (const combiner of [
1437
+ "allOf",
1438
+ "anyOf",
1439
+ "oneOf"
1440
+ ]) {
1441
+ const schemas = cleaned[combiner];
1442
+ if (schemas) cleaned[combiner] = schemas.map((s) => sanitizeSchema(s, defs));
1443
+ }
1444
+ for (const branch of [
1445
+ "if",
1446
+ "then",
1447
+ "else"
1448
+ ]) {
1449
+ const branchSchema = cleaned[branch];
1450
+ if (branchSchema) cleaned[branch] = sanitizeSchema(branchSchema, defs, true);
1451
+ }
1452
+ if (cleaned.items && typeof cleaned.items === "object" && !Array.isArray(cleaned.items)) cleaned.items = sanitizeSchema(cleaned.items, defs);
1453
+ return cleaned;
1498
1454
  };
1499
- var defaultRenderMarkdown = (source) => source;
1500
- var stableStringify = (obj) => JSON.stringify(obj, (_key, val) => {
1501
- if (val && typeof val === "object" && !Array.isArray(val)) {
1502
- const sorted = {};
1503
- for (const key of Object.keys(val).sort()) {
1504
- sorted[key] = val[key];
1505
- }
1506
- return sorted;
1507
- }
1508
- return val;
1455
+ //#endregion
1456
+ //#region src/blocks/RjsfSchemaEditor/RjsfSchemaEditor.tsx
1457
+ const defaultRenderMarkdown = (source) => source;
1458
+ /**
1459
+ * Produces a canonical JSON string with sorted keys at every level.
1460
+ * This ensures two objects with the same data but different key ordering
1461
+ * produce the same string. Also normalizes undefined → omitted (via JSON.stringify).
1462
+ */
1463
+ const stableStringify = (obj) => JSON.stringify(obj, (_key, val) => {
1464
+ if (val && typeof val === "object" && !Array.isArray(val)) {
1465
+ const sorted = {};
1466
+ for (const key of Object.keys(val).sort()) sorted[key] = val[key];
1467
+ return sorted;
1468
+ }
1469
+ return val;
1509
1470
  });
1510
- var RjsfSchemaEditor = ({
1511
- schema,
1512
- value,
1513
- onChange,
1514
- readOnly,
1515
- inForm,
1516
- globalConfig,
1517
- onRegisterValidate,
1518
- widgets,
1519
- fields,
1520
- renderMarkdown,
1521
- hasProtectedDefaultBranch = false
1522
- }) => {
1523
- const schemaJs = useMemo(() => sanitizeSchema(schema), [schema]);
1524
- const uiSchema = useMemo(
1525
- () => generateUiSchema(
1526
- schema,
1527
- readOnly,
1528
- void 0,
1529
- globalConfig ?? void 0,
1530
- hasProtectedDefaultBranch
1531
- ),
1532
- [schema, readOnly, globalConfig, hasProtectedDefaultBranch]
1533
- );
1534
- const mergedWidgets = useMemo(() => ({ ...defaultWidgets, ...widgets }), [widgets]);
1535
- const mergedFields = useMemo(() => ({ ...defaultFields, ...fields }), [fields]);
1536
- const initialDataRef = useRef(value);
1537
- const formDataRef = useRef(initialDataRef.current);
1538
- const [formKey, setFormKey] = useState(0);
1539
- const [hasValidated, setHasValidated] = useState(false);
1540
- const [rootFormData, setRootFormData] = useState(initialDataRef.current);
1541
- const mountedFormDataJsonRef = useRef(null);
1542
- const isInitialMountRef = useRef(true);
1543
- useEffect(() => {
1544
- isInitialMountRef.current = false;
1545
- }, [formKey]);
1546
- const onChangeRef = useRef(onChange);
1547
- onChangeRef.current = onChange;
1548
- const valueRef = useRef(value);
1549
- valueRef.current = value;
1550
- const lastSentJsonRef = useRef(null);
1551
- const debouncedOnChange = useMemo(
1552
- () => debounce((data) => {
1553
- const dataJson = stableStringify(data);
1554
- const storeJson = stableStringify(valueRef.current);
1555
- if (dataJson !== storeJson) {
1556
- if (lastSentJsonRef.current === null && mountedFormDataJsonRef.current && dataJson === mountedFormDataJsonRef.current) {
1557
- return;
1558
- }
1559
- lastSentJsonRef.current = dataJson;
1560
- onChangeRef.current(data);
1561
- }
1562
- }, 100),
1563
- []
1564
- );
1565
- useEffect(() => () => debouncedOnChange.cancel(), [debouncedOnChange]);
1566
- const [prevValue, setPrevValue] = useState(value);
1567
- if (value !== prevValue) {
1568
- setPrevValue(value);
1569
- const incomingJson = stableStringify(value);
1570
- if (incomingJson !== stableStringify(prevValue)) {
1571
- if (lastSentJsonRef.current && lastSentJsonRef.current === incomingJson) {
1572
- lastSentJsonRef.current = null;
1573
- } else {
1574
- debouncedOnChange.cancel();
1575
- lastSentJsonRef.current = null;
1576
- initialDataRef.current = value;
1577
- formDataRef.current = value;
1578
- isInitialMountRef.current = true;
1579
- mountedFormDataJsonRef.current = null;
1580
- setFormKey((k) => k + 1);
1581
- }
1582
- }
1583
- }
1584
- const handleChange = useCallback(
1585
- (e) => {
1586
- if (!e.formData) return;
1587
- formDataRef.current = e.formData;
1588
- setRootFormData(e.formData);
1589
- if (isInitialMountRef.current) {
1590
- mountedFormDataJsonRef.current = stableStringify(e.formData);
1591
- return;
1592
- }
1593
- debouncedOnChange(e.formData);
1594
- },
1595
- [debouncedOnChange]
1596
- );
1597
- const debouncedOnChangeRef = useRef(debouncedOnChange);
1598
- debouncedOnChangeRef.current = debouncedOnChange;
1599
- const setRootFormDataRef = useRef(setRootFormData);
1600
- setRootFormDataRef.current = setRootFormData;
1601
- const formContext = useMemo(
1602
- () => ({
1603
- setFormData: (data) => {
1604
- const merged = { ...formDataRef.current, ...data };
1605
- initialDataRef.current = merged;
1606
- formDataRef.current = merged;
1607
- setRootFormDataRef.current(merged);
1608
- debouncedOnChangeRef.current.cancel();
1609
- lastSentJsonRef.current = stableStringify(merged);
1610
- onChangeRef.current(merged);
1611
- isInitialMountRef.current = true;
1612
- mountedFormDataJsonRef.current = null;
1613
- setFormKey((k) => k + 1);
1614
- },
1615
- getFormData: () => formDataRef.current
1616
- }),
1617
- []
1618
- // stable — uses refs for all external values
1619
- );
1620
- const formRef = useRef(null);
1621
- useEffect(() => {
1622
- if (onRegisterValidate) {
1623
- onRegisterValidate(() => {
1624
- setHasValidated(true);
1625
- return formRef.current?.validateForm() ?? true;
1626
- });
1627
- }
1628
- }, [onRegisterValidate, formKey]);
1629
- return /* @__PURE__ */ jsx("div", { className: "json-editor", children: /* @__PURE__ */ jsx(RenderMarkdownProvider, { value: renderMarkdown ?? defaultRenderMarkdown, children: /* @__PURE__ */ jsx(RootFormDataProvider, { value: rootFormData, children: /* @__PURE__ */ jsx(
1630
- Form,
1631
- {
1632
- ref: formRef,
1633
- schema: schemaJs,
1634
- initialFormData: initialDataRef.current,
1635
- uiSchema,
1636
- validator,
1637
- onChange: handleChange,
1638
- widgets: mergedWidgets,
1639
- fields: mergedFields,
1640
- templates: defaultTemplates,
1641
- formContext,
1642
- disabled: readOnly,
1643
- liveValidate: hasValidated ? "onBlur" : void 0,
1644
- showErrorList: false,
1645
- noHtml5Validate: true,
1646
- tagName: inForm ? "div" : "form",
1647
- children: /* @__PURE__ */ jsx(Fragment, {})
1648
- },
1649
- formKey
1650
- ) }) }) });
1471
+ const RjsfSchemaEditor = ({ schema, value, onChange, readOnly, inForm, globalConfig, onRegisterValidate, widgets, fields, renderMarkdown, hasProtectedDefaultBranch = false }) => {
1472
+ const schemaJs = useMemo(() => sanitizeSchema(schema), [schema]);
1473
+ const uiSchema = useMemo(() => generateUiSchema(schema, readOnly, void 0, globalConfig ?? void 0, hasProtectedDefaultBranch), [
1474
+ schema,
1475
+ readOnly,
1476
+ globalConfig,
1477
+ hasProtectedDefaultBranch
1478
+ ]);
1479
+ const mergedWidgets = useMemo(() => ({
1480
+ ...defaultWidgets,
1481
+ ...widgets
1482
+ }), [widgets]);
1483
+ const mergedFields = useMemo(() => ({
1484
+ ...defaultFields,
1485
+ ...fields
1486
+ }), [fields]);
1487
+ const initialDataRef = useRef(value);
1488
+ const formDataRef = useRef(initialDataRef.current);
1489
+ const [formKey, setFormKey] = useState(0);
1490
+ const [hasValidated, setHasValidated] = useState(false);
1491
+ const [rootFormData, setRootFormData] = useState(initialDataRef.current);
1492
+ const mountedFormDataJsonRef = useRef(null);
1493
+ const isInitialMountRef = useRef(true);
1494
+ useEffect(() => {
1495
+ isInitialMountRef.current = false;
1496
+ }, [formKey]);
1497
+ const onChangeRef = useRef(onChange);
1498
+ onChangeRef.current = onChange;
1499
+ const valueRef = useRef(value);
1500
+ valueRef.current = value;
1501
+ const lastSentJsonRef = useRef(null);
1502
+ const debouncedOnChange = useMemo(() => debounce((data) => {
1503
+ const dataJson = stableStringify(data);
1504
+ if (dataJson !== stableStringify(valueRef.current)) {
1505
+ if (lastSentJsonRef.current === null && mountedFormDataJsonRef.current && dataJson === mountedFormDataJsonRef.current) return;
1506
+ lastSentJsonRef.current = dataJson;
1507
+ onChangeRef.current(data);
1508
+ }
1509
+ }, 100), []);
1510
+ useEffect(() => () => debouncedOnChange.cancel(), [debouncedOnChange]);
1511
+ const [prevValue, setPrevValue] = useState(value);
1512
+ if (value !== prevValue) {
1513
+ setPrevValue(value);
1514
+ const incomingJson = stableStringify(value);
1515
+ if (incomingJson !== stableStringify(prevValue)) {
1516
+ if (lastSentJsonRef.current && lastSentJsonRef.current === incomingJson) lastSentJsonRef.current = null;
1517
+ else {
1518
+ debouncedOnChange.cancel();
1519
+ lastSentJsonRef.current = null;
1520
+ initialDataRef.current = value;
1521
+ formDataRef.current = value;
1522
+ isInitialMountRef.current = true;
1523
+ mountedFormDataJsonRef.current = null;
1524
+ setFormKey((k) => k + 1);
1525
+ }
1526
+ }
1527
+ }
1528
+ const handleChange = useCallback((e) => {
1529
+ if (!e.formData) return;
1530
+ formDataRef.current = e.formData;
1531
+ setRootFormData(e.formData);
1532
+ if (isInitialMountRef.current) {
1533
+ mountedFormDataJsonRef.current = stableStringify(e.formData);
1534
+ return;
1535
+ }
1536
+ debouncedOnChange(e.formData);
1537
+ }, [debouncedOnChange]);
1538
+ const debouncedOnChangeRef = useRef(debouncedOnChange);
1539
+ debouncedOnChangeRef.current = debouncedOnChange;
1540
+ const setRootFormDataRef = useRef(setRootFormData);
1541
+ setRootFormDataRef.current = setRootFormData;
1542
+ const formContext = useMemo(() => ({
1543
+ setFormData: (data) => {
1544
+ const merged = {
1545
+ ...formDataRef.current,
1546
+ ...data
1547
+ };
1548
+ initialDataRef.current = merged;
1549
+ formDataRef.current = merged;
1550
+ setRootFormDataRef.current(merged);
1551
+ debouncedOnChangeRef.current.cancel();
1552
+ lastSentJsonRef.current = stableStringify(merged);
1553
+ onChangeRef.current(merged);
1554
+ isInitialMountRef.current = true;
1555
+ mountedFormDataJsonRef.current = null;
1556
+ setFormKey((k) => k + 1);
1557
+ },
1558
+ getFormData: () => formDataRef.current
1559
+ }), []);
1560
+ const formRef = useRef(null);
1561
+ useEffect(() => {
1562
+ if (onRegisterValidate) onRegisterValidate(() => {
1563
+ setHasValidated(true);
1564
+ return formRef.current?.validateForm() ?? true;
1565
+ });
1566
+ }, [onRegisterValidate, formKey]);
1567
+ return /* @__PURE__ */ jsx("div", {
1568
+ className: "json-editor",
1569
+ children: /* @__PURE__ */ jsx(RenderMarkdownProvider, {
1570
+ value: renderMarkdown ?? defaultRenderMarkdown,
1571
+ children: /* @__PURE__ */ jsx(RootFormDataProvider, {
1572
+ value: rootFormData,
1573
+ children: /* @__PURE__ */ jsx(Form, {
1574
+ ref: formRef,
1575
+ schema: schemaJs,
1576
+ initialFormData: initialDataRef.current,
1577
+ uiSchema,
1578
+ validator,
1579
+ onChange: handleChange,
1580
+ widgets: mergedWidgets,
1581
+ fields: mergedFields,
1582
+ templates: defaultTemplates,
1583
+ formContext,
1584
+ disabled: readOnly,
1585
+ liveValidate: hasValidated ? "onBlur" : void 0,
1586
+ showErrorList: false,
1587
+ noHtml5Validate: true,
1588
+ tagName: inForm ? "div" : "form",
1589
+ children: /* @__PURE__ */ jsx(Fragment$1, {})
1590
+ }, formKey)
1591
+ })
1592
+ })
1593
+ });
1651
1594
  };
1652
-
1595
+ //#endregion
1653
1596
  export { RjsfSchemaEditor, buildDynamicOptions, resolveByPath, useRootFormData };
1654
- //# sourceMappingURL=rjsf.js.map
1597
+
1655
1598
  //# sourceMappingURL=rjsf.js.map