@flanksource/clicky-ui 0.2.21 → 0.3.2

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 (522) hide show
  1. package/dist/comments/CommentAuthor.cjs +58 -0
  2. package/dist/comments/CommentAuthor.cjs.map +1 -0
  3. package/dist/comments/CommentAuthor.d.ts +17 -0
  4. package/dist/comments/CommentAuthor.d.ts.map +1 -0
  5. package/dist/comments/CommentAuthor.js +58 -0
  6. package/dist/comments/CommentAuthor.js.map +1 -0
  7. package/dist/comments/CommentCard.cjs +343 -0
  8. package/dist/comments/CommentCard.cjs.map +1 -0
  9. package/dist/comments/CommentCard.d.ts +27 -0
  10. package/dist/comments/CommentCard.d.ts.map +1 -0
  11. package/dist/comments/CommentCard.js +343 -0
  12. package/dist/comments/CommentCard.js.map +1 -0
  13. package/dist/comments/CommentComposer.cjs +207 -0
  14. package/dist/comments/CommentComposer.cjs.map +1 -0
  15. package/dist/comments/CommentComposer.d.ts +23 -0
  16. package/dist/comments/CommentComposer.d.ts.map +1 -0
  17. package/dist/comments/CommentComposer.js +207 -0
  18. package/dist/comments/CommentComposer.js.map +1 -0
  19. package/dist/comments/CommentFilterBar.cjs +145 -0
  20. package/dist/comments/CommentFilterBar.cjs.map +1 -0
  21. package/dist/comments/CommentFilterBar.d.ts +15 -0
  22. package/dist/comments/CommentFilterBar.d.ts.map +1 -0
  23. package/dist/comments/CommentFilterBar.js +145 -0
  24. package/dist/comments/CommentFilterBar.js.map +1 -0
  25. package/dist/comments/CommentMarkdown.cjs +156 -0
  26. package/dist/comments/CommentMarkdown.cjs.map +1 -0
  27. package/dist/comments/CommentMarkdown.d.ts +13 -0
  28. package/dist/comments/CommentMarkdown.d.ts.map +1 -0
  29. package/dist/comments/CommentMarkdown.js +156 -0
  30. package/dist/comments/CommentMarkdown.js.map +1 -0
  31. package/dist/comments/CommentProgress.cjs +86 -0
  32. package/dist/comments/CommentProgress.cjs.map +1 -0
  33. package/dist/comments/CommentProgress.d.ts +16 -0
  34. package/dist/comments/CommentProgress.d.ts.map +1 -0
  35. package/dist/comments/CommentProgress.js +86 -0
  36. package/dist/comments/CommentProgress.js.map +1 -0
  37. package/dist/comments/CommentProvider.cjs +99 -0
  38. package/dist/comments/CommentProvider.cjs.map +1 -0
  39. package/dist/comments/CommentProvider.d.ts +19 -0
  40. package/dist/comments/CommentProvider.d.ts.map +1 -0
  41. package/dist/comments/CommentProvider.js +99 -0
  42. package/dist/comments/CommentProvider.js.map +1 -0
  43. package/dist/comments/CommentSidePanel.cjs +219 -0
  44. package/dist/comments/CommentSidePanel.cjs.map +1 -0
  45. package/dist/comments/CommentSidePanel.d.ts +16 -0
  46. package/dist/comments/CommentSidePanel.d.ts.map +1 -0
  47. package/dist/comments/CommentSidePanel.js +219 -0
  48. package/dist/comments/CommentSidePanel.js.map +1 -0
  49. package/dist/comments/CommentThread.cjs +57 -0
  50. package/dist/comments/CommentThread.cjs.map +1 -0
  51. package/dist/comments/CommentThread.d.ts +24 -0
  52. package/dist/comments/CommentThread.d.ts.map +1 -0
  53. package/dist/comments/CommentThread.js +57 -0
  54. package/dist/comments/CommentThread.js.map +1 -0
  55. package/dist/comments/CommentThreadList.cjs +124 -0
  56. package/dist/comments/CommentThreadList.cjs.map +1 -0
  57. package/dist/comments/CommentThreadList.d.ts +25 -0
  58. package/dist/comments/CommentThreadList.d.ts.map +1 -0
  59. package/dist/comments/CommentThreadList.js +124 -0
  60. package/dist/comments/CommentThreadList.js.map +1 -0
  61. package/dist/comments/GroupedComments.cjs +74 -0
  62. package/dist/comments/GroupedComments.cjs.map +1 -0
  63. package/dist/comments/GroupedComments.d.ts +18 -0
  64. package/dist/comments/GroupedComments.d.ts.map +1 -0
  65. package/dist/comments/GroupedComments.js +74 -0
  66. package/dist/comments/GroupedComments.js.map +1 -0
  67. package/dist/comments/MentionTextarea.cjs +253 -0
  68. package/dist/comments/MentionTextarea.cjs.map +1 -0
  69. package/dist/comments/MentionTextarea.d.ts +28 -0
  70. package/dist/comments/MentionTextarea.d.ts.map +1 -0
  71. package/dist/comments/MentionTextarea.js +253 -0
  72. package/dist/comments/MentionTextarea.js.map +1 -0
  73. package/dist/comments/comment-context.cjs +33 -0
  74. package/dist/comments/comment-context.cjs.map +1 -0
  75. package/dist/comments/comment-context.d.ts +32 -0
  76. package/dist/comments/comment-context.d.ts.map +1 -0
  77. package/dist/comments/comment-context.js +33 -0
  78. package/dist/comments/comment-context.js.map +1 -0
  79. package/dist/comments/comment-fixtures.d.ts +11 -0
  80. package/dist/comments/comment-fixtures.d.ts.map +1 -0
  81. package/dist/comments/comment-types.cjs +19 -0
  82. package/dist/comments/comment-types.cjs.map +1 -0
  83. package/dist/comments/comment-types.d.ts +170 -0
  84. package/dist/comments/comment-types.d.ts.map +1 -0
  85. package/dist/comments/comment-types.js +19 -0
  86. package/dist/comments/comment-types.js.map +1 -0
  87. package/dist/comments/comment-utils.cjs +216 -0
  88. package/dist/comments/comment-utils.cjs.map +1 -0
  89. package/dist/comments/comment-utils.d.ts +59 -0
  90. package/dist/comments/comment-utils.d.ts.map +1 -0
  91. package/dist/comments/comment-utils.js +216 -0
  92. package/dist/comments/comment-utils.js.map +1 -0
  93. package/dist/comments.cjs +57 -0
  94. package/dist/comments.cjs.map +1 -0
  95. package/dist/comments.d.ts +16 -0
  96. package/dist/comments.d.ts.map +1 -0
  97. package/dist/comments.js +57 -0
  98. package/dist/comments.js.map +1 -0
  99. package/dist/components/Combobox.cjs +5 -2
  100. package/dist/components/Combobox.cjs.map +1 -1
  101. package/dist/components/Combobox.d.ts.map +1 -1
  102. package/dist/components/Combobox.js +5 -2
  103. package/dist/components/Combobox.js.map +1 -1
  104. package/dist/components/FilterBar.cjs +293 -256
  105. package/dist/components/FilterBar.cjs.map +1 -1
  106. package/dist/components/FilterBar.d.ts.map +1 -1
  107. package/dist/components/FilterBar.js +293 -256
  108. package/dist/components/FilterBar.js.map +1 -1
  109. package/dist/components/JsonSchemaForm.cjs +22 -6
  110. package/dist/components/JsonSchemaForm.cjs.map +1 -1
  111. package/dist/components/JsonSchemaForm.d.ts +1 -1
  112. package/dist/components/JsonSchemaForm.d.ts.map +1 -1
  113. package/dist/components/JsonSchemaForm.js +25 -9
  114. package/dist/components/JsonSchemaForm.js.map +1 -1
  115. package/dist/components/MultiSelect.cjs +29 -32
  116. package/dist/components/MultiSelect.cjs.map +1 -1
  117. package/dist/components/MultiSelect.d.ts.map +1 -1
  118. package/dist/components/MultiSelect.js +30 -33
  119. package/dist/components/MultiSelect.js.map +1 -1
  120. package/dist/components/NamespacePicker.cjs +52 -0
  121. package/dist/components/NamespacePicker.cjs.map +1 -0
  122. package/dist/components/NamespacePicker.d.ts +17 -0
  123. package/dist/components/NamespacePicker.d.ts.map +1 -0
  124. package/dist/components/NamespacePicker.js +52 -0
  125. package/dist/components/NamespacePicker.js.map +1 -0
  126. package/dist/components/TimeRange.cjs +29 -37
  127. package/dist/components/TimeRange.cjs.map +1 -1
  128. package/dist/components/TimeRange.d.ts.map +1 -1
  129. package/dist/components/TimeRange.js +30 -38
  130. package/dist/components/TimeRange.js.map +1 -1
  131. package/dist/components/TreePickerField.cjs +6 -3
  132. package/dist/components/TreePickerField.cjs.map +1 -1
  133. package/dist/components/TreePickerField.d.ts.map +1 -1
  134. package/dist/components/TreePickerField.js +6 -3
  135. package/dist/components/TreePickerField.js.map +1 -1
  136. package/dist/components/form-lookup-context.cjs +36 -0
  137. package/dist/components/form-lookup-context.cjs.map +1 -0
  138. package/dist/components/form-lookup-context.d.ts +9 -0
  139. package/dist/components/form-lookup-context.d.ts.map +1 -0
  140. package/dist/components/form-lookup-context.js +36 -0
  141. package/dist/components/form-lookup-context.js.map +1 -0
  142. package/dist/components/icon-menu-picker.cjs +9 -3
  143. package/dist/components/icon-menu-picker.cjs.map +1 -1
  144. package/dist/components/icon-menu-picker.d.ts.map +1 -1
  145. package/dist/components/icon-menu-picker.js +9 -3
  146. package/dist/components/icon-menu-picker.js.map +1 -1
  147. package/dist/components/json-schema-form-discriminator.cjs +67 -0
  148. package/dist/components/json-schema-form-discriminator.cjs.map +1 -0
  149. package/dist/components/json-schema-form-discriminator.d.ts +10 -0
  150. package/dist/components/json-schema-form-discriminator.d.ts.map +1 -0
  151. package/dist/components/json-schema-form-discriminator.js +67 -0
  152. package/dist/components/json-schema-form-discriminator.js.map +1 -0
  153. package/dist/components/json-schema-form-fields.cjs +146 -3
  154. package/dist/components/json-schema-form-fields.cjs.map +1 -1
  155. package/dist/components/json-schema-form-fields.d.ts +22 -0
  156. package/dist/components/json-schema-form-fields.d.ts.map +1 -1
  157. package/dist/components/json-schema-form-fields.js +147 -4
  158. package/dist/components/json-schema-form-fields.js.map +1 -1
  159. package/dist/components/json-schema-form-grid.cjs +92 -0
  160. package/dist/components/json-schema-form-grid.cjs.map +1 -0
  161. package/dist/components/json-schema-form-grid.d.ts +9 -0
  162. package/dist/components/json-schema-form-grid.d.ts.map +1 -0
  163. package/dist/components/json-schema-form-grid.js +92 -0
  164. package/dist/components/json-schema-form-grid.js.map +1 -0
  165. package/dist/components/json-schema-form-refs.cjs +60 -0
  166. package/dist/components/json-schema-form-refs.cjs.map +1 -0
  167. package/dist/components/json-schema-form-refs.d.ts +3 -0
  168. package/dist/components/json-schema-form-refs.d.ts.map +1 -0
  169. package/dist/components/json-schema-form-refs.js +60 -0
  170. package/dist/components/json-schema-form-refs.js.map +1 -0
  171. package/dist/components/json-schema-form-render.cjs +34 -5
  172. package/dist/components/json-schema-form-render.cjs.map +1 -1
  173. package/dist/components/json-schema-form-render.d.ts.map +1 -1
  174. package/dist/components/json-schema-form-render.js +36 -7
  175. package/dist/components/json-schema-form-render.js.map +1 -1
  176. package/dist/components/json-schema-form-resolve.cjs +29 -2
  177. package/dist/components/json-schema-form-resolve.cjs.map +1 -1
  178. package/dist/components/json-schema-form-resolve.d.ts.map +1 -1
  179. package/dist/components/json-schema-form-resolve.js +29 -2
  180. package/dist/components/json-schema-form-resolve.js.map +1 -1
  181. package/dist/components/json-schema-form-template-menu.cjs +83 -0
  182. package/dist/components/json-schema-form-template-menu.cjs.map +1 -0
  183. package/dist/components/json-schema-form-template-menu.d.ts +15 -0
  184. package/dist/components/json-schema-form-template-menu.d.ts.map +1 -0
  185. package/dist/components/json-schema-form-template-menu.js +83 -0
  186. package/dist/components/json-schema-form-template-menu.js.map +1 -0
  187. package/dist/components/json-schema-form-template.cjs +18 -0
  188. package/dist/components/json-schema-form-template.cjs.map +1 -0
  189. package/dist/components/json-schema-form-template.d.ts +13 -0
  190. package/dist/components/json-schema-form-template.d.ts.map +1 -0
  191. package/dist/components/json-schema-form-template.js +18 -0
  192. package/dist/components/json-schema-form-template.js.map +1 -0
  193. package/dist/components/json-schema-form-types.d.ts +41 -2
  194. package/dist/components/json-schema-form-types.d.ts.map +1 -1
  195. package/dist/components/json-schema-form-utils.cjs +8 -0
  196. package/dist/components/json-schema-form-utils.cjs.map +1 -1
  197. package/dist/components/json-schema-form-utils.d.ts +1 -0
  198. package/dist/components/json-schema-form-utils.d.ts.map +1 -1
  199. package/dist/components/json-schema-form-utils.js +8 -0
  200. package/dist/components/json-schema-form-utils.js.map +1 -1
  201. package/dist/components/workload-picker-utils.cjs.map +1 -1
  202. package/dist/components/workload-picker-utils.d.ts +11 -1
  203. package/dist/components/workload-picker-utils.d.ts.map +1 -1
  204. package/dist/components/workload-picker-utils.js.map +1 -1
  205. package/dist/components.cjs +10 -0
  206. package/dist/components.cjs.map +1 -1
  207. package/dist/components.d.ts +7 -2
  208. package/dist/components.d.ts.map +1 -1
  209. package/dist/components.js +10 -0
  210. package/dist/components.js.map +1 -1
  211. package/dist/data/Clicky.cjs +231 -69
  212. package/dist/data/Clicky.cjs.map +1 -1
  213. package/dist/data/Clicky.d.ts +7 -1
  214. package/dist/data/Clicky.d.ts.map +1 -1
  215. package/dist/data/Clicky.fixtures.d.ts +3 -1
  216. package/dist/data/Clicky.fixtures.d.ts.map +1 -1
  217. package/dist/data/Clicky.js +232 -70
  218. package/dist/data/Clicky.js.map +1 -1
  219. package/dist/data/DataTable.cjs +23 -17
  220. package/dist/data/DataTable.cjs.map +1 -1
  221. package/dist/data/DataTable.d.ts +7 -1
  222. package/dist/data/DataTable.d.ts.map +1 -1
  223. package/dist/data/DataTable.js +24 -18
  224. package/dist/data/DataTable.js.map +1 -1
  225. package/dist/data/ExecutionTree.cjs +68 -0
  226. package/dist/data/ExecutionTree.cjs.map +1 -0
  227. package/dist/data/ExecutionTree.d.ts +40 -0
  228. package/dist/data/ExecutionTree.d.ts.map +1 -0
  229. package/dist/data/ExecutionTree.js +68 -0
  230. package/dist/data/ExecutionTree.js.map +1 -0
  231. package/dist/data/Gauge.cjs +37 -4
  232. package/dist/data/Gauge.cjs.map +1 -1
  233. package/dist/data/Gauge.d.ts +6 -1
  234. package/dist/data/Gauge.d.ts.map +1 -1
  235. package/dist/data/Gauge.js +37 -4
  236. package/dist/data/Gauge.js.map +1 -1
  237. package/dist/data/GaugeHoverCard.cjs +35 -0
  238. package/dist/data/GaugeHoverCard.cjs.map +1 -0
  239. package/dist/data/GaugeHoverCard.d.ts +25 -0
  240. package/dist/data/GaugeHoverCard.d.ts.map +1 -0
  241. package/dist/data/GaugeHoverCard.js +35 -0
  242. package/dist/data/GaugeHoverCard.js.map +1 -0
  243. package/dist/data/MarkdownEditor.cjs +616 -0
  244. package/dist/data/MarkdownEditor.cjs.map +1 -0
  245. package/dist/data/MarkdownEditor.d.ts +61 -0
  246. package/dist/data/MarkdownEditor.d.ts.map +1 -0
  247. package/dist/data/MarkdownEditor.js +616 -0
  248. package/dist/data/MarkdownEditor.js.map +1 -0
  249. package/dist/data/MarkdownEditor.model.cjs +27 -0
  250. package/dist/data/MarkdownEditor.model.cjs.map +1 -0
  251. package/dist/data/MarkdownEditor.model.d.ts +38 -0
  252. package/dist/data/MarkdownEditor.model.d.ts.map +1 -0
  253. package/dist/data/MarkdownEditor.model.js +27 -0
  254. package/dist/data/MarkdownEditor.model.js.map +1 -0
  255. package/dist/data/ObjectGraph.cjs +44 -0
  256. package/dist/data/ObjectGraph.cjs.map +1 -0
  257. package/dist/data/ObjectGraph.d.ts +39 -0
  258. package/dist/data/ObjectGraph.d.ts.map +1 -0
  259. package/dist/data/ObjectGraph.js +44 -0
  260. package/dist/data/ObjectGraph.js.map +1 -0
  261. package/dist/data/SchemaViewer.cjs +152 -0
  262. package/dist/data/SchemaViewer.cjs.map +1 -0
  263. package/dist/data/SchemaViewer.d.ts +27 -0
  264. package/dist/data/SchemaViewer.d.ts.map +1 -0
  265. package/dist/data/SchemaViewer.js +152 -0
  266. package/dist/data/SchemaViewer.js.map +1 -0
  267. package/dist/data/TimeseriesCoreBars.cjs +169 -32
  268. package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
  269. package/dist/data/TimeseriesCoreBars.d.ts +42 -5
  270. package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
  271. package/dist/data/TimeseriesCoreBars.js +170 -33
  272. package/dist/data/TimeseriesCoreBars.js.map +1 -1
  273. package/dist/data/TimeseriesCoreBars.model.cjs +5 -5
  274. package/dist/data/TimeseriesCoreBars.model.cjs.map +1 -1
  275. package/dist/data/TimeseriesCoreBars.model.d.ts +4 -4
  276. package/dist/data/TimeseriesCoreBars.model.d.ts.map +1 -1
  277. package/dist/data/TimeseriesCoreBars.model.js +5 -5
  278. package/dist/data/TimeseriesCoreBars.model.js.map +1 -1
  279. package/dist/data/TimeseriesGauge.cjs +132 -36
  280. package/dist/data/TimeseriesGauge.cjs.map +1 -1
  281. package/dist/data/TimeseriesGauge.d.ts +15 -1
  282. package/dist/data/TimeseriesGauge.d.ts.map +1 -1
  283. package/dist/data/TimeseriesGauge.js +133 -37
  284. package/dist/data/TimeseriesGauge.js.map +1 -1
  285. package/dist/data/WorkloadCard.cjs +371 -0
  286. package/dist/data/WorkloadCard.cjs.map +1 -0
  287. package/dist/data/WorkloadCard.d.ts +25 -0
  288. package/dist/data/WorkloadCard.d.ts.map +1 -0
  289. package/dist/data/WorkloadCard.js +371 -0
  290. package/dist/data/WorkloadCard.js.map +1 -0
  291. package/dist/data/WorkloadCard.model.cjs +51 -0
  292. package/dist/data/WorkloadCard.model.cjs.map +1 -0
  293. package/dist/data/WorkloadCard.model.d.ts +53 -0
  294. package/dist/data/WorkloadCard.model.d.ts.map +1 -0
  295. package/dist/data/WorkloadCard.model.js +51 -0
  296. package/dist/data/WorkloadCard.model.js.map +1 -0
  297. package/dist/data/ai/ChatFab.cjs +3 -1
  298. package/dist/data/ai/ChatFab.cjs.map +1 -1
  299. package/dist/data/ai/ChatFab.d.ts.map +1 -1
  300. package/dist/data/ai/ChatFab.js +3 -1
  301. package/dist/data/ai/ChatFab.js.map +1 -1
  302. package/dist/data/ai/ChatWindow.cjs +19 -9
  303. package/dist/data/ai/ChatWindow.cjs.map +1 -1
  304. package/dist/data/ai/ChatWindow.d.ts +4 -2
  305. package/dist/data/ai/ChatWindow.d.ts.map +1 -1
  306. package/dist/data/ai/ChatWindow.js +19 -9
  307. package/dist/data/ai/ChatWindow.js.map +1 -1
  308. package/dist/data/ai/ChatWindowRequestBody.cjs +20 -0
  309. package/dist/data/ai/ChatWindowRequestBody.cjs.map +1 -0
  310. package/dist/data/ai/ChatWindowRequestBody.d.ts +9 -0
  311. package/dist/data/ai/ChatWindowRequestBody.d.ts.map +1 -0
  312. package/dist/data/ai/ChatWindowRequestBody.js +20 -0
  313. package/dist/data/ai/ChatWindowRequestBody.js.map +1 -0
  314. package/dist/data/ai/chat-window-context.cjs +2 -1
  315. package/dist/data/ai/chat-window-context.cjs.map +1 -1
  316. package/dist/data/ai/chat-window-context.d.ts +1 -1
  317. package/dist/data/ai/chat-window-context.d.ts.map +1 -1
  318. package/dist/data/ai/chat-window-context.js +2 -1
  319. package/dist/data/ai/chat-window-context.js.map +1 -1
  320. package/dist/data/ai/context.cjs.map +1 -1
  321. package/dist/data/ai/context.d.ts +3 -0
  322. package/dist/data/ai/context.d.ts.map +1 -1
  323. package/dist/data/ai/context.js.map +1 -1
  324. package/dist/data/chat/Chat.cjs +21 -1
  325. package/dist/data/chat/Chat.cjs.map +1 -1
  326. package/dist/data/chat/Chat.d.ts +11 -2
  327. package/dist/data/chat/Chat.d.ts.map +1 -1
  328. package/dist/data/chat/Chat.js +22 -2
  329. package/dist/data/chat/Chat.js.map +1 -1
  330. package/dist/data/chat/Message.cjs +13 -4
  331. package/dist/data/chat/Message.cjs.map +1 -1
  332. package/dist/data/chat/Message.d.ts +4 -2
  333. package/dist/data/chat/Message.d.ts.map +1 -1
  334. package/dist/data/chat/Message.js +13 -4
  335. package/dist/data/chat/Message.js.map +1 -1
  336. package/dist/data/chat/ToolCall.cjs +9 -4
  337. package/dist/data/chat/ToolCall.cjs.map +1 -1
  338. package/dist/data/chat/ToolCall.d.ts +3 -2
  339. package/dist/data/chat/ToolCall.d.ts.map +1 -1
  340. package/dist/data/chat/ToolCall.js +9 -4
  341. package/dist/data/chat/ToolCall.js.map +1 -1
  342. package/dist/data/chat/index.d.ts +1 -1
  343. package/dist/data/chat/index.d.ts.map +1 -1
  344. package/dist/data/chat/types.cjs.map +1 -1
  345. package/dist/data/chat/types.d.ts +7 -0
  346. package/dist/data/chat/types.d.ts.map +1 -1
  347. package/dist/data/chat/types.js.map +1 -1
  348. package/dist/data/gauge-stats.cjs +19 -0
  349. package/dist/data/gauge-stats.cjs.map +1 -0
  350. package/dist/data/gauge-stats.d.ts +15 -0
  351. package/dist/data/gauge-stats.d.ts.map +1 -0
  352. package/dist/data/gauge-stats.js +19 -0
  353. package/dist/data/gauge-stats.js.map +1 -0
  354. package/dist/data/schema-viewer-model.cjs +436 -0
  355. package/dist/data/schema-viewer-model.cjs.map +1 -0
  356. package/dist/data/schema-viewer-model.d.ts +64 -0
  357. package/dist/data/schema-viewer-model.d.ts.map +1 -0
  358. package/dist/data/schema-viewer-model.js +436 -0
  359. package/dist/data/schema-viewer-model.js.map +1 -0
  360. package/dist/data/version-info.cjs +2 -2
  361. package/dist/data/version-info.js +2 -2
  362. package/dist/data.cjs +30 -0
  363. package/dist/data.cjs.map +1 -1
  364. package/dist/data.d.ts +14 -4
  365. package/dist/data.d.ts.map +1 -1
  366. package/dist/data.js +31 -1
  367. package/dist/data.js.map +1 -1
  368. package/dist/hooks/use-sort.cjs +19 -10
  369. package/dist/hooks/use-sort.cjs.map +1 -1
  370. package/dist/hooks/use-sort.d.ts +3 -0
  371. package/dist/hooks/use-sort.d.ts.map +1 -1
  372. package/dist/hooks/use-sort.js +19 -10
  373. package/dist/hooks/use-sort.js.map +1 -1
  374. package/dist/index.cjs +98 -2
  375. package/dist/index.cjs.map +1 -1
  376. package/dist/index.d.ts +1 -0
  377. package/dist/index.d.ts.map +1 -1
  378. package/dist/index.js +98 -2
  379. package/dist/index.js.map +1 -1
  380. package/dist/layout/AppShell.cjs +6 -10
  381. package/dist/layout/AppShell.cjs.map +1 -1
  382. package/dist/layout/AppShell.d.ts +2 -0
  383. package/dist/layout/AppShell.d.ts.map +1 -1
  384. package/dist/layout/AppShell.js +6 -10
  385. package/dist/layout/AppShell.js.map +1 -1
  386. package/dist/overlay/DropdownMenu.cjs +50 -38
  387. package/dist/overlay/DropdownMenu.cjs.map +1 -1
  388. package/dist/overlay/DropdownMenu.d.ts +5 -1
  389. package/dist/overlay/DropdownMenu.d.ts.map +1 -1
  390. package/dist/overlay/DropdownMenu.js +50 -38
  391. package/dist/overlay/DropdownMenu.js.map +1 -1
  392. package/dist/overlay/HoverCard.cjs +7 -2
  393. package/dist/overlay/HoverCard.cjs.map +1 -1
  394. package/dist/overlay/HoverCard.d.ts.map +1 -1
  395. package/dist/overlay/HoverCard.js +7 -2
  396. package/dist/overlay/HoverCard.js.map +1 -1
  397. package/dist/overlay/Modal.cjs +20 -17
  398. package/dist/overlay/Modal.cjs.map +1 -1
  399. package/dist/overlay/Modal.d.ts.map +1 -1
  400. package/dist/overlay/Modal.js +21 -18
  401. package/dist/overlay/Modal.js.map +1 -1
  402. package/dist/overlay/Toast.cjs +9 -1
  403. package/dist/overlay/Toast.cjs.map +1 -1
  404. package/dist/overlay/Toast.d.ts.map +1 -1
  405. package/dist/overlay/Toast.js +9 -1
  406. package/dist/overlay/Toast.js.map +1 -1
  407. package/dist/overlay/modalStack.cjs +53 -1
  408. package/dist/overlay/modalStack.cjs.map +1 -1
  409. package/dist/overlay/modalStack.d.ts +12 -0
  410. package/dist/overlay/modalStack.d.ts.map +1 -1
  411. package/dist/overlay/modalStack.js +54 -2
  412. package/dist/overlay/modalStack.js.map +1 -1
  413. package/dist/overlay/zIndex.cjs +20 -0
  414. package/dist/overlay/zIndex.cjs.map +1 -0
  415. package/dist/overlay/zIndex.d.ts +39 -0
  416. package/dist/overlay/zIndex.d.ts.map +1 -0
  417. package/dist/overlay/zIndex.js +20 -0
  418. package/dist/overlay/zIndex.js.map +1 -0
  419. package/dist/rpc/EntityExplorerApp.cjs +102 -143
  420. package/dist/rpc/EntityExplorerApp.cjs.map +1 -1
  421. package/dist/rpc/EntityExplorerApp.d.ts +34 -1
  422. package/dist/rpc/EntityExplorerApp.d.ts.map +1 -1
  423. package/dist/rpc/EntityExplorerApp.js +105 -146
  424. package/dist/rpc/EntityExplorerApp.js.map +1 -1
  425. package/dist/rpc/OperationActionBar.cjs +135 -0
  426. package/dist/rpc/OperationActionBar.cjs.map +1 -0
  427. package/dist/rpc/OperationActionBar.d.ts +20 -0
  428. package/dist/rpc/OperationActionBar.d.ts.map +1 -0
  429. package/dist/rpc/OperationActionBar.js +135 -0
  430. package/dist/rpc/OperationActionBar.js.map +1 -0
  431. package/dist/rpc/OperationCatalog.cjs +79 -116
  432. package/dist/rpc/OperationCatalog.cjs.map +1 -1
  433. package/dist/rpc/OperationCatalog.d.ts +8 -1
  434. package/dist/rpc/OperationCatalog.d.ts.map +1 -1
  435. package/dist/rpc/OperationCatalog.js +80 -117
  436. package/dist/rpc/OperationCatalog.js.map +1 -1
  437. package/dist/rpc/OperationCommandPage.cjs +134 -223
  438. package/dist/rpc/OperationCommandPage.cjs.map +1 -1
  439. package/dist/rpc/OperationCommandPage.d.ts +1 -1
  440. package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
  441. package/dist/rpc/OperationCommandPage.js +135 -224
  442. package/dist/rpc/OperationCommandPage.js.map +1 -1
  443. package/dist/rpc/OperationEntityPage.cjs +49 -100
  444. package/dist/rpc/OperationEntityPage.cjs.map +1 -1
  445. package/dist/rpc/OperationEntityPage.d.ts +6 -1
  446. package/dist/rpc/OperationEntityPage.d.ts.map +1 -1
  447. package/dist/rpc/OperationEntityPage.js +50 -101
  448. package/dist/rpc/OperationEntityPage.js.map +1 -1
  449. package/dist/rpc/OperationResultView.cjs +43 -0
  450. package/dist/rpc/OperationResultView.cjs.map +1 -0
  451. package/dist/rpc/OperationResultView.d.ts +30 -0
  452. package/dist/rpc/OperationResultView.d.ts.map +1 -0
  453. package/dist/rpc/OperationResultView.js +43 -0
  454. package/dist/rpc/OperationResultView.js.map +1 -0
  455. package/dist/rpc/SchemaActionForm.cjs +102 -0
  456. package/dist/rpc/SchemaActionForm.cjs.map +1 -0
  457. package/dist/rpc/SchemaActionForm.d.ts +23 -0
  458. package/dist/rpc/SchemaActionForm.d.ts.map +1 -0
  459. package/dist/rpc/SchemaActionForm.js +102 -0
  460. package/dist/rpc/SchemaActionForm.js.map +1 -0
  461. package/dist/rpc/accept-options.cjs.map +1 -1
  462. package/dist/rpc/accept-options.d.ts +0 -1
  463. package/dist/rpc/accept-options.d.ts.map +1 -1
  464. package/dist/rpc/accept-options.js.map +1 -1
  465. package/dist/rpc/apiClient.cjs +34 -2
  466. package/dist/rpc/apiClient.cjs.map +1 -1
  467. package/dist/rpc/apiClient.d.ts +4 -1
  468. package/dist/rpc/apiClient.d.ts.map +1 -1
  469. package/dist/rpc/apiClient.js +34 -2
  470. package/dist/rpc/apiClient.js.map +1 -1
  471. package/dist/rpc/clickyMetadata.cjs +4 -4
  472. package/dist/rpc/clickyMetadata.cjs.map +1 -1
  473. package/dist/rpc/clickyMetadata.d.ts +0 -1
  474. package/dist/rpc/clickyMetadata.d.ts.map +1 -1
  475. package/dist/rpc/clickyMetadata.js +4 -4
  476. package/dist/rpc/clickyMetadata.js.map +1 -1
  477. package/dist/rpc/formMetadata.cjs +1 -0
  478. package/dist/rpc/formMetadata.cjs.map +1 -1
  479. package/dist/rpc/formMetadata.d.ts +6 -1
  480. package/dist/rpc/formMetadata.d.ts.map +1 -1
  481. package/dist/rpc/formMetadata.js +1 -0
  482. package/dist/rpc/formMetadata.js.map +1 -1
  483. package/dist/rpc/rowNavigation.cjs +86 -0
  484. package/dist/rpc/rowNavigation.cjs.map +1 -0
  485. package/dist/rpc/rowNavigation.d.ts +14 -0
  486. package/dist/rpc/rowNavigation.d.ts.map +1 -0
  487. package/dist/rpc/rowNavigation.js +86 -0
  488. package/dist/rpc/rowNavigation.js.map +1 -0
  489. package/dist/rpc/schemaActionPath.cjs +22 -0
  490. package/dist/rpc/schemaActionPath.cjs.map +1 -0
  491. package/dist/rpc/schemaActionPath.d.ts +4 -0
  492. package/dist/rpc/schemaActionPath.d.ts.map +1 -0
  493. package/dist/rpc/schemaActionPath.js +22 -0
  494. package/dist/rpc/schemaActionPath.js.map +1 -0
  495. package/dist/rpc/surfaceIconMap.cjs +35 -0
  496. package/dist/rpc/surfaceIconMap.cjs.map +1 -0
  497. package/dist/rpc/surfaceIconMap.d.ts +3 -0
  498. package/dist/rpc/surfaceIconMap.d.ts.map +1 -0
  499. package/dist/rpc/surfaceIconMap.js +35 -0
  500. package/dist/rpc/surfaceIconMap.js.map +1 -0
  501. package/dist/rpc/types.cjs.map +1 -1
  502. package/dist/rpc/types.d.ts +2 -0
  503. package/dist/rpc/types.d.ts.map +1 -1
  504. package/dist/rpc/types.js.map +1 -1
  505. package/dist/rpc/useOperations.cjs.map +1 -1
  506. package/dist/rpc/useOperations.d.ts +4 -1
  507. package/dist/rpc/useOperations.d.ts.map +1 -1
  508. package/dist/rpc/useOperations.js.map +1 -1
  509. package/dist/rpc.cjs +4 -2
  510. package/dist/rpc.cjs.map +1 -1
  511. package/dist/rpc.d.ts +7 -6
  512. package/dist/rpc.d.ts.map +1 -1
  513. package/dist/rpc.js +4 -2
  514. package/dist/rpc.js.map +1 -1
  515. package/dist/styles.css +1 -1
  516. package/package.json +6 -1
  517. package/dist/rpc/AcceptPicker.cjs +0 -135
  518. package/dist/rpc/AcceptPicker.cjs.map +0 -1
  519. package/dist/rpc/AcceptPicker.d.ts +0 -12
  520. package/dist/rpc/AcceptPicker.d.ts.map +0 -1
  521. package/dist/rpc/AcceptPicker.js +0 -135
  522. package/dist/rpc/AcceptPicker.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"json-schema-form-fields.js","sources":["../../src/components/json-schema-form-fields.tsx"],"sourcesContent":["import { type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { LabelIcon, type LabelIconSpec } from \"../data/Icon\";\nimport { formatDateTimeRelative } from \"../data/cells/timestamp-format\";\nimport { Combobox } from \"./Combobox\";\nimport { DateTimePicker } from \"./DateTimePicker\";\nimport type { FieldControl, FieldOption, FormLayout } from \"./json-schema-form-types\";\nimport {\n defaultPlaceholder,\n inputClass,\n toText,\n withSyntheticValue,\n} from \"./json-schema-form-utils\";\nimport {\n controlHeightClass,\n controlMinHeightClass,\n fieldInnerGapClass,\n inlineRowGapClass,\n labelSizeClass,\n stackedRowGapClass,\n type FormSize,\n} from \"./json-schema-form-size\";\n\n// FieldsGrid is the container every group of field rows renders into — the\n// top-level form and each nested object/map. In inline mode it owns the single\n// 2-column track definition: `fit-content(labelMaxWidth)` for the label column,\n// `minmax(0, valueMaxWidth)` for the value column. Every field row is a\n// `subgrid` that inherits these tracks, so all labels share one column width and\n// every value lines up — a real form grid, not per-row independent grids.\n// (`fit-content()` is the only valid CSS for \"size to content, clamped to a max\"\n// — `min(w, max-content)` is rejected by the browser, which silently drops the\n// whole declaration and collapses every row to a stacked-looking column. The\n// template is an inline style because Tailwind can't interpolate runtime widths.)\n// Stacked mode is a plain single-column grid.\nexport function FieldsGrid({ layout, size, children }: { layout: FormLayout; size: FormSize; children: ReactNode }) {\n if (layout.mode === \"inline\") {\n const labelMaxWidth = layout.labelMaxWidth ?? \"40ch\";\n const valueMaxWidth = layout.valueMaxWidth ?? \"600px\";\n return (\n <div\n className={cn(\"grid\", inlineRowGapClass[size])}\n style={{ gridTemplateColumns: `fit-content(${labelMaxWidth}) minmax(0, ${valueMaxWidth})` }}\n >\n {children}\n </div>\n );\n }\n return <div className={cn(\"grid\", stackedRowGapClass[size])}>{children}</div>;\n}\n\n// FieldWrapper lays out a single label + value (+ helper/error). In inline mode\n// it is a `subgrid` row spanning the parent FieldsGrid's two columns, so its\n// label and value snap to the shared label/value tracks (helper/error sit under\n// the value column). In stacked mode the label sits tight above its control as\n// one unit, capped at valueMaxWidth so controls don't stretch edge to edge.\nexport function FieldWrapper({\n label,\n value,\n helper,\n error,\n layout,\n size,\n}: {\n label: ReactNode;\n value: ReactNode;\n helper?: ReactNode;\n error?: ReactNode;\n layout: FormLayout;\n size: FormSize;\n}) {\n if (layout.mode === \"inline\") {\n return (\n <div className=\"col-span-2 grid grid-cols-subgrid items-start gap-x-3 gap-y-0.5\">\n <div className={cn(\"flex min-w-0 items-center\", controlMinHeightClass[size])}>{label}</div>\n <div className=\"min-w-0\">{value}</div>\n {helper && <p className=\"col-start-2 text-xs text-muted-foreground\">{helper}</p>}\n {error && <p className=\"col-start-2 text-xs text-destructive\">{error}</p>}\n </div>\n );\n }\n return (\n <div\n className=\"flex w-full flex-col gap-1\"\n style={{ maxWidth: layout.valueMaxWidth ?? \"600px\" }}\n >\n {label}\n {value}\n {helper && <p className=\"text-xs text-muted-foreground\">{helper}</p>}\n {error && <p className=\"text-xs text-destructive\">{error}</p>}\n </div>\n );\n}\n\nexport function FieldLabel({ field, fieldId, size }: { field: FieldControl; fieldId: string; size: FormSize }) {\n return (\n <label htmlFor={fieldId} className={cn(\"flex min-w-0 items-center gap-2 font-medium\", labelSizeClass[size])}>\n <LabelIcon icon={field.labelIcon} className=\"shrink-0 text-[15px] text-muted-foreground\" />\n <span className=\"truncate\" title={field.label !== field.key ? field.key : undefined}>\n {field.label}\n </span>\n {field.required && <span className=\"shrink-0 text-destructive\">*</span>}\n {field.badge && (\n <span className=\"shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n {field.badge}\n </span>\n )}\n </label>\n );\n}\n\n// ObjectSection renders a nested object as a labelled section: a header row\n// (the field label + required/badge) above its fields, which fill the full\n// width below. It replaces the inline label + bordered box so nested objects\n// read as flat, headed groups rather than indented sub-forms. `col-span-full`\n// makes it span both tracks of an inline FieldsGrid (full width, not crammed\n// into the value column); in a stacked single-column grid it is a no-op.\nexport function ObjectSection({\n label,\n required,\n size,\n badge,\n helper,\n labelIcon,\n children,\n}: {\n label: string;\n required: boolean;\n size: FormSize;\n badge?: string;\n helper?: string;\n labelIcon?: LabelIconSpec;\n children: ReactNode;\n}) {\n return (\n <div className={cn(\"col-span-full flex flex-col\", fieldInnerGapClass[size])}>\n <div className={cn(\"flex items-center gap-2 border-b border-border pb-1 font-semibold\", labelSizeClass[size])}>\n <LabelIcon icon={labelIcon} className=\"text-[15px] text-muted-foreground\" />\n <span>{label}</span>\n {required && <span className=\"text-destructive\">*</span>}\n {badge && (\n <span className=\"rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n {badge}\n </span>\n )}\n </div>\n {helper && <p className=\"text-xs text-muted-foreground\">{helper}</p>}\n {children}\n </div>\n );\n}\n\n// ReadOnlyValue renders a `readOnly` field's current value as static text — no\n// input, no border, just the value (date/date-time formatted human-readably).\n// An empty value shows an em-dash. Carries the same id + data-jsf-input as the\n// editable controls so layout and queries stay uniform.\nexport function ReadOnlyValue({ field, fieldId, size }: { field: FieldControl; fieldId: string; size: FormSize }) {\n const text = toText(field.value);\n const display = field.kind === \"date\" && text ? formatDateTimeRelative(text) : text;\n return (\n <span\n id={fieldId}\n data-jsf-input\n data-jsf-readonly\n className={cn(\"flex items-center text-foreground\", controlHeightClass[size], labelSizeClass[size])}\n title={text || undefined}\n >\n {display || <span className=\"text-muted-foreground\">—</span>}\n </span>\n );\n}\n\n// FieldAdornmentWrapper positions a field's leading/trailing in-field adornments\n// (FieldControl.prefix at the left edge, FieldControl.suffix at the right). The\n// container is tagged data-jsf-control so an adornment can locate its sibling\n// input[data-jsf-input] (e.g. for caret-aware insertion). With neither adornment\n// it renders the input bare, so unadorned fields are byte-for-byte unchanged.\nfunction FieldAdornmentWrapper({\n prefix,\n suffix,\n children,\n}: {\n prefix?: ReactNode;\n suffix?: ReactNode;\n children: ReactNode;\n}) {\n if (!prefix && !suffix) return <>{children}</>;\n return (\n <div data-jsf-control className=\"relative\">\n {prefix && <div className=\"absolute inset-y-0 left-1.5 flex items-center\">{prefix}</div>}\n {children}\n {suffix && <div className=\"absolute inset-y-0 right-1.5 flex items-center\">{suffix}</div>}\n </div>\n );\n}\n\nexport function StringControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n return (\n <FieldAdornmentWrapper prefix={field.prefix} suffix={field.suffix}>\n <input\n id={fieldId}\n type=\"text\"\n data-jsf-input\n className={cn(inputClass(size), field.prefix && \"pl-8\", field.suffix && \"pr-8\")}\n value={toText(field.value)}\n disabled={readOnly}\n placeholder={defaultPlaceholder(field.schema)}\n onChange={(e) => field.onChange(e.target.value)}\n />\n </FieldAdornmentWrapper>\n );\n}\n\nexport function NumberControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n // type=\"text\" (not number) so non-numeric values a consumer permits — e.g.\n // template tokens — are not silently dropped by the browser.\n const coerce = field.coerceNumber !== false;\n return (\n <FieldAdornmentWrapper prefix={field.prefix} suffix={field.suffix}>\n <input\n id={fieldId}\n type=\"text\"\n inputMode=\"decimal\"\n data-jsf-input\n className={cn(inputClass(size), field.prefix && \"pl-8\", field.suffix && \"pr-8\")}\n value={toText(field.value)}\n disabled={readOnly}\n placeholder={defaultPlaceholder(field.schema)}\n onChange={(e) => {\n const raw = e.target.value;\n // Coerce mid-typing ONLY when the parse round-trips to the same text\n // (e.g. \"100\", \"33.5\") — so an in-progress decimal like \"33.\" or a\n // trailing-zero \"33.30\" keeps its raw text instead of collapsing to a\n // number and stranding the caret. Non-numeric tokens fall through to\n // the raw string. Blur finalizes any still-uncoerced numeric text.\n if (coerce && raw.trim() !== \"\" && String(Number(raw)) === raw.trim()) {\n field.onChange(Number(raw));\n } else {\n field.onChange(raw);\n }\n }}\n onBlur={(e) => {\n const raw = e.target.value;\n if (coerce && raw.trim() !== \"\" && Number.isFinite(Number(raw))) {\n field.onChange(Number(raw));\n }\n }}\n />\n </FieldAdornmentWrapper>\n );\n}\n\n// DateControl edits a `format: date`/`date-time` string. Read-only, it shows the\n// human-readable absolute + relative form (e.g. \"Apr 15, 2026, 12:00 PM (2h\n// ago)\"); editable, a DateTimePicker. The raw string is committed unchanged so a\n// consumer-permitted template token in the field is preserved.\nexport function DateControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n const text = toText(field.value);\n if (readOnly) {\n return (\n <div\n id={fieldId}\n data-jsf-input\n className={cn(\"flex items-center text-foreground\", controlHeightClass[size], labelSizeClass[size])}\n title={text || undefined}\n >\n {text ? formatDateTimeRelative(text) : <span className=\"text-muted-foreground\">—</span>}\n </div>\n );\n }\n return (\n <DateTimePicker\n id={fieldId}\n aria-label={field.label}\n data-jsf-input\n inputClassName={cn(inputClass(size), field.prefix && \"pl-8\", field.suffix ? \"pr-14\" : \"pr-8\")}\n value={text}\n onChange={(next) => field.onChange(next)}\n placeholder={defaultPlaceholder(field.schema)}\n prefix={field.prefix}\n suffix={field.suffix}\n />\n );\n}\n\nexport function BooleanControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n // Only render a checkbox when the value is genuinely boolean (or unset).\n // A non-boolean value (e.g. a token a consumer left in place) renders as text\n // so it is preserved and editable.\n if (typeof field.value === \"boolean\" || field.value === undefined || field.value === null) {\n return (\n <div className={cn(\"flex items-center\", controlHeightClass[size])}>\n <input\n id={fieldId}\n type=\"checkbox\"\n className=\"h-4 w-4 accent-primary\"\n checked={field.value === true}\n disabled={readOnly}\n onChange={(e) => field.onChange(e.target.checked)}\n />\n </div>\n );\n }\n return <StringControl field={field} fieldId={fieldId} readOnly={readOnly} size={size} />;\n}\n\nexport function EnumControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n const value = toText(field.value);\n const options = withSyntheticValue(field.options ?? [], value);\n if (field.display === \"radio\") {\n return (\n <RadioGroupControl field={field} fieldId={fieldId} readOnly={readOnly} options={options} value={value} size={size} />\n );\n }\n return (\n <Combobox\n id={fieldId}\n options={options}\n value={value}\n disabled={readOnly}\n size={size}\n allowCustomValue={field.allowCustomValue ?? false}\n onChange={(v) => field.onChange(v)}\n prefix={field.prefix}\n suffix={field.suffix}\n {...(defaultPlaceholder(field.schema) ? { placeholder: defaultPlaceholder(field.schema) } : {})}\n />\n );\n}\n\n// RadioGroupControl renders a small fixed enum as a segmented radio-button group\n// instead of a dropdown. It shares EnumControl's option list (any out-of-enum\n// value is already prepended, so a token still shows). One `radiogroup` role +\n// native radios keep it keyboard-navigable; the visible chip is a styled label.\nfunction RadioGroupControl({\n field,\n fieldId,\n readOnly,\n options,\n value,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n options: FieldOption[];\n value: string;\n size: FormSize;\n}) {\n return (\n <div\n role=\"radiogroup\"\n aria-label={field.label}\n id={fieldId}\n data-jsf-input\n className=\"inline-flex flex-wrap items-center gap-1 rounded-md border border-input bg-background p-0.5\"\n >\n {options.map((opt) => {\n const checked = opt.value === value;\n return (\n <label\n key={opt.value}\n className={cn(\n \"inline-flex cursor-pointer select-none items-center rounded px-2.5 py-1\",\n labelSizeClass[size],\n checked\n ? \"bg-primary text-primary-foreground\"\n : \"text-muted-foreground hover:bg-accent hover:text-foreground\",\n readOnly && \"cursor-not-allowed opacity-60\",\n )}\n >\n <input\n type=\"radio\"\n name={fieldId}\n className=\"sr-only\"\n value={opt.value}\n checked={checked}\n disabled={readOnly}\n onChange={() => field.onChange(opt.value)}\n />\n {opt.label}\n </label>\n );\n })}\n </div>\n );\n}\n\n// HMR probe\n// HMR probe 2\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"json-schema-form-fields.js","sources":["../../src/components/json-schema-form-fields.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { LabelIcon, type LabelIconSpec } from \"../data/Icon\";\nimport { formatDateTimeRelative } from \"../data/cells/timestamp-format\";\nimport { Combobox } from \"./Combobox\";\nimport { DateTimePicker } from \"./DateTimePicker\";\nimport { GridControl } from \"./json-schema-form-grid\";\nimport { resolveLookupScope, useLookupFetcher } from \"./form-lookup-context\";\nimport type { FieldControl, FieldOption, FormLayout } from \"./json-schema-form-types\";\nimport {\n defaultPlaceholder,\n inputClass,\n toText,\n withSyntheticValue,\n} from \"./json-schema-form-utils\";\nimport {\n controlHeightClass,\n controlMinHeightClass,\n fieldInnerGapClass,\n inlineRowGapClass,\n labelSizeClass,\n stackedRowGapClass,\n type FormSize,\n} from \"./json-schema-form-size\";\n\n// FieldsGrid is the container every group of field rows renders into — the\n// top-level form and each nested object/map. In inline mode it owns the single\n// 2-column track definition: `fit-content(labelMaxWidth)` for the label column,\n// `minmax(0, valueMaxWidth)` for the value column. Every field row is a\n// `subgrid` that inherits these tracks, so all labels share one column width and\n// every value lines up — a real form grid, not per-row independent grids.\n// (`fit-content()` is the only valid CSS for \"size to content, clamped to a max\"\n// — `min(w, max-content)` is rejected by the browser, which silently drops the\n// whole declaration and collapses every row to a stacked-looking column. The\n// template is an inline style because Tailwind can't interpolate runtime widths.)\n// Stacked mode is a plain single-column grid.\nexport function FieldsGrid({ layout, size, children }: { layout: FormLayout; size: FormSize; children: ReactNode }) {\n if (layout.mode === \"inline\") {\n const labelMaxWidth = layout.labelMaxWidth ?? \"40ch\";\n const valueMaxWidth = layout.valueMaxWidth ?? \"600px\";\n return (\n <div\n className={cn(\"grid\", inlineRowGapClass[size])}\n style={{ gridTemplateColumns: `fit-content(${labelMaxWidth}) minmax(0, ${valueMaxWidth})` }}\n >\n {children}\n </div>\n );\n }\n return <div className={cn(\"grid\", stackedRowGapClass[size])}>{children}</div>;\n}\n\n// FieldWrapper lays out a single label + value (+ helper/error). In inline mode\n// it is a `subgrid` row spanning the parent FieldsGrid's two columns, so its\n// label and value snap to the shared label/value tracks (helper/error sit under\n// the value column). In stacked mode the label sits tight above its control as\n// one unit, capped at valueMaxWidth so controls don't stretch edge to edge.\nexport function FieldWrapper({\n label,\n value,\n helper,\n error,\n layout,\n size,\n}: {\n label: ReactNode;\n value: ReactNode;\n helper?: ReactNode;\n error?: ReactNode;\n layout: FormLayout;\n size: FormSize;\n}) {\n if (layout.mode === \"inline\") {\n return (\n <div className=\"col-span-2 grid grid-cols-subgrid items-start gap-x-3 gap-y-0.5\">\n <div className={cn(\"flex min-w-0 items-center\", controlMinHeightClass[size])}>{label}</div>\n <div className=\"min-w-0\">{value}</div>\n {helper && <p className=\"col-start-2 text-xs text-muted-foreground\">{helper}</p>}\n {error && <p className=\"col-start-2 text-xs text-destructive\">{error}</p>}\n </div>\n );\n }\n return (\n <div\n className=\"flex w-full flex-col gap-1\"\n style={{ maxWidth: layout.valueMaxWidth ?? \"600px\" }}\n >\n {label}\n {value}\n {helper && <p className=\"text-xs text-muted-foreground\">{helper}</p>}\n {error && <p className=\"text-xs text-destructive\">{error}</p>}\n </div>\n );\n}\n\nexport function FieldLabel({ field, fieldId, size }: { field: FieldControl; fieldId: string; size: FormSize }) {\n return (\n <label htmlFor={fieldId} className={cn(\"flex min-w-0 items-center gap-2 font-medium\", labelSizeClass[size])}>\n <LabelIcon icon={field.labelIcon} className=\"shrink-0 text-[15px] text-muted-foreground\" />\n <span className=\"truncate\" title={field.label !== field.key ? field.key : undefined}>\n {field.label}\n </span>\n {field.required && <span className=\"shrink-0 text-destructive\">*</span>}\n {field.badge && (\n <span className=\"shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n {field.badge}\n </span>\n )}\n </label>\n );\n}\n\n// ObjectSection renders a nested object as a labelled section: a header row\n// (the field label + required/badge) above its fields, which fill the full\n// width below. It replaces the inline label + bordered box so nested objects\n// read as flat, headed groups rather than indented sub-forms. `col-span-full`\n// makes it span both tracks of an inline FieldsGrid (full width, not crammed\n// into the value column); in a stacked single-column grid it is a no-op.\nexport function ObjectSection({\n label,\n required,\n size,\n badge,\n helper,\n labelIcon,\n children,\n}: {\n label: string;\n required: boolean;\n size: FormSize;\n badge?: string;\n helper?: string;\n labelIcon?: LabelIconSpec;\n children: ReactNode;\n}) {\n return (\n <div className={cn(\"col-span-full flex flex-col\", fieldInnerGapClass[size])}>\n <div className={cn(\"flex items-center gap-2 border-b border-border pb-1 font-semibold\", labelSizeClass[size])}>\n <LabelIcon icon={labelIcon} className=\"text-[15px] text-muted-foreground\" />\n <span>{label}</span>\n {required && <span className=\"text-destructive\">*</span>}\n {badge && (\n <span className=\"rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n {badge}\n </span>\n )}\n </div>\n {helper && <p className=\"text-xs text-muted-foreground\">{helper}</p>}\n {children}\n </div>\n );\n}\n\n// ReadOnlyValue renders a `readOnly` field's current value as static text — no\n// input, no border, just the value (date/date-time formatted human-readably).\n// An empty value shows an em-dash. Carries the same id + data-jsf-input as the\n// editable controls so layout and queries stay uniform.\nexport function ReadOnlyValue({ field, fieldId, size }: { field: FieldControl; fieldId: string; size: FormSize }) {\n const text = toText(field.value);\n const display = field.kind === \"date\" && text ? formatDateTimeRelative(text) : text;\n return (\n <span\n id={fieldId}\n data-jsf-input\n data-jsf-readonly\n className={cn(\"flex items-center text-foreground\", controlHeightClass[size], labelSizeClass[size])}\n title={text || undefined}\n >\n {display || <span className=\"text-muted-foreground\">—</span>}\n </span>\n );\n}\n\n// FieldAdornmentWrapper positions a field's leading/trailing in-field adornments\n// (FieldControl.prefix at the left edge, FieldControl.suffix at the right). The\n// container is tagged data-jsf-control so an adornment can locate its sibling\n// input[data-jsf-input] (e.g. for caret-aware insertion). With neither adornment\n// it renders the input bare, so unadorned fields are byte-for-byte unchanged.\nfunction FieldAdornmentWrapper({\n prefix,\n suffix,\n children,\n}: {\n prefix?: ReactNode;\n suffix?: ReactNode;\n children: ReactNode;\n}) {\n if (!prefix && !suffix) return <>{children}</>;\n return (\n <div data-jsf-control className=\"relative\">\n {prefix && <div className=\"absolute inset-y-0 left-1.5 flex items-center\">{prefix}</div>}\n {children}\n {suffix && <div className=\"absolute inset-y-0 right-1.5 flex items-center\">{suffix}</div>}\n </div>\n );\n}\n\nexport function StringControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n return (\n <FieldAdornmentWrapper prefix={field.prefix} suffix={field.suffix}>\n <input\n id={fieldId}\n type=\"text\"\n data-jsf-input\n className={cn(inputClass(size), field.prefix && \"pl-8\", field.suffix && \"pr-8\")}\n value={toText(field.value)}\n disabled={readOnly}\n placeholder={defaultPlaceholder(field.schema)}\n onChange={(e) => field.onChange(e.target.value)}\n />\n </FieldAdornmentWrapper>\n );\n}\n\nexport function NumberControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n // type=\"text\" (not number) so non-numeric values a consumer permits — e.g.\n // template tokens — are not silently dropped by the browser.\n const coerce = field.coerceNumber !== false;\n // A static unit (e.g. \"%\") rides the right edge of the input as a display-only\n // suffix; a consumer-set `suffix` (e.g. an insert-snippet button) wins if both\n // are present (number insert triggers mount on the left as `prefix`).\n const suffix = field.suffix ?? (field.unit ? (\n <span className=\"pointer-events-none select-none text-muted-foreground\">{field.unit}</span>\n ) : undefined);\n return (\n <FieldAdornmentWrapper prefix={field.prefix} suffix={suffix}>\n <input\n id={fieldId}\n type=\"text\"\n inputMode=\"decimal\"\n data-jsf-input\n className={cn(inputClass(size), field.prefix && \"pl-8\", suffix && \"pr-8\")}\n value={toText(field.value)}\n disabled={readOnly}\n placeholder={defaultPlaceholder(field.schema)}\n onChange={(e) => {\n const raw = e.target.value;\n // Coerce mid-typing ONLY when the parse round-trips to the same text\n // (e.g. \"100\", \"33.5\") — so an in-progress decimal like \"33.\" or a\n // trailing-zero \"33.30\" keeps its raw text instead of collapsing to a\n // number and stranding the caret. Non-numeric tokens fall through to\n // the raw string. Blur finalizes any still-uncoerced numeric text.\n if (coerce && raw.trim() !== \"\" && String(Number(raw)) === raw.trim()) {\n field.onChange(Number(raw));\n } else {\n field.onChange(raw);\n }\n }}\n onBlur={(e) => {\n const raw = e.target.value;\n if (coerce && raw.trim() !== \"\" && Number.isFinite(Number(raw))) {\n field.onChange(Number(raw));\n }\n }}\n />\n </FieldAdornmentWrapper>\n );\n}\n\n// DateControl edits a `format: date`/`date-time` string. Read-only, it shows the\n// human-readable absolute + relative form (e.g. \"Apr 15, 2026, 12:00 PM (2h\n// ago)\"); editable, a DateTimePicker. The raw string is committed unchanged so a\n// consumer-permitted template token in the field is preserved.\nexport function DateControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n const text = toText(field.value);\n if (readOnly) {\n return (\n <div\n id={fieldId}\n data-jsf-input\n className={cn(\"flex items-center text-foreground\", controlHeightClass[size], labelSizeClass[size])}\n title={text || undefined}\n >\n {text ? formatDateTimeRelative(text) : <span className=\"text-muted-foreground\">—</span>}\n </div>\n );\n }\n return (\n <DateTimePicker\n id={fieldId}\n aria-label={field.label}\n data-jsf-input\n inputClassName={cn(inputClass(size), field.prefix && \"pl-8\", field.suffix ? \"pr-14\" : \"pr-8\")}\n value={text}\n onChange={(next) => field.onChange(next)}\n placeholder={defaultPlaceholder(field.schema)}\n prefix={field.prefix}\n suffix={field.suffix}\n />\n );\n}\n\nexport function BooleanControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n // Only render a checkbox when the value is genuinely boolean (or unset).\n // A non-boolean value (e.g. a token a consumer left in place) renders as text\n // so it is preserved and editable.\n if (typeof field.value === \"boolean\" || field.value === undefined || field.value === null) {\n return (\n <div className={cn(\"flex items-center\", controlHeightClass[size])}>\n <input\n id={fieldId}\n type=\"checkbox\"\n className=\"h-4 w-4 accent-primary\"\n checked={field.value === true}\n disabled={readOnly}\n onChange={(e) => field.onChange(e.target.checked)}\n />\n </div>\n );\n }\n return <StringControl field={field} fieldId={fieldId} readOnly={readOnly} size={size} />;\n}\n\nexport function EnumControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n const value = toText(field.value);\n const options = withSyntheticValue(field.options ?? [], value);\n if (field.display === \"grid\") {\n return <GridControl field={field} fieldId={fieldId} readOnly={readOnly} size={size} />;\n }\n if (field.display === \"radio\") {\n return (\n <RadioGroupControl field={field} fieldId={fieldId} readOnly={readOnly} options={options} value={value} size={size} />\n );\n }\n return (\n <Combobox\n id={fieldId}\n options={options}\n value={value}\n disabled={readOnly}\n size={size}\n allowCustomValue={field.allowCustomValue ?? false}\n onChange={(v) => field.onChange(v)}\n prefix={field.prefix}\n suffix={field.suffix}\n {...(defaultPlaceholder(field.schema) ? { placeholder: defaultPlaceholder(field.schema) } : {})}\n />\n );\n}\n\n// LookupControl is the async entity-reference picker for an `x-clicky-lookup`\n// field. It wraps Combobox and fetches options lazily through the form's\n// LookupFetcher (from context): the head set loads when the menu opens and the\n// (debounced) typed query drives server-side search. Single-select keeps\n// allowCustomValue on so a value outside the option set still commits (e.g. an\n// inline DSN). When no fetcher is wired it degrades to a free-text combobox.\nexport function LookupControl({\n field,\n fieldId,\n readOnly,\n size,\n rootValue,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n rootValue?: Record<string, unknown>;\n}) {\n const fetcher = useLookupFetcher();\n const descriptor = field.lookup;\n const value = toText(field.value);\n const [options, setOptions] = useState<FieldOption[]>([]);\n const [loading, setLoading] = useState(false);\n\n // rootValue is read through a ref so onSearch stays referentially stable: a new\n // onSearch each render would retrigger Combobox's search effect on every\n // setOptions, looping. The scopeKey effect below re-fetches when scope changes.\n const rootRef = useRef(rootValue);\n rootRef.current = rootValue;\n\n const onSearch = useCallback(\n (query: string) => {\n if (!descriptor || !fetcher) return;\n setLoading(true);\n const root = rootRef.current;\n fetcher({ descriptor, query, ...(root ? { rootValue: root } : {}) })\n .then((next) => setOptions(next))\n .catch(() => setOptions([]))\n .finally(() => setLoading(false));\n },\n [descriptor, fetcher],\n );\n\n // Re-fetch the head set when the scope (a sibling field, e.g. provider type)\n // changes so the out-of-scope set is replaced rather than shown stale.\n const scopeKey = descriptor ? JSON.stringify(resolveLookupScope(descriptor, rootValue)) : \"\";\n useEffect(() => {\n if (descriptor && fetcher) onSearch(\"\");\n else setOptions([]);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [scopeKey, onSearch]);\n\n if (!descriptor || !fetcher) {\n return (\n <Combobox\n id={fieldId}\n options={withSyntheticValue([], value)}\n value={value}\n disabled={readOnly}\n size={size}\n allowCustomValue\n onChange={(v) => field.onChange(v)}\n {...(defaultPlaceholder(field.schema) ? { placeholder: defaultPlaceholder(field.schema) } : {})}\n />\n );\n }\n\n return (\n <Combobox\n id={fieldId}\n options={withSyntheticValue(options, value)}\n value={value}\n disabled={readOnly}\n size={size}\n loading={loading}\n allowCustomValue={field.allowCustomValue ?? false}\n onSearch={onSearch}\n onChange={(v) => field.onChange(v)}\n {...(defaultPlaceholder(field.schema) ? { placeholder: defaultPlaceholder(field.schema) } : {})}\n />\n );\n}\n\n// RadioGroupControl renders a small fixed enum as a segmented radio-button group\n// instead of a dropdown. It shares EnumControl's option list (any out-of-enum\n// value is already prepended, so a token still shows). One `radiogroup` role +\n// native radios keep it keyboard-navigable; the visible chip is a styled label.\nfunction RadioGroupControl({\n field,\n fieldId,\n readOnly,\n options,\n value,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n options: FieldOption[];\n value: string;\n size: FormSize;\n}) {\n return (\n <div\n role=\"radiogroup\"\n aria-label={field.label}\n id={fieldId}\n data-jsf-input\n className=\"inline-flex flex-wrap items-center gap-1 rounded-md border border-input bg-background p-0.5\"\n >\n {options.map((opt) => {\n const checked = opt.value === value;\n return (\n <label\n key={opt.value}\n className={cn(\n \"inline-flex cursor-pointer select-none items-center rounded px-2.5 py-1\",\n labelSizeClass[size],\n checked\n ? \"bg-primary text-primary-foreground\"\n : \"text-muted-foreground hover:bg-accent hover:text-foreground\",\n readOnly && \"cursor-not-allowed opacity-60\",\n )}\n >\n <input\n type=\"radio\"\n name={fieldId}\n className=\"sr-only\"\n value={opt.value}\n checked={checked}\n disabled={readOnly}\n onChange={() => field.onChange(opt.value)}\n />\n {opt.label}\n </label>\n );\n })}\n </div>\n );\n}\n\n// TextareaControl edits a long-form string in a multi-line box. Read-only, it\n// shows the value with line breaks preserved; editable, a resizable <textarea>.\n// The raw string is committed unchanged so a consumer-permitted template token\n// survives.\nexport function TextareaControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n const text = toText(field.value);\n if (readOnly) {\n return (\n <span\n id={fieldId}\n data-jsf-input\n data-jsf-readonly\n className={cn(\"block whitespace-pre-wrap break-words text-foreground\", labelSizeClass[size])}\n title={text || undefined}\n >\n {text || <span className=\"text-muted-foreground\">—</span>}\n </span>\n );\n }\n return (\n <FieldAdornmentWrapper prefix={field.prefix} suffix={field.suffix}>\n <textarea\n id={fieldId}\n data-jsf-input\n rows={4}\n className={cn(inputClass(size), \"h-auto min-h-[5rem] resize-y\", field.prefix && \"pl-8\", field.suffix && \"pr-8\")}\n value={text}\n disabled={readOnly}\n placeholder={defaultPlaceholder(field.schema)}\n onChange={(e) => field.onChange(e.target.value)}\n />\n </FieldAdornmentWrapper>\n );\n}\n\n// DisplayControl renders a static, non-editable presentation element:\n// Label/Title (heading), Message (info text), Line (divider), or Blank/Filler\n// (spacer). It never collects a value; the heading/text source is the field's\n// title (label) and, for \"text\", its description. Rendered identically in the\n// form and the read-only Viewer.\nexport function DisplayControl({ field, size }: { field: FieldControl; size: FormSize }) {\n const variant = field.displayVariant ?? \"text\";\n if (variant === \"divider\") {\n return <hr data-jsf-input className=\"my-1 w-full border-t border-border\" />;\n }\n if (variant === \"spacer\") {\n return <div data-jsf-input aria-hidden className=\"h-2\" />;\n }\n if (variant === \"heading\") {\n return (\n <div\n data-jsf-input\n className={cn(\"border-b border-border pb-1 font-semibold text-foreground\", labelSizeClass[size])}\n >\n {field.label}\n </div>\n );\n }\n const text = field.description ?? toText(field.value) ?? field.label;\n return (\n <p data-jsf-input className={cn(\"text-muted-foreground\", labelSizeClass[size])}>\n {text || field.label}\n </p>\n );\n}\n\n// LinkControl renders a read-only external hyperlink. The\n// href is field.href, falling back to the value when it is an absolute URL; with\n// neither it degrades to a plain read-only value.\nexport function LinkControl({ field, fieldId, size }: { field: FieldControl; fieldId: string; size: FormSize }) {\n const text = toText(field.value);\n const href = field.href ?? (/^https?:\\/\\//i.test(text) ? text : undefined);\n if (!href) {\n return <ReadOnlyValue field={field} fieldId={fieldId} size={size} />;\n }\n return (\n <a\n id={fieldId}\n data-jsf-input\n href={href}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className={cn(\"inline-flex items-center text-primary underline underline-offset-2\", controlHeightClass[size], labelSizeClass[size])}\n >\n {text || field.label || href}\n </a>\n );\n}\n\n// HMR probe\n// HMR probe 2\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ const utils = require("../lib/utils.cjs");
6
+ const Icon = require("../data/Icon.cjs");
7
+ const jsonSchemaFormUtils = require("./json-schema-form-utils.cjs");
8
+ const jsonSchemaFormSize = require("./json-schema-form-size.cjs");
9
+ function GridControl({
10
+ field,
11
+ fieldId,
12
+ readOnly,
13
+ size
14
+ }) {
15
+ const value = jsonSchemaFormUtils.toText(field.value);
16
+ const [query, setQuery] = react.useState("");
17
+ const options = jsonSchemaFormUtils.withSyntheticValue(field.options ?? [], value);
18
+ if (readOnly) {
19
+ const selected = options.find((o) => o.value === value);
20
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { id: fieldId, "data-jsf-input": true, children: /* @__PURE__ */ jsxRuntime.jsx(GridCard, { option: selected ?? { value, label: value }, checked: true, readOnly: true, size, onSelect: () => {
21
+ } }) });
22
+ }
23
+ const q = query.trim().toLowerCase();
24
+ const visible = q ? options.filter((o) => o.label.toLowerCase().includes(q) || o.value.toLowerCase().includes(q)) : options;
25
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-2", children: [
26
+ /* @__PURE__ */ jsxRuntime.jsx(
27
+ "input",
28
+ {
29
+ type: "search",
30
+ "aria-label": `Filter ${field.label}`,
31
+ placeholder: "Filter…",
32
+ value: query,
33
+ onChange: (e) => setQuery(e.target.value),
34
+ className: jsonSchemaFormUtils.inputClass(size)
35
+ }
36
+ ),
37
+ /* @__PURE__ */ jsxRuntime.jsxs(
38
+ "div",
39
+ {
40
+ role: "radiogroup",
41
+ "aria-label": field.label,
42
+ id: fieldId,
43
+ "data-jsf-input": true,
44
+ className: "grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4",
45
+ children: [
46
+ visible.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
47
+ GridCard,
48
+ {
49
+ option: opt,
50
+ checked: opt.value === value,
51
+ readOnly: false,
52
+ size,
53
+ onSelect: () => field.onChange(opt.value)
54
+ },
55
+ opt.value
56
+ )),
57
+ visible.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: utils.cn("col-span-full py-4 text-center text-muted-foreground", jsonSchemaFormSize.labelSizeClass[size]), children: "No matches" })
58
+ ]
59
+ }
60
+ )
61
+ ] });
62
+ }
63
+ function GridCard({
64
+ option,
65
+ checked,
66
+ readOnly,
67
+ size,
68
+ onSelect
69
+ }) {
70
+ return /* @__PURE__ */ jsxRuntime.jsxs(
71
+ "button",
72
+ {
73
+ type: "button",
74
+ role: "radio",
75
+ "aria-checked": checked,
76
+ disabled: readOnly,
77
+ onClick: onSelect,
78
+ className: utils.cn(
79
+ "flex flex-col items-center justify-center gap-1.5 rounded-md border p-3 text-center transition-colors",
80
+ jsonSchemaFormSize.labelSizeClass[size],
81
+ checked ? "border-primary bg-primary/5 ring-1 ring-primary" : "border-input hover:border-primary/50 hover:bg-accent",
82
+ readOnly && "cursor-default opacity-80"
83
+ ),
84
+ children: [
85
+ /* @__PURE__ */ jsxRuntime.jsx(Icon.LabelIcon, { icon: option.icon, className: "text-2xl text-foreground" }),
86
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-words leading-tight", children: option.label })
87
+ ]
88
+ }
89
+ );
90
+ }
91
+ exports.GridControl = GridControl;
92
+ //# sourceMappingURL=json-schema-form-grid.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema-form-grid.cjs","sources":["../../src/components/json-schema-form-grid.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { LabelIcon } from \"../data/Icon\";\nimport type { FieldControl, FieldOption } from \"./json-schema-form-types\";\nimport { inputClass, toText, withSyntheticValue } from \"./json-schema-form-utils\";\nimport { labelSizeClass, type FormSize } from \"./json-schema-form-size\";\n\n// GridControl renders an enum as a filterable grid of selectable icon cards\n// (instead of a dropdown). It is the presentation for enums carrying\n// x-enum-icons — e.g. the connection \"type\" picker. The current value is always\n// selectable even if it is outside the enum (a template token still shows).\n// Read-only: only the selected card renders, disabled.\nexport function GridControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n const value = toText(field.value);\n const [query, setQuery] = useState(\"\");\n const options = withSyntheticValue(field.options ?? [], value);\n\n if (readOnly) {\n const selected = options.find((o) => o.value === value);\n return (\n <div id={fieldId} data-jsf-input>\n <GridCard option={selected ?? { value, label: value }} checked readOnly size={size} onSelect={() => {}} />\n </div>\n );\n }\n\n const q = query.trim().toLowerCase();\n const visible = q\n ? options.filter((o) => o.label.toLowerCase().includes(q) || o.value.toLowerCase().includes(q))\n : options;\n\n return (\n <div className=\"flex w-full flex-col gap-2\">\n <input\n type=\"search\"\n aria-label={`Filter ${field.label}`}\n placeholder=\"Filter…\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n className={inputClass(size)}\n />\n <div\n role=\"radiogroup\"\n aria-label={field.label}\n id={fieldId}\n data-jsf-input\n className=\"grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4\"\n >\n {visible.map((opt) => (\n <GridCard\n key={opt.value}\n option={opt}\n checked={opt.value === value}\n readOnly={false}\n size={size}\n onSelect={() => field.onChange(opt.value)}\n />\n ))}\n {visible.length === 0 && (\n <div className={cn(\"col-span-full py-4 text-center text-muted-foreground\", labelSizeClass[size])}>\n No matches\n </div>\n )}\n </div>\n </div>\n );\n}\n\n// GridCard is one selectable option in the grid: its icon over its label, with a\n// selected (primary ring) state. A native button with role=\"radio\" keeps it\n// keyboard-navigable and screen-reader-correct.\nfunction GridCard({\n option,\n checked,\n readOnly,\n size,\n onSelect,\n}: {\n option: FieldOption;\n checked: boolean;\n readOnly: boolean;\n size: FormSize;\n onSelect: () => void;\n}) {\n return (\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n disabled={readOnly}\n onClick={onSelect}\n className={cn(\n \"flex flex-col items-center justify-center gap-1.5 rounded-md border p-3 text-center transition-colors\",\n labelSizeClass[size],\n checked\n ? \"border-primary bg-primary/5 ring-1 ring-primary\"\n : \"border-input hover:border-primary/50 hover:bg-accent\",\n readOnly && \"cursor-default opacity-80\",\n )}\n >\n <LabelIcon icon={option.icon} className=\"text-2xl text-foreground\" />\n <span className=\"break-words leading-tight\">{option.label}</span>\n </button>\n );\n}\n"],"names":["toText","useState","withSyntheticValue","jsx","jsxs","inputClass","cn","labelSizeClass","LabelIcon"],"mappings":";;;;;;;;AAYO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,QAAQA,oBAAAA,OAAO,MAAM,KAAK;AAChC,QAAM,CAAC,OAAO,QAAQ,IAAIC,MAAAA,SAAS,EAAE;AACrC,QAAM,UAAUC,oBAAAA,mBAAmB,MAAM,WAAW,CAAA,GAAI,KAAK;AAE7D,MAAI,UAAU;AACZ,UAAM,WAAW,QAAQ,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK;AACtD,WACEC,+BAAC,SAAI,IAAI,SAAS,kBAAc,MAC9B,UAAAA,+BAAC,YAAS,QAAQ,YAAY,EAAE,OAAO,OAAO,SAAS,SAAO,MAAC,UAAQ,MAAC,MAAY,UAAU,MAAM;AAAA,IAAC,GAAG,EAAA,CAC1G;AAAA,EAEJ;AAEA,QAAM,IAAI,MAAM,KAAA,EAAO,YAAA;AACvB,QAAM,UAAU,IACZ,QAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,YAAA,EAAc,SAAS,CAAC,KAAK,EAAE,MAAM,YAAA,EAAc,SAAS,CAAC,CAAC,IAC5F;AAEJ,SACEC,2BAAAA,KAAC,OAAA,EAAI,WAAU,8BACb,UAAA;AAAA,IAAAD,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY,UAAU,MAAM,KAAK;AAAA,QACjC,aAAY;AAAA,QACZ,OAAO;AAAA,QACP,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,QACxC,WAAWE,oBAAAA,WAAW,IAAI;AAAA,MAAA;AAAA,IAAA;AAAA,IAE5BD,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY,MAAM;AAAA,QAClB,IAAI;AAAA,QACJ,kBAAc;AAAA,QACd,WAAU;AAAA,QAET,UAAA;AAAA,UAAA,QAAQ,IAAI,CAAC,QACZD,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cAEC,QAAQ;AAAA,cACR,SAAS,IAAI,UAAU;AAAA,cACvB,UAAU;AAAA,cACV;AAAA,cACA,UAAU,MAAM,MAAM,SAAS,IAAI,KAAK;AAAA,YAAA;AAAA,YALnC,IAAI;AAAA,UAAA,CAOZ;AAAA,UACA,QAAQ,WAAW,KAClBA,2BAAAA,IAAC,OAAA,EAAI,WAAWG,SAAG,wDAAwDC,mBAAAA,eAAe,IAAI,CAAC,GAAG,UAAA,aAAA,CAElG;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAEJ,GACF;AAEJ;AAKA,SAAS,SAAS;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACEH,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,MAAK;AAAA,MACL,gBAAc;AAAA,MACd,UAAU;AAAA,MACV,SAAS;AAAA,MACT,WAAWE,MAAAA;AAAAA,QACT;AAAA,QACAC,mBAAAA,eAAe,IAAI;AAAA,QACnB,UACI,oDACA;AAAA,QACJ,YAAY;AAAA,MAAA;AAAA,MAGd,UAAA;AAAA,QAAAJ,2BAAAA,IAACK,KAAAA,WAAA,EAAU,MAAM,OAAO,MAAM,WAAU,4BAA2B;AAAA,QACnEL,2BAAAA,IAAC,QAAA,EAAK,WAAU,6BAA6B,iBAAO,MAAA,CAAM;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGhE;;"}
@@ -0,0 +1,9 @@
1
+ import { FieldControl } from './json-schema-form-types';
2
+ import { FormSize } from './json-schema-form-size';
3
+ export declare function GridControl({ field, fieldId, readOnly, size, }: {
4
+ field: FieldControl;
5
+ fieldId: string;
6
+ readOnly: boolean;
7
+ size: FormSize;
8
+ }): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=json-schema-form-grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema-form-grid.d.ts","sourceRoot":"","sources":["../../src/components/json-schema-form-grid.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,0BAA0B,CAAC;AAE1E,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAOxE,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,OAAO,EACP,QAAQ,EACR,IAAI,GACL,EAAE;IACD,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,QAAQ,CAAC;CAChB,2CAsDA"}
@@ -0,0 +1,92 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { cn } from "../lib/utils.js";
4
+ import { LabelIcon } from "../data/Icon.js";
5
+ import { toText, withSyntheticValue, inputClass } from "./json-schema-form-utils.js";
6
+ import { labelSizeClass } from "./json-schema-form-size.js";
7
+ function GridControl({
8
+ field,
9
+ fieldId,
10
+ readOnly,
11
+ size
12
+ }) {
13
+ const value = toText(field.value);
14
+ const [query, setQuery] = useState("");
15
+ const options = withSyntheticValue(field.options ?? [], value);
16
+ if (readOnly) {
17
+ const selected = options.find((o) => o.value === value);
18
+ return /* @__PURE__ */ jsx("div", { id: fieldId, "data-jsf-input": true, children: /* @__PURE__ */ jsx(GridCard, { option: selected ?? { value, label: value }, checked: true, readOnly: true, size, onSelect: () => {
19
+ } }) });
20
+ }
21
+ const q = query.trim().toLowerCase();
22
+ const visible = q ? options.filter((o) => o.label.toLowerCase().includes(q) || o.value.toLowerCase().includes(q)) : options;
23
+ return /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-2", children: [
24
+ /* @__PURE__ */ jsx(
25
+ "input",
26
+ {
27
+ type: "search",
28
+ "aria-label": `Filter ${field.label}`,
29
+ placeholder: "Filter…",
30
+ value: query,
31
+ onChange: (e) => setQuery(e.target.value),
32
+ className: inputClass(size)
33
+ }
34
+ ),
35
+ /* @__PURE__ */ jsxs(
36
+ "div",
37
+ {
38
+ role: "radiogroup",
39
+ "aria-label": field.label,
40
+ id: fieldId,
41
+ "data-jsf-input": true,
42
+ className: "grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4",
43
+ children: [
44
+ visible.map((opt) => /* @__PURE__ */ jsx(
45
+ GridCard,
46
+ {
47
+ option: opt,
48
+ checked: opt.value === value,
49
+ readOnly: false,
50
+ size,
51
+ onSelect: () => field.onChange(opt.value)
52
+ },
53
+ opt.value
54
+ )),
55
+ visible.length === 0 && /* @__PURE__ */ jsx("div", { className: cn("col-span-full py-4 text-center text-muted-foreground", labelSizeClass[size]), children: "No matches" })
56
+ ]
57
+ }
58
+ )
59
+ ] });
60
+ }
61
+ function GridCard({
62
+ option,
63
+ checked,
64
+ readOnly,
65
+ size,
66
+ onSelect
67
+ }) {
68
+ return /* @__PURE__ */ jsxs(
69
+ "button",
70
+ {
71
+ type: "button",
72
+ role: "radio",
73
+ "aria-checked": checked,
74
+ disabled: readOnly,
75
+ onClick: onSelect,
76
+ className: cn(
77
+ "flex flex-col items-center justify-center gap-1.5 rounded-md border p-3 text-center transition-colors",
78
+ labelSizeClass[size],
79
+ checked ? "border-primary bg-primary/5 ring-1 ring-primary" : "border-input hover:border-primary/50 hover:bg-accent",
80
+ readOnly && "cursor-default opacity-80"
81
+ ),
82
+ children: [
83
+ /* @__PURE__ */ jsx(LabelIcon, { icon: option.icon, className: "text-2xl text-foreground" }),
84
+ /* @__PURE__ */ jsx("span", { className: "break-words leading-tight", children: option.label })
85
+ ]
86
+ }
87
+ );
88
+ }
89
+ export {
90
+ GridControl
91
+ };
92
+ //# sourceMappingURL=json-schema-form-grid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema-form-grid.js","sources":["../../src/components/json-schema-form-grid.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { LabelIcon } from \"../data/Icon\";\nimport type { FieldControl, FieldOption } from \"./json-schema-form-types\";\nimport { inputClass, toText, withSyntheticValue } from \"./json-schema-form-utils\";\nimport { labelSizeClass, type FormSize } from \"./json-schema-form-size\";\n\n// GridControl renders an enum as a filterable grid of selectable icon cards\n// (instead of a dropdown). It is the presentation for enums carrying\n// x-enum-icons — e.g. the connection \"type\" picker. The current value is always\n// selectable even if it is outside the enum (a template token still shows).\n// Read-only: only the selected card renders, disabled.\nexport function GridControl({\n field,\n fieldId,\n readOnly,\n size,\n}: {\n field: FieldControl;\n fieldId: string;\n readOnly: boolean;\n size: FormSize;\n}) {\n const value = toText(field.value);\n const [query, setQuery] = useState(\"\");\n const options = withSyntheticValue(field.options ?? [], value);\n\n if (readOnly) {\n const selected = options.find((o) => o.value === value);\n return (\n <div id={fieldId} data-jsf-input>\n <GridCard option={selected ?? { value, label: value }} checked readOnly size={size} onSelect={() => {}} />\n </div>\n );\n }\n\n const q = query.trim().toLowerCase();\n const visible = q\n ? options.filter((o) => o.label.toLowerCase().includes(q) || o.value.toLowerCase().includes(q))\n : options;\n\n return (\n <div className=\"flex w-full flex-col gap-2\">\n <input\n type=\"search\"\n aria-label={`Filter ${field.label}`}\n placeholder=\"Filter…\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n className={inputClass(size)}\n />\n <div\n role=\"radiogroup\"\n aria-label={field.label}\n id={fieldId}\n data-jsf-input\n className=\"grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4\"\n >\n {visible.map((opt) => (\n <GridCard\n key={opt.value}\n option={opt}\n checked={opt.value === value}\n readOnly={false}\n size={size}\n onSelect={() => field.onChange(opt.value)}\n />\n ))}\n {visible.length === 0 && (\n <div className={cn(\"col-span-full py-4 text-center text-muted-foreground\", labelSizeClass[size])}>\n No matches\n </div>\n )}\n </div>\n </div>\n );\n}\n\n// GridCard is one selectable option in the grid: its icon over its label, with a\n// selected (primary ring) state. A native button with role=\"radio\" keeps it\n// keyboard-navigable and screen-reader-correct.\nfunction GridCard({\n option,\n checked,\n readOnly,\n size,\n onSelect,\n}: {\n option: FieldOption;\n checked: boolean;\n readOnly: boolean;\n size: FormSize;\n onSelect: () => void;\n}) {\n return (\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n disabled={readOnly}\n onClick={onSelect}\n className={cn(\n \"flex flex-col items-center justify-center gap-1.5 rounded-md border p-3 text-center transition-colors\",\n labelSizeClass[size],\n checked\n ? \"border-primary bg-primary/5 ring-1 ring-primary\"\n : \"border-input hover:border-primary/50 hover:bg-accent\",\n readOnly && \"cursor-default opacity-80\",\n )}\n >\n <LabelIcon icon={option.icon} className=\"text-2xl text-foreground\" />\n <span className=\"break-words leading-tight\">{option.label}</span>\n </button>\n );\n}\n"],"names":[],"mappings":";;;;;;AAYO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,QAAQ,OAAO,MAAM,KAAK;AAChC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,UAAU,mBAAmB,MAAM,WAAW,CAAA,GAAI,KAAK;AAE7D,MAAI,UAAU;AACZ,UAAM,WAAW,QAAQ,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK;AACtD,WACE,oBAAC,SAAI,IAAI,SAAS,kBAAc,MAC9B,UAAA,oBAAC,YAAS,QAAQ,YAAY,EAAE,OAAO,OAAO,SAAS,SAAO,MAAC,UAAQ,MAAC,MAAY,UAAU,MAAM;AAAA,IAAC,GAAG,EAAA,CAC1G;AAAA,EAEJ;AAEA,QAAM,IAAI,MAAM,KAAA,EAAO,YAAA;AACvB,QAAM,UAAU,IACZ,QAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,YAAA,EAAc,SAAS,CAAC,KAAK,EAAE,MAAM,YAAA,EAAc,SAAS,CAAC,CAAC,IAC5F;AAEJ,SACE,qBAAC,OAAA,EAAI,WAAU,8BACb,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY,UAAU,MAAM,KAAK;AAAA,QACjC,aAAY;AAAA,QACZ,OAAO;AAAA,QACP,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,QACxC,WAAW,WAAW,IAAI;AAAA,MAAA;AAAA,IAAA;AAAA,IAE5B;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY,MAAM;AAAA,QAClB,IAAI;AAAA,QACJ,kBAAc;AAAA,QACd,WAAU;AAAA,QAET,UAAA;AAAA,UAAA,QAAQ,IAAI,CAAC,QACZ;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,QAAQ;AAAA,cACR,SAAS,IAAI,UAAU;AAAA,cACvB,UAAU;AAAA,cACV;AAAA,cACA,UAAU,MAAM,MAAM,SAAS,IAAI,KAAK;AAAA,YAAA;AAAA,YALnC,IAAI;AAAA,UAAA,CAOZ;AAAA,UACA,QAAQ,WAAW,KAClB,oBAAC,OAAA,EAAI,WAAW,GAAG,wDAAwD,eAAe,IAAI,CAAC,GAAG,UAAA,aAAA,CAElG;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAEJ,GACF;AAEJ;AAKA,SAAS,SAAS;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,MAAK;AAAA,MACL,gBAAc;AAAA,MACd,UAAU;AAAA,MACV,SAAS;AAAA,MACT,WAAW;AAAA,QACT;AAAA,QACA,eAAe,IAAI;AAAA,QACnB,UACI,oDACA;AAAA,QACJ,YAAY;AAAA,MAAA;AAAA,MAGd,UAAA;AAAA,QAAA,oBAAC,WAAA,EAAU,MAAM,OAAO,MAAM,WAAU,4BAA2B;AAAA,QACnE,oBAAC,QAAA,EAAK,WAAU,6BAA6B,iBAAO,MAAA,CAAM;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGhE;"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const DEFS_PREFIX = "#/$defs/";
4
+ function rehydrateRefs(schema) {
5
+ const defs = schema["$defs"];
6
+ if (!defs || Object.keys(defs).length === 0) return schema;
7
+ const cache = /* @__PURE__ */ new Map();
8
+ const resolving = /* @__PURE__ */ new Set();
9
+ const resolveDef = (key) => {
10
+ const cached = cache.get(key);
11
+ if (cached) return cached;
12
+ if (resolving.has(key)) return { type: "object", description: "↻ recursive schema" };
13
+ const body = defs[key];
14
+ if (body === void 0) return {};
15
+ resolving.add(key);
16
+ const resolved = walk(body);
17
+ resolving.delete(key);
18
+ cache.set(key, resolved);
19
+ return resolved;
20
+ };
21
+ const walk = (node) => {
22
+ if (Array.isArray(node)) {
23
+ let changed = false;
24
+ const out = node.map((v) => {
25
+ const w = walk(v);
26
+ if (w !== v) changed = true;
27
+ return w;
28
+ });
29
+ return changed ? out : node;
30
+ }
31
+ if (node && typeof node === "object") {
32
+ const obj = node;
33
+ const ref = obj["$ref"];
34
+ if (typeof ref === "string" && ref.startsWith(DEFS_PREFIX)) {
35
+ const resolved = resolveDef(ref.slice(DEFS_PREFIX.length));
36
+ const siblings = {};
37
+ let hasSiblings = false;
38
+ for (const [k, v] of Object.entries(obj)) {
39
+ if (k === "$ref") continue;
40
+ siblings[k] = walk(v);
41
+ hasSiblings = true;
42
+ }
43
+ return hasSiblings ? { ...resolved, ...siblings } : resolved;
44
+ }
45
+ let changed = false;
46
+ const out = {};
47
+ for (const [k, v] of Object.entries(obj)) {
48
+ const w = walk(v);
49
+ out[k] = w;
50
+ if (w !== v) changed = true;
51
+ }
52
+ return changed ? out : node;
53
+ }
54
+ return node;
55
+ };
56
+ const { $defs: _defs, ...rest } = schema;
57
+ return walk(rest);
58
+ }
59
+ exports.rehydrateRefs = rehydrateRefs;
60
+ //# sourceMappingURL=json-schema-form-refs.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema-form-refs.cjs","sources":["../../src/components/json-schema-form-refs.ts"],"sourcesContent":["import type { JsonSchemaObject, JsonSchemaProperty } from \"./json-schema-form-types\";\n\nconst DEFS_PREFIX = \"#/$defs/\";\n\n// rehydrateRefs resolves a BUNDLED schema — one whose components live under\n// `$defs` and are referenced by local `#/$defs/<key>` pointers (the shape the\n// server's refs=inline bundling emits) — into a self-contained tree the existing\n// renderer walks directly. It is the read-side counterpart of bundling: where\n// bundling collapses a component referenced N times to one `$defs` entry + N\n// local pointers, this expands those pointers back to the (shared, by-reference)\n// component, so the component's bytes still cost O(1) in memory, not O(N).\n//\n// Each unique `$defs` entry is resolved once and shared by reference; a cyclic\n// ref is broken with a non-recursive stub, so the result is always a finite DAG\n// the recursive renderer can traverse without a depth cap. A schema with no\n// `$defs` is returned unchanged (the common, already-self-contained case), so\n// this is a no-op for non-bundled schemas.\nexport function rehydrateRefs(schema: JsonSchemaObject): JsonSchemaObject {\n const defs = (schema as Record<string, unknown>)[\"$defs\"] as\n | Record<string, JsonSchemaProperty>\n | undefined;\n if (!defs || Object.keys(defs).length === 0) return schema;\n\n const cache = new Map<string, JsonSchemaProperty>();\n const resolving = new Set<string>();\n\n const resolveDef = (key: string): JsonSchemaProperty => {\n const cached = cache.get(key);\n if (cached) return cached;\n // A ref to a def already on the resolution stack is a cycle: break it with a\n // permissive stub rather than building a self-referential object graph.\n if (resolving.has(key)) return { type: \"object\", description: \"↻ recursive schema\" };\n const body = defs[key];\n if (body === undefined) return {}; // dangling local ref → permissive object\n resolving.add(key);\n const resolved = walk(body) as JsonSchemaProperty;\n resolving.delete(key);\n cache.set(key, resolved);\n return resolved;\n };\n\n // walk rewrites local `#/$defs` refs and otherwise REUSES the input node by\n // reference when nothing beneath it changed (structural sharing). This is what\n // keeps rehydration cheap: a ref-free component — e.g. address-form.json, which\n // is 5.6MB with no internal refs — is returned as-is, never deep-rebuilt, so\n // only the (small) ref-bearing spine of the document is reallocated.\n const walk = (node: unknown): unknown => {\n if (Array.isArray(node)) {\n let changed = false;\n const out = node.map((v) => {\n const w = walk(v);\n if (w !== v) changed = true;\n return w;\n });\n return changed ? out : node;\n }\n if (node && typeof node === \"object\") {\n const obj = node as Record<string, unknown>;\n const ref = obj[\"$ref\"];\n if (typeof ref === \"string\" && ref.startsWith(DEFS_PREFIX)) {\n const resolved = resolveDef(ref.slice(DEFS_PREFIX.length));\n // A `$ref` alongside siblings: the siblings are local keywords that win\n // over the referenced body (JSON Schema 2020-12 semantics), e.g.\n // `allOf:[{$ref, title}]`.\n const siblings: Record<string, unknown> = {};\n let hasSiblings = false;\n for (const [k, v] of Object.entries(obj)) {\n if (k === \"$ref\") continue;\n siblings[k] = walk(v);\n hasSiblings = true;\n }\n return hasSiblings ? { ...resolved, ...siblings } : resolved;\n }\n let changed = false;\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n const w = walk(v);\n out[k] = w;\n if (w !== v) changed = true;\n }\n return changed ? out : node;\n }\n return node;\n };\n\n // Drop `$defs` from the rendered root — every reference to it is now resolved\n // inline (by shared reference), so it is dead weight the renderer would ignore.\n const { $defs: _defs, ...rest } = schema as Record<string, unknown>;\n void _defs;\n return walk(rest) as JsonSchemaObject;\n}\n"],"names":[],"mappings":";;AAEA,MAAM,cAAc;AAeb,SAAS,cAAc,QAA4C;AACxE,QAAM,OAAQ,OAAmC,OAAO;AAGxD,MAAI,CAAC,QAAQ,OAAO,KAAK,IAAI,EAAE,WAAW,EAAG,QAAO;AAEpD,QAAM,4BAAY,IAAA;AAClB,QAAM,gCAAgB,IAAA;AAEtB,QAAM,aAAa,CAAC,QAAoC;AACtD,UAAM,SAAS,MAAM,IAAI,GAAG;AAC5B,QAAI,OAAQ,QAAO;AAGnB,QAAI,UAAU,IAAI,GAAG,UAAU,EAAE,MAAM,UAAU,aAAa,qBAAA;AAC9D,UAAM,OAAO,KAAK,GAAG;AACrB,QAAI,SAAS,OAAW,QAAO,CAAA;AAC/B,cAAU,IAAI,GAAG;AACjB,UAAM,WAAW,KAAK,IAAI;AAC1B,cAAU,OAAO,GAAG;AACpB,UAAM,IAAI,KAAK,QAAQ;AACvB,WAAO;AAAA,EACT;AAOA,QAAM,OAAO,CAAC,SAA2B;AACvC,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,UAAI,UAAU;AACd,YAAM,MAAM,KAAK,IAAI,CAAC,MAAM;AAC1B,cAAM,IAAI,KAAK,CAAC;AAChB,YAAI,MAAM,EAAG,WAAU;AACvB,eAAO;AAAA,MACT,CAAC;AACD,aAAO,UAAU,MAAM;AAAA,IACzB;AACA,QAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,YAAM,MAAM;AACZ,YAAM,MAAM,IAAI,MAAM;AACtB,UAAI,OAAO,QAAQ,YAAY,IAAI,WAAW,WAAW,GAAG;AAC1D,cAAM,WAAW,WAAW,IAAI,MAAM,YAAY,MAAM,CAAC;AAIzD,cAAM,WAAoC,CAAA;AAC1C,YAAI,cAAc;AAClB,mBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,cAAI,MAAM,OAAQ;AAClB,mBAAS,CAAC,IAAI,KAAK,CAAC;AACpB,wBAAc;AAAA,QAChB;AACA,eAAO,cAAc,EAAE,GAAG,UAAU,GAAG,aAAa;AAAA,MACtD;AACA,UAAI,UAAU;AACd,YAAM,MAA+B,CAAA;AACrC,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,cAAM,IAAI,KAAK,CAAC;AAChB,YAAI,CAAC,IAAI;AACT,YAAI,MAAM,EAAG,WAAU;AAAA,MACzB;AACA,aAAO,UAAU,MAAM;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AAIA,QAAM,EAAE,OAAO,OAAO,GAAG,SAAS;AAElC,SAAO,KAAK,IAAI;AAClB;;"}
@@ -0,0 +1,3 @@
1
+ import { JsonSchemaObject } from './json-schema-form-types';
2
+ export declare function rehydrateRefs(schema: JsonSchemaObject): JsonSchemaObject;
3
+ //# sourceMappingURL=json-schema-form-refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema-form-refs.d.ts","sourceRoot":"","sources":["../../src/components/json-schema-form-refs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,0BAA0B,CAAC;AAiBrF,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAyExE"}
@@ -0,0 +1,60 @@
1
+ const DEFS_PREFIX = "#/$defs/";
2
+ function rehydrateRefs(schema) {
3
+ const defs = schema["$defs"];
4
+ if (!defs || Object.keys(defs).length === 0) return schema;
5
+ const cache = /* @__PURE__ */ new Map();
6
+ const resolving = /* @__PURE__ */ new Set();
7
+ const resolveDef = (key) => {
8
+ const cached = cache.get(key);
9
+ if (cached) return cached;
10
+ if (resolving.has(key)) return { type: "object", description: "↻ recursive schema" };
11
+ const body = defs[key];
12
+ if (body === void 0) return {};
13
+ resolving.add(key);
14
+ const resolved = walk(body);
15
+ resolving.delete(key);
16
+ cache.set(key, resolved);
17
+ return resolved;
18
+ };
19
+ const walk = (node) => {
20
+ if (Array.isArray(node)) {
21
+ let changed = false;
22
+ const out = node.map((v) => {
23
+ const w = walk(v);
24
+ if (w !== v) changed = true;
25
+ return w;
26
+ });
27
+ return changed ? out : node;
28
+ }
29
+ if (node && typeof node === "object") {
30
+ const obj = node;
31
+ const ref = obj["$ref"];
32
+ if (typeof ref === "string" && ref.startsWith(DEFS_PREFIX)) {
33
+ const resolved = resolveDef(ref.slice(DEFS_PREFIX.length));
34
+ const siblings = {};
35
+ let hasSiblings = false;
36
+ for (const [k, v] of Object.entries(obj)) {
37
+ if (k === "$ref") continue;
38
+ siblings[k] = walk(v);
39
+ hasSiblings = true;
40
+ }
41
+ return hasSiblings ? { ...resolved, ...siblings } : resolved;
42
+ }
43
+ let changed = false;
44
+ const out = {};
45
+ for (const [k, v] of Object.entries(obj)) {
46
+ const w = walk(v);
47
+ out[k] = w;
48
+ if (w !== v) changed = true;
49
+ }
50
+ return changed ? out : node;
51
+ }
52
+ return node;
53
+ };
54
+ const { $defs: _defs, ...rest } = schema;
55
+ return walk(rest);
56
+ }
57
+ export {
58
+ rehydrateRefs
59
+ };
60
+ //# sourceMappingURL=json-schema-form-refs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema-form-refs.js","sources":["../../src/components/json-schema-form-refs.ts"],"sourcesContent":["import type { JsonSchemaObject, JsonSchemaProperty } from \"./json-schema-form-types\";\n\nconst DEFS_PREFIX = \"#/$defs/\";\n\n// rehydrateRefs resolves a BUNDLED schema — one whose components live under\n// `$defs` and are referenced by local `#/$defs/<key>` pointers (the shape the\n// server's refs=inline bundling emits) — into a self-contained tree the existing\n// renderer walks directly. It is the read-side counterpart of bundling: where\n// bundling collapses a component referenced N times to one `$defs` entry + N\n// local pointers, this expands those pointers back to the (shared, by-reference)\n// component, so the component's bytes still cost O(1) in memory, not O(N).\n//\n// Each unique `$defs` entry is resolved once and shared by reference; a cyclic\n// ref is broken with a non-recursive stub, so the result is always a finite DAG\n// the recursive renderer can traverse without a depth cap. A schema with no\n// `$defs` is returned unchanged (the common, already-self-contained case), so\n// this is a no-op for non-bundled schemas.\nexport function rehydrateRefs(schema: JsonSchemaObject): JsonSchemaObject {\n const defs = (schema as Record<string, unknown>)[\"$defs\"] as\n | Record<string, JsonSchemaProperty>\n | undefined;\n if (!defs || Object.keys(defs).length === 0) return schema;\n\n const cache = new Map<string, JsonSchemaProperty>();\n const resolving = new Set<string>();\n\n const resolveDef = (key: string): JsonSchemaProperty => {\n const cached = cache.get(key);\n if (cached) return cached;\n // A ref to a def already on the resolution stack is a cycle: break it with a\n // permissive stub rather than building a self-referential object graph.\n if (resolving.has(key)) return { type: \"object\", description: \"↻ recursive schema\" };\n const body = defs[key];\n if (body === undefined) return {}; // dangling local ref → permissive object\n resolving.add(key);\n const resolved = walk(body) as JsonSchemaProperty;\n resolving.delete(key);\n cache.set(key, resolved);\n return resolved;\n };\n\n // walk rewrites local `#/$defs` refs and otherwise REUSES the input node by\n // reference when nothing beneath it changed (structural sharing). This is what\n // keeps rehydration cheap: a ref-free component — e.g. address-form.json, which\n // is 5.6MB with no internal refs — is returned as-is, never deep-rebuilt, so\n // only the (small) ref-bearing spine of the document is reallocated.\n const walk = (node: unknown): unknown => {\n if (Array.isArray(node)) {\n let changed = false;\n const out = node.map((v) => {\n const w = walk(v);\n if (w !== v) changed = true;\n return w;\n });\n return changed ? out : node;\n }\n if (node && typeof node === \"object\") {\n const obj = node as Record<string, unknown>;\n const ref = obj[\"$ref\"];\n if (typeof ref === \"string\" && ref.startsWith(DEFS_PREFIX)) {\n const resolved = resolveDef(ref.slice(DEFS_PREFIX.length));\n // A `$ref` alongside siblings: the siblings are local keywords that win\n // over the referenced body (JSON Schema 2020-12 semantics), e.g.\n // `allOf:[{$ref, title}]`.\n const siblings: Record<string, unknown> = {};\n let hasSiblings = false;\n for (const [k, v] of Object.entries(obj)) {\n if (k === \"$ref\") continue;\n siblings[k] = walk(v);\n hasSiblings = true;\n }\n return hasSiblings ? { ...resolved, ...siblings } : resolved;\n }\n let changed = false;\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n const w = walk(v);\n out[k] = w;\n if (w !== v) changed = true;\n }\n return changed ? out : node;\n }\n return node;\n };\n\n // Drop `$defs` from the rendered root — every reference to it is now resolved\n // inline (by shared reference), so it is dead weight the renderer would ignore.\n const { $defs: _defs, ...rest } = schema as Record<string, unknown>;\n void _defs;\n return walk(rest) as JsonSchemaObject;\n}\n"],"names":[],"mappings":"AAEA,MAAM,cAAc;AAeb,SAAS,cAAc,QAA4C;AACxE,QAAM,OAAQ,OAAmC,OAAO;AAGxD,MAAI,CAAC,QAAQ,OAAO,KAAK,IAAI,EAAE,WAAW,EAAG,QAAO;AAEpD,QAAM,4BAAY,IAAA;AAClB,QAAM,gCAAgB,IAAA;AAEtB,QAAM,aAAa,CAAC,QAAoC;AACtD,UAAM,SAAS,MAAM,IAAI,GAAG;AAC5B,QAAI,OAAQ,QAAO;AAGnB,QAAI,UAAU,IAAI,GAAG,UAAU,EAAE,MAAM,UAAU,aAAa,qBAAA;AAC9D,UAAM,OAAO,KAAK,GAAG;AACrB,QAAI,SAAS,OAAW,QAAO,CAAA;AAC/B,cAAU,IAAI,GAAG;AACjB,UAAM,WAAW,KAAK,IAAI;AAC1B,cAAU,OAAO,GAAG;AACpB,UAAM,IAAI,KAAK,QAAQ;AACvB,WAAO;AAAA,EACT;AAOA,QAAM,OAAO,CAAC,SAA2B;AACvC,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,UAAI,UAAU;AACd,YAAM,MAAM,KAAK,IAAI,CAAC,MAAM;AAC1B,cAAM,IAAI,KAAK,CAAC;AAChB,YAAI,MAAM,EAAG,WAAU;AACvB,eAAO;AAAA,MACT,CAAC;AACD,aAAO,UAAU,MAAM;AAAA,IACzB;AACA,QAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,YAAM,MAAM;AACZ,YAAM,MAAM,IAAI,MAAM;AACtB,UAAI,OAAO,QAAQ,YAAY,IAAI,WAAW,WAAW,GAAG;AAC1D,cAAM,WAAW,WAAW,IAAI,MAAM,YAAY,MAAM,CAAC;AAIzD,cAAM,WAAoC,CAAA;AAC1C,YAAI,cAAc;AAClB,mBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,cAAI,MAAM,OAAQ;AAClB,mBAAS,CAAC,IAAI,KAAK,CAAC;AACpB,wBAAc;AAAA,QAChB;AACA,eAAO,cAAc,EAAE,GAAG,UAAU,GAAG,aAAa;AAAA,MACtD;AACA,UAAI,UAAU;AACd,YAAM,MAA+B,CAAA;AACrC,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,cAAM,IAAI,KAAK,CAAC;AAChB,YAAI,CAAC,IAAI;AACT,YAAI,MAAM,EAAG,WAAU;AAAA,MACzB;AACA,aAAO,UAAU,MAAM;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AAIA,QAAM,EAAE,OAAO,OAAO,GAAG,SAAS;AAElC,SAAO,KAAK,IAAI;AAClB;"}
@@ -12,20 +12,37 @@ const jsonSchemaFormUtils = require("./json-schema-form-utils.cjs");
12
12
  const jsonSchemaFormSize = require("./json-schema-form-size.cjs");
13
13
  function renderValueControl(field, ctx) {
14
14
  const fieldId = jsonSchemaFormUtils.fieldInputId(field.key, ctx.idPrefix);
15
- if (field.readOnly && field.kind !== "array" && field.kind !== "object" && field.kind !== "string-map") {
15
+ if (field.readOnly && !ownsReadOnlyRendering(field.kind)) {
16
16
  return /* @__PURE__ */ jsxRuntime.jsx(jsonSchemaFormFields.ReadOnlyValue, { field, fieldId, size: ctx.size });
17
17
  }
18
- const readOnly = ctx.readOnly;
18
+ const readOnly = ctx.readOnly || field.readOnly === true;
19
19
  const size = ctx.size;
20
20
  switch (field.kind) {
21
21
  case "enum":
22
22
  return /* @__PURE__ */ jsxRuntime.jsx(jsonSchemaFormFields.EnumControl, { field, fieldId, readOnly, size });
23
+ case "lookup":
24
+ return /* @__PURE__ */ jsxRuntime.jsx(
25
+ jsonSchemaFormFields.LookupControl,
26
+ {
27
+ field,
28
+ fieldId,
29
+ readOnly,
30
+ size,
31
+ ...ctx.rootValue ? { rootValue: ctx.rootValue } : {}
32
+ }
33
+ );
23
34
  case "boolean":
24
35
  return /* @__PURE__ */ jsxRuntime.jsx(jsonSchemaFormFields.BooleanControl, { field, fieldId, readOnly, size });
25
36
  case "number":
26
37
  return /* @__PURE__ */ jsxRuntime.jsx(jsonSchemaFormFields.NumberControl, { field, fieldId, readOnly, size });
27
38
  case "date":
28
39
  return /* @__PURE__ */ jsxRuntime.jsx(jsonSchemaFormFields.DateControl, { field, fieldId, readOnly, size });
40
+ case "textarea":
41
+ return /* @__PURE__ */ jsxRuntime.jsx(jsonSchemaFormFields.TextareaControl, { field, fieldId, readOnly, size });
42
+ case "display":
43
+ return /* @__PURE__ */ jsxRuntime.jsx(jsonSchemaFormFields.DisplayControl, { field, size });
44
+ case "link":
45
+ return /* @__PURE__ */ jsxRuntime.jsx(jsonSchemaFormFields.LinkControl, { field, fieldId, size });
29
46
  case "array":
30
47
  return /* @__PURE__ */ jsxRuntime.jsx(jsonSchemaFormArray.ArrayControl, { field, fieldId, ctx });
31
48
  case "object":
@@ -36,12 +53,20 @@ function renderValueControl(field, ctx) {
36
53
  return /* @__PURE__ */ jsxRuntime.jsx(jsonSchemaFormFields.StringControl, { field, fieldId, readOnly, size });
37
54
  }
38
55
  }
56
+ function ownsReadOnlyRendering(kind) {
57
+ return kind === "array" || kind === "object" || kind === "string-map" || kind === "textarea" || kind === "display" || kind === "link";
58
+ }
39
59
  function buildField(args, ctx) {
40
60
  const base = jsonSchemaFormResolve.resolveControl(args);
41
61
  let field = base;
42
62
  for (const ext of ctx.pre) {
43
63
  if (!field) break;
44
- field = ext(field, { key: args.key, prop: args.prop, value: args.value });
64
+ field = ext(field, {
65
+ key: args.key,
66
+ prop: args.prop,
67
+ value: args.value,
68
+ ...ctx.rootValue ? { rootValue: ctx.rootValue } : {}
69
+ });
45
70
  }
46
71
  if (!field) return null;
47
72
  if (ctx.hideReadOnlyFields && field.readOnly) return null;
@@ -50,8 +75,9 @@ function buildField(args, ctx) {
50
75
  const overrideMode = field.layout === "inline" ? "inline" : field.layout === "stack" ? "stacked" : void 0;
51
76
  const valueCtx = overrideMode ? { ...ctx, layout: { ...ctx.layout, mode: overrideMode } } : ctx;
52
77
  let value = renderValueControl(field, valueCtx);
78
+ const postCtx = ctx.rootValue ? { rootValue: ctx.rootValue } : {};
53
79
  for (const ext of ctx.post) {
54
- const next = ext(field, { label, value });
80
+ const next = ext(field, { label, value }, postCtx);
55
81
  label = next.label;
56
82
  value = next.value;
57
83
  }
@@ -80,6 +106,9 @@ function renderFieldRow(args, ctx, opts) {
80
106
  }
81
107
  );
82
108
  }
109
+ if (field.kind === "display") {
110
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-full", children: built.value });
111
+ }
83
112
  const label = (opts == null ? void 0 : opts.labelOverride) ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: utils.cn("flex items-center gap-2 font-medium", jsonSchemaFormSize.labelSizeClass[ctx.size]), children: [
84
113
  /* @__PURE__ */ jsxRuntime.jsx(Icon.LabelIcon, { icon: field.labelIcon, className: "text-[15px] text-muted-foreground" }),
85
114
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: opts.labelOverride }),
@@ -102,7 +131,7 @@ function renderFieldRow(args, ctx, opts) {
102
131
  function renderObjectFields(schema, value, onChange, ctx, opts) {
103
132
  const { properties, required } = jsonSchemaFormResolve.effectiveProperties(schema, value);
104
133
  const hidden = new Set((opts == null ? void 0 : opts.hiddenKeys) ?? []);
105
- const ordered = jsonSchemaFormUtils.orderByXOrder(Object.entries(properties), schema["x-order"]);
134
+ const ordered = jsonSchemaFormUtils.orderByClickyOrder(jsonSchemaFormUtils.orderByXOrder(Object.entries(properties), schema["x-order"]));
106
135
  const entries = ctx.sortMode === "required-first" ? jsonSchemaFormUtils.orderRequiredFirst(ordered, required) : ctx.sortMode === "priority" ? jsonSchemaFormUtils.orderByPriority(ordered, required, value) : ordered;
107
136
  return entries.flatMap(([key, prop]) => {
108
137
  if (hidden.has(key)) return [];