@qoretechnologies/reqraft 0.10.25 → 0.10.26

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 (310) hide show
  1. package/.claude/CLAUDE.md +52 -23
  2. package/design/COMPACT_ENGINE_REDESIGN.md +156 -0
  3. package/design/FORM_ENGINE_COMPACT_UX_PLAN.md +353 -0
  4. package/dist/components/FocusedEditing/index.d.ts +9 -1
  5. package/dist/components/FocusedEditing/index.d.ts.map +1 -1
  6. package/dist/components/FocusedEditing/index.js +2 -2
  7. package/dist/components/FocusedEditing/index.js.map +1 -1
  8. package/dist/components/composer/Composer.d.ts +108 -0
  9. package/dist/components/composer/Composer.d.ts.map +1 -0
  10. package/dist/components/composer/Composer.js +238 -0
  11. package/dist/components/composer/Composer.js.map +1 -0
  12. package/dist/components/composer/helpers.d.ts +21 -0
  13. package/dist/components/composer/helpers.d.ts.map +1 -0
  14. package/dist/components/composer/helpers.js +75 -0
  15. package/dist/components/composer/helpers.js.map +1 -0
  16. package/dist/components/composer/index.d.ts +3 -0
  17. package/dist/components/composer/index.d.ts.map +1 -0
  18. package/dist/components/composer/index.js +19 -0
  19. package/dist/components/composer/index.js.map +1 -0
  20. package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
  21. package/dist/components/form/engine/CompactRow.js +307 -110
  22. package/dist/components/form/engine/CompactRow.js.map +1 -1
  23. package/dist/components/form/engine/CompactToolbar.d.ts.map +1 -1
  24. package/dist/components/form/engine/CompactToolbar.js +123 -106
  25. package/dist/components/form/engine/CompactToolbar.js.map +1 -1
  26. package/dist/components/form/engine/FormEngine.d.ts +107 -11
  27. package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
  28. package/dist/components/form/engine/FormEngine.js +618 -179
  29. package/dist/components/form/engine/FormEngine.js.map +1 -1
  30. package/dist/components/form/engine/compactRowContext.d.ts +9 -0
  31. package/dist/components/form/engine/compactRowContext.d.ts.map +1 -1
  32. package/dist/components/form/engine/compactRowContext.js.map +1 -1
  33. package/dist/components/form/engine/compactRowStyles.d.ts +7 -3
  34. package/dist/components/form/engine/compactRowStyles.d.ts.map +1 -1
  35. package/dist/components/form/engine/compactRowStyles.js +88 -51
  36. package/dist/components/form/engine/compactRowStyles.js.map +1 -1
  37. package/dist/components/form/engine/compactToolbarContext.d.ts +1 -0
  38. package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
  39. package/dist/components/form/engine/compactToolbarContext.js.map +1 -1
  40. package/dist/components/form/engine/optionActions.d.ts +28 -0
  41. package/dist/components/form/engine/optionActions.d.ts.map +1 -0
  42. package/dist/components/form/engine/optionActions.js +18 -0
  43. package/dist/components/form/engine/optionActions.js.map +1 -0
  44. package/dist/components/form/engine/readFirst.d.ts +63 -2
  45. package/dist/components/form/engine/readFirst.d.ts.map +1 -1
  46. package/dist/components/form/engine/readFirst.js +121 -6
  47. package/dist/components/form/engine/readFirst.js.map +1 -1
  48. package/dist/components/form/engine/rendererTypes.d.ts +35 -0
  49. package/dist/components/form/engine/rendererTypes.d.ts.map +1 -0
  50. package/dist/components/form/engine/rendererTypes.js +63 -0
  51. package/dist/components/form/engine/rendererTypes.js.map +1 -0
  52. package/dist/components/form/engine/variants/VariantCalmTable.d.ts +6 -0
  53. package/dist/components/form/engine/variants/VariantCalmTable.d.ts.map +1 -0
  54. package/dist/components/form/engine/variants/VariantCalmTable.js +94 -0
  55. package/dist/components/form/engine/variants/VariantCalmTable.js.map +1 -0
  56. package/dist/components/form/engine/variants/VariantCards.d.ts +6 -0
  57. package/dist/components/form/engine/variants/VariantCards.d.ts.map +1 -0
  58. package/dist/components/form/engine/variants/VariantCards.js +80 -0
  59. package/dist/components/form/engine/variants/VariantCards.js.map +1 -0
  60. package/dist/components/form/engine/variants/VariantFocus.d.ts +7 -0
  61. package/dist/components/form/engine/variants/VariantFocus.d.ts.map +1 -0
  62. package/dist/components/form/engine/variants/VariantFocus.js +138 -0
  63. package/dist/components/form/engine/variants/VariantFocus.js.map +1 -0
  64. package/dist/components/form/engine/variants/VariantMinimal.d.ts +6 -0
  65. package/dist/components/form/engine/variants/VariantMinimal.d.ts.map +1 -0
  66. package/dist/components/form/engine/variants/VariantMinimal.js +73 -0
  67. package/dist/components/form/engine/variants/VariantMinimal.js.map +1 -0
  68. package/dist/components/form/engine/variants/focusDemo.d.ts +13 -0
  69. package/dist/components/form/engine/variants/focusDemo.d.ts.map +1 -0
  70. package/dist/components/form/engine/variants/focusDemo.js +139 -0
  71. package/dist/components/form/engine/variants/focusDemo.js.map +1 -0
  72. package/dist/components/form/engine/variants/variantModel.d.ts +70 -0
  73. package/dist/components/form/engine/variants/variantModel.d.ts.map +1 -0
  74. package/dist/components/form/engine/variants/variantModel.js +133 -0
  75. package/dist/components/form/engine/variants/variantModel.js.map +1 -0
  76. package/dist/components/form/engine/variants/variantParts.d.ts +79 -0
  77. package/dist/components/form/engine/variants/variantParts.d.ts.map +1 -0
  78. package/dist/components/form/engine/variants/variantParts.js +191 -0
  79. package/dist/components/form/engine/variants/variantParts.js.map +1 -0
  80. package/dist/components/form/expressions/builder/index.d.ts.map +1 -1
  81. package/dist/components/form/expressions/builder/index.js +13 -2
  82. package/dist/components/form/expressions/builder/index.js.map +1 -1
  83. package/dist/components/form/expressions/useExpressions.d.ts.map +1 -1
  84. package/dist/components/form/expressions/useExpressions.js +4 -1
  85. package/dist/components/form/expressions/useExpressions.js.map +1 -1
  86. package/dist/components/form/fields/Field.d.ts.map +1 -1
  87. package/dist/components/form/fields/Field.js +5 -3
  88. package/dist/components/form/fields/Field.js.map +1 -1
  89. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts +2 -1
  90. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
  91. package/dist/components/form/fields/allowed-values/AllowedValues.js +8 -26
  92. package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
  93. package/dist/components/form/fields/auto/AutoFormField.d.ts +3 -0
  94. package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
  95. package/dist/components/form/fields/auto/AutoFormField.js +42 -8
  96. package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
  97. package/dist/components/form/fields/binary/Binary.d.ts +15 -0
  98. package/dist/components/form/fields/binary/Binary.d.ts.map +1 -0
  99. package/dist/components/form/fields/binary/Binary.js +74 -0
  100. package/dist/components/form/fields/binary/Binary.js.map +1 -0
  101. package/dist/components/form/fields/boolean/Boolean.js +1 -1
  102. package/dist/components/form/fields/boolean/Boolean.js.map +1 -1
  103. package/dist/components/form/fields/multi-select/MultiSelectFormField.d.ts.map +1 -1
  104. package/dist/components/form/fields/multi-select/MultiSelectFormField.js +5 -4
  105. package/dist/components/form/fields/multi-select/MultiSelectFormField.js.map +1 -1
  106. package/dist/components/form/fields/select/Select.d.ts.map +1 -1
  107. package/dist/components/form/fields/select/Select.js +29 -12
  108. package/dist/components/form/fields/select/Select.js.map +1 -1
  109. package/dist/components/form/fields/select/SelectCollection.d.ts +8 -2
  110. package/dist/components/form/fields/select/SelectCollection.d.ts.map +1 -1
  111. package/dist/components/form/fields/select/SelectCollection.js +52 -16
  112. package/dist/components/form/fields/select/SelectCollection.js.map +1 -1
  113. package/dist/components/form/index.d.ts +2 -0
  114. package/dist/components/form/index.d.ts.map +1 -1
  115. package/dist/components/form/index.js +2 -0
  116. package/dist/components/form/index.js.map +1 -1
  117. package/dist/components/imageLightbox/ImageLightbox.d.ts +21 -0
  118. package/dist/components/imageLightbox/ImageLightbox.d.ts.map +1 -0
  119. package/dist/components/imageLightbox/ImageLightbox.js +169 -0
  120. package/dist/components/imageLightbox/ImageLightbox.js.map +1 -0
  121. package/dist/components/imageLightbox/index.d.ts +2 -0
  122. package/dist/components/imageLightbox/index.d.ts.map +1 -0
  123. package/dist/components/imageLightbox/index.js +18 -0
  124. package/dist/components/imageLightbox/index.js.map +1 -0
  125. package/dist/components/searchFilterBar/SearchFilterBar.d.ts +33 -0
  126. package/dist/components/searchFilterBar/SearchFilterBar.d.ts.map +1 -0
  127. package/dist/components/searchFilterBar/SearchFilterBar.js +76 -0
  128. package/dist/components/searchFilterBar/SearchFilterBar.js.map +1 -0
  129. package/dist/components/searchFilterBar/index.d.ts +2 -0
  130. package/dist/components/searchFilterBar/index.d.ts.map +1 -0
  131. package/dist/components/searchFilterBar/index.js +18 -0
  132. package/dist/components/searchFilterBar/index.js.map +1 -0
  133. package/dist/components/supportTicket/AttachmentChips.d.ts +10 -0
  134. package/dist/components/supportTicket/AttachmentChips.d.ts.map +1 -0
  135. package/dist/components/supportTicket/AttachmentChips.js +122 -0
  136. package/dist/components/supportTicket/AttachmentChips.js.map +1 -0
  137. package/dist/components/supportTicket/InterfaceReferenceTags.d.ts +43 -0
  138. package/dist/components/supportTicket/InterfaceReferenceTags.d.ts.map +1 -0
  139. package/dist/components/supportTicket/InterfaceReferenceTags.js +31 -0
  140. package/dist/components/supportTicket/InterfaceReferenceTags.js.map +1 -0
  141. package/dist/components/supportTicket/ReferencePicker.d.ts +87 -0
  142. package/dist/components/supportTicket/ReferencePicker.d.ts.map +1 -0
  143. package/dist/components/supportTicket/ReferencePicker.js +295 -0
  144. package/dist/components/supportTicket/ReferencePicker.js.map +1 -0
  145. package/dist/components/supportTicket/TicketHeader.d.ts +86 -0
  146. package/dist/components/supportTicket/TicketHeader.d.ts.map +1 -0
  147. package/dist/components/supportTicket/TicketHeader.js +149 -0
  148. package/dist/components/supportTicket/TicketHeader.js.map +1 -0
  149. package/dist/components/supportTicket/TicketMetaTags.d.ts +32 -0
  150. package/dist/components/supportTicket/TicketMetaTags.d.ts.map +1 -0
  151. package/dist/components/supportTicket/TicketMetaTags.js +21 -0
  152. package/dist/components/supportTicket/TicketMetaTags.js.map +1 -0
  153. package/dist/components/supportTicket/TicketReplyBox.d.ts +63 -0
  154. package/dist/components/supportTicket/TicketReplyBox.d.ts.map +1 -0
  155. package/dist/components/supportTicket/TicketReplyBox.js +115 -0
  156. package/dist/components/supportTicket/TicketReplyBox.js.map +1 -0
  157. package/dist/components/supportTicket/attachmentAccess.d.ts +37 -0
  158. package/dist/components/supportTicket/attachmentAccess.d.ts.map +1 -0
  159. package/dist/components/supportTicket/attachmentAccess.js +132 -0
  160. package/dist/components/supportTicket/attachmentAccess.js.map +1 -0
  161. package/dist/components/supportTicket/fileToAttachment.d.ts +9 -0
  162. package/dist/components/supportTicket/fileToAttachment.d.ts.map +1 -0
  163. package/dist/components/supportTicket/fileToAttachment.js +28 -0
  164. package/dist/components/supportTicket/fileToAttachment.js.map +1 -0
  165. package/dist/components/supportTicket/index.d.ts +11 -0
  166. package/dist/components/supportTicket/index.d.ts.map +1 -0
  167. package/dist/components/supportTicket/index.js +27 -0
  168. package/dist/components/supportTicket/index.js.map +1 -0
  169. package/dist/components/supportTicket/meta.d.ts +71 -0
  170. package/dist/components/supportTicket/meta.d.ts.map +1 -0
  171. package/dist/components/supportTicket/meta.js +115 -0
  172. package/dist/components/supportTicket/meta.js.map +1 -0
  173. package/dist/components/supportTicket/ticketModel.d.ts +102 -0
  174. package/dist/components/supportTicket/ticketModel.d.ts.map +1 -0
  175. package/dist/components/supportTicket/ticketModel.js +3 -0
  176. package/dist/components/supportTicket/ticketModel.js.map +1 -0
  177. package/dist/components/ticketReferences/TicketReferences.d.ts +52 -0
  178. package/dist/components/ticketReferences/TicketReferences.d.ts.map +1 -0
  179. package/dist/components/ticketReferences/TicketReferences.js +492 -0
  180. package/dist/components/ticketReferences/TicketReferences.js.map +1 -0
  181. package/dist/components/ticketReferences/index.d.ts +3 -0
  182. package/dist/components/ticketReferences/index.d.ts.map +1 -0
  183. package/dist/components/ticketReferences/index.js +6 -0
  184. package/dist/components/ticketReferences/index.js.map +1 -0
  185. package/dist/components/ticketThread/TicketThread.d.ts +57 -0
  186. package/dist/components/ticketThread/TicketThread.d.ts.map +1 -0
  187. package/dist/components/ticketThread/TicketThread.js +299 -0
  188. package/dist/components/ticketThread/TicketThread.js.map +1 -0
  189. package/dist/components/ticketThread/index.d.ts +3 -0
  190. package/dist/components/ticketThread/index.d.ts.map +1 -0
  191. package/dist/components/ticketThread/index.js +7 -0
  192. package/dist/components/ticketThread/index.js.map +1 -0
  193. package/dist/helpers/common.d.ts +5 -0
  194. package/dist/helpers/common.d.ts.map +1 -1
  195. package/dist/helpers/common.js +20 -1
  196. package/dist/helpers/common.js.map +1 -1
  197. package/dist/helpers/scrollbar.d.ts +2 -0
  198. package/dist/helpers/scrollbar.d.ts.map +1 -0
  199. package/dist/helpers/scrollbar.js +25 -0
  200. package/dist/helpers/scrollbar.js.map +1 -0
  201. package/dist/index.d.ts +8 -1
  202. package/dist/index.d.ts.map +1 -1
  203. package/dist/index.js +10 -1
  204. package/dist/index.js.map +1 -1
  205. package/dist/providers/StorageProvider.d.ts +13 -0
  206. package/dist/providers/StorageProvider.d.ts.map +1 -1
  207. package/dist/providers/StorageProvider.js +29 -5
  208. package/dist/providers/StorageProvider.js.map +1 -1
  209. package/package.json +6 -5
  210. package/src/components/FocusedEditing/index.tsx +17 -2
  211. package/src/components/composer/Composer.stories.tsx +238 -0
  212. package/src/components/composer/Composer.tsx +545 -0
  213. package/src/components/composer/helpers.ts +74 -0
  214. package/src/components/composer/index.ts +2 -0
  215. package/src/components/dpqlEditor/DpqlEditor.stories.tsx +74 -2
  216. package/src/components/form/engine/CompactRow.tsx +561 -283
  217. package/src/components/form/engine/CompactToolbar.tsx +216 -182
  218. package/src/components/form/engine/FormEngine.stories.tsx +1736 -162
  219. package/src/components/form/engine/FormEngine.tsx +886 -170
  220. package/src/components/form/engine/FormEngineRemote.stories.tsx +377 -0
  221. package/src/components/form/engine/_structuredData/StructuredDataView.stories.tsx +8 -0
  222. package/src/components/form/engine/compactRowContext.ts +14 -0
  223. package/src/components/form/engine/compactRowStyles.ts +273 -146
  224. package/src/components/form/engine/compactToolbarContext.ts +1 -0
  225. package/src/components/form/engine/optionActions.ts +40 -0
  226. package/src/components/form/engine/readFirst.ts +169 -10
  227. package/src/components/form/engine/rendererTypes.ts +55 -0
  228. package/src/components/form/engine/variants/FormEngineVariants.stories.tsx +159 -0
  229. package/src/components/form/engine/variants/VariantCalmTable.tsx +242 -0
  230. package/src/components/form/engine/variants/VariantCards.tsx +212 -0
  231. package/src/components/form/engine/variants/VariantFocus.tsx +382 -0
  232. package/src/components/form/engine/variants/VariantMinimal.tsx +170 -0
  233. package/src/components/form/engine/variants/focusDemo.ts +145 -0
  234. package/src/components/form/engine/variants/variantModel.ts +216 -0
  235. package/src/components/form/engine/variants/variantParts.tsx +313 -0
  236. package/src/components/form/expressions/ExpressionField.stories.tsx +84 -2
  237. package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +213 -19
  238. package/src/components/form/expressions/builder/index.tsx +12 -1
  239. package/src/components/form/expressions/useExpressions.ts +4 -1
  240. package/src/components/form/fields/Field.stories.tsx +40 -0
  241. package/src/components/form/fields/Field.tsx +10 -1
  242. package/src/components/form/fields/allowed-values/AllowedValues.tsx +13 -36
  243. package/src/components/form/fields/array/ArrayAutoField.stories.tsx +64 -0
  244. package/src/components/form/fields/auto/AutoFormField.stories.tsx +146 -2
  245. package/src/components/form/fields/auto/AutoFormField.tsx +42 -1
  246. package/src/components/form/fields/binary/Binary.stories.tsx +122 -0
  247. package/src/components/form/fields/binary/Binary.tsx +81 -0
  248. package/src/components/form/fields/boolean/Boolean.stories.tsx +58 -0
  249. package/src/components/form/fields/boolean/Boolean.tsx +1 -1
  250. package/src/components/form/fields/byte-size/ByteSize.stories.tsx +24 -0
  251. package/src/components/form/fields/color/Color.stories.tsx +30 -0
  252. package/src/components/form/fields/cron/Cron.stories.tsx +8 -0
  253. package/src/components/form/fields/date/Date.stories.tsx +22 -0
  254. package/src/components/form/fields/file/File.stories.tsx +48 -0
  255. package/src/components/form/fields/long-string/LongString.stories.tsx +24 -0
  256. package/src/components/form/fields/markdown/Markdown.stories.tsx +8 -0
  257. package/src/components/form/fields/multi-select/MultiSelectFormField.tsx +14 -10
  258. package/src/components/form/fields/number/Number.stories.tsx +31 -0
  259. package/src/components/form/fields/object/Object.stories.tsx +88 -0
  260. package/src/components/form/fields/radio-group/RadioGroup.stories.tsx +24 -0
  261. package/src/components/form/fields/rich-text/RichText.stories.tsx +23 -0
  262. package/src/components/form/fields/schema-definition/SchemaDefinitionField.stories.tsx +72 -0
  263. package/src/components/form/fields/select/Select.stories.tsx +108 -0
  264. package/src/components/form/fields/select/Select.tsx +38 -12
  265. package/src/components/form/fields/select/SelectCollection.tsx +78 -17
  266. package/src/components/form/fields/string/String.stories.tsx +16 -0
  267. package/src/components/form/fields/template/TemplateField.stories.tsx +160 -0
  268. package/src/components/form/fields/url/Url.stories.tsx +24 -0
  269. package/src/components/form/index.tsx +2 -0
  270. package/src/components/imageLightbox/ImageLightbox.stories.tsx +238 -0
  271. package/src/components/imageLightbox/ImageLightbox.tsx +236 -0
  272. package/src/components/imageLightbox/index.ts +1 -0
  273. package/src/components/log/Log.stories.tsx +96 -0
  274. package/src/components/menu/Menu.stories.tsx +54 -0
  275. package/src/components/qonsoleSmartInput/QonsoleSmartInput.stories.tsx +83 -37
  276. package/src/components/searchFilterBar/SearchFilterBar.tsx +131 -0
  277. package/src/components/searchFilterBar/index.ts +1 -0
  278. package/src/components/smartEditor/SmartEditor.stories.tsx +32 -0
  279. package/src/components/supportTicket/AttachmentChips.stories.tsx +171 -0
  280. package/src/components/supportTicket/AttachmentChips.tsx +147 -0
  281. package/src/components/supportTicket/InterfaceReferenceTags.stories.tsx +171 -0
  282. package/src/components/supportTicket/InterfaceReferenceTags.tsx +96 -0
  283. package/src/components/supportTicket/ReferencePicker.stories.tsx +519 -0
  284. package/src/components/supportTicket/ReferencePicker.tsx +563 -0
  285. package/src/components/supportTicket/TicketConversation.stories.tsx +121 -0
  286. package/src/components/supportTicket/TicketHeader.stories.tsx +183 -0
  287. package/src/components/supportTicket/TicketHeader.tsx +247 -0
  288. package/src/components/supportTicket/TicketMetaTags.stories.tsx +103 -0
  289. package/src/components/supportTicket/TicketMetaTags.tsx +85 -0
  290. package/src/components/supportTicket/TicketReplyBox.stories.tsx +351 -0
  291. package/src/components/supportTicket/TicketReplyBox.tsx +146 -0
  292. package/src/components/supportTicket/attachmentAccess.ts +97 -0
  293. package/src/components/supportTicket/fileToAttachment.ts +24 -0
  294. package/src/components/supportTicket/index.ts +10 -0
  295. package/src/components/supportTicket/meta.ts +185 -0
  296. package/src/components/supportTicket/ticketModel.ts +131 -0
  297. package/src/components/ticketReferences/TicketReferences.stories.tsx +315 -0
  298. package/src/components/ticketReferences/TicketReferences.tsx +886 -0
  299. package/src/components/ticketReferences/index.ts +2 -0
  300. package/src/components/ticketThread/TicketThread.stories.tsx +828 -0
  301. package/src/components/ticketThread/TicketThread.tsx +704 -0
  302. package/src/components/ticketThread/index.ts +6 -0
  303. package/src/helpers/common.ts +19 -0
  304. package/src/helpers/scrollbar.ts +32 -0
  305. package/src/hooks/useFetch/useFetch.stories.tsx +30 -0
  306. package/src/hooks/useStorage/useStorage.stories.tsx +82 -0
  307. package/src/hooks/useWebSocket/useWebsocket.stories.tsx +127 -1
  308. package/src/index.tsx +8 -1
  309. package/src/providers/StorageProvider.tsx +30 -4
  310. package/src/stores/currentUser/currentUser.stories.tsx +49 -0
@@ -16,7 +16,8 @@ import { ExpressionBuilder } from './index';
16
16
  // --- inlined test helpers (equivalents of the IDE `../Tests/utils`) ---------
17
17
 
18
18
  /** Count regular expression cards (`.expression`). */
19
- const expressionCount = () => document.querySelectorAll('.expression').length;
19
+ const expressionCount = (scope: ParentNode = document) =>
20
+ scope.querySelectorAll('.expression').length;
20
21
 
21
22
  /** Click a ReqoreButton by visible label (anywhere in the document). */
22
23
  const clickButtonByLabel = async (label: string) => {
@@ -26,14 +27,14 @@ const clickButtonByLabel = async (label: string) => {
26
27
  };
27
28
 
28
29
  /** Click a button by CSS selector. */
29
- const clickSelector = async (selector: string, nth = 0) => {
30
- const els = document.querySelectorAll(selector);
30
+ const clickSelector = async (selector: string, nth = 0, scope: ParentNode = document) => {
31
+ const els = scope.querySelectorAll(selector);
31
32
  await fireEvent.click(els[nth]);
32
33
  };
33
34
 
34
35
  /** Wait for some text to appear in the document. */
35
- const waitForText = async (text: string | RegExp) => {
36
- const body = within(document.body);
36
+ const waitForText = async (text: string | RegExp, scope: HTMLElement = document.body) => {
37
+ const body = within(scope);
37
38
  await waitFor(() => expect(body.queryAllByText(text)[0]).toBeTruthy(), { timeout: 10000 });
38
39
  };
39
40
 
@@ -44,15 +45,19 @@ const waitForText = async (text: string | RegExp) => {
44
45
  * toolkit `Select` opens a `SelectFieldCollection` modal (not an inline
45
46
  * dropdown) — the item is a collection button with the display name as text.
46
47
  */
47
- const selectOperation = async (currentLabel: string, itemLabel: string) => {
48
- const body = within(document.body);
48
+ const selectOperation = async (
49
+ currentLabel: string,
50
+ itemLabel: string,
51
+ ownerDocument: Document = document
52
+ ) => {
53
+ const body = within(ownerDocument.body);
49
54
  // Open the picker (placeholder when empty, or the current operation name).
50
55
  const trigger = await body.findByText(currentLabel, undefined, { timeout: 10000 });
51
56
  await fireEvent.click(trigger);
52
57
  // Click the item inside the now-open collection modal.
53
58
  const item = await waitFor(
54
59
  () => {
55
- const el = within(document.body).queryAllByText(itemLabel)[0];
60
+ const el = within(ownerDocument.body).queryAllByText(itemLabel)[0];
56
61
  if (!el) throw new Error(`collection item "${itemLabel}" not ready`);
57
62
  return el;
58
63
  },
@@ -113,8 +118,16 @@ export const Default: Story = {
113
118
  args: {
114
119
  returnType: ['string', 'int'],
115
120
  },
116
- play: async () => {
117
- await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
121
+ parameters: {
122
+ docs: {
123
+ description: {
124
+ story:
125
+ 'Renders the ExpressionBuilder with no value and a string-or-int return type — a single empty expression card is shown so the operator can pick an operation.',
126
+ },
127
+ },
128
+ },
129
+ play: async ({ canvasElement }) => {
130
+ await waitFor(() => expect(expressionCount(canvasElement)).toBe(1), { timeout: 10000 });
118
131
  },
119
132
  };
120
133
 
@@ -122,6 +135,14 @@ export const DefaultBoolean: Story = {
122
135
  args: {
123
136
  returnType: ['boolean'],
124
137
  },
138
+ parameters: {
139
+ docs: {
140
+ description: {
141
+ story:
142
+ 'Renders the ExpressionBuilder with no value and a boolean return type — a single empty expression card is shown so the operator can pick a boolean-returning operation.',
143
+ },
144
+ },
145
+ },
125
146
  play: async () => {
126
147
  await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
127
148
  },
@@ -142,6 +163,14 @@ export const WithSimpleValue: Story = {
142
163
  },
143
164
  },
144
165
  },
166
+ parameters: {
167
+ docs: {
168
+ description: {
169
+ story:
170
+ 'Renders the ExpressionBuilder holding a single "contains" expression with three arguments — the card shows the operation and each operand slot.',
171
+ },
172
+ },
173
+ },
145
174
  play: async () => {
146
175
  await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
147
176
  },
@@ -234,6 +263,14 @@ export const WithComplexValue: Story = {
234
263
  },
235
264
  },
236
265
  },
266
+ parameters: {
267
+ docs: {
268
+ description: {
269
+ story:
270
+ 'Renders the ExpressionBuilder holding a nested &&/|| expression with six leaf expressions — the builder shows the full expression tree with the AND/OR group cards and their operand cards.',
271
+ },
272
+ },
273
+ },
237
274
  play: async () => {
238
275
  await waitFor(() => expect(expressionCount()).toBe(6), { timeout: 10000 });
239
276
  },
@@ -241,6 +278,15 @@ export const WithComplexValue: Story = {
241
278
 
242
279
  export const ShowsExplanation: Story = {
243
280
  ...WithComplexValue,
281
+ parameters: {
282
+ ...WithComplexValue.parameters,
283
+ docs: {
284
+ description: {
285
+ story:
286
+ 'Renders the nested expression tree and clicks Explain — the plain-language explanation of the whole expression is shown alongside the builder.',
287
+ },
288
+ },
289
+ },
244
290
  play: async (args) => {
245
291
  await WithComplexValue.play!(args);
246
292
  await clickButtonByLabel('Explain');
@@ -260,6 +306,15 @@ export const Readonly: Story = {
260
306
  ...WithComplexValue.args,
261
307
  readOnly: true,
262
308
  },
309
+ parameters: {
310
+ ...WithComplexValue.parameters,
311
+ docs: {
312
+ description: {
313
+ story:
314
+ 'Renders the nested expression tree with readOnly enabled — the tree is visible but the AND/OR add-group controls are hidden so the operator cannot mutate it.',
315
+ },
316
+ },
317
+ },
263
318
  play: async (args) => {
264
319
  await WithComplexValue.play!(args);
265
320
  expect(document.querySelector('.expression-and')).toBeNull();
@@ -268,6 +323,15 @@ export const Readonly: Story = {
268
323
 
269
324
  export const FocusedEditing: Story = {
270
325
  ...WithComplexValue,
326
+ parameters: {
327
+ ...WithComplexValue.parameters,
328
+ docs: {
329
+ description: {
330
+ story:
331
+ 'Renders the nested expression tree, hovers a card and clicks its fullscreen action — the focused-editing modal opens over that subtree.',
332
+ },
333
+ },
334
+ },
271
335
  play: async (args) => {
272
336
  await WithComplexValue.play!(args);
273
337
  await userEvent.hover(document.querySelectorAll('.expression')[0]);
@@ -288,6 +352,14 @@ export const WithArgWithAllowedValues: Story = {
288
352
  args: {
289
353
  returnType: ['bool'],
290
354
  },
355
+ parameters: {
356
+ docs: {
357
+ description: {
358
+ story:
359
+ 'Renders an empty ExpressionBuilder and selects "Matches Regular Expression" — the third operand ("Regex Options") carries element_allowed_values and renders the "Select one or more" picker.',
360
+ },
361
+ },
362
+ },
291
363
  play: async (args) => {
292
364
  await Default.play!(args);
293
365
 
@@ -311,6 +383,14 @@ export const WithIntType: Story = {
311
383
  },
312
384
  },
313
385
  },
386
+ parameters: {
387
+ docs: {
388
+ description: {
389
+ story:
390
+ 'Renders the ExpressionBuilder with an int-typed >= expression comparing $local:input to 20 — the operands render as Number fields inside the expression card.',
391
+ },
392
+ },
393
+ },
314
394
  play: async () => {
315
395
  await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
316
396
  },
@@ -326,6 +406,15 @@ export const WithIntType: Story = {
326
406
  */
327
407
  export const ArgsChangeWhenOperatorChanges: Story = {
328
408
  ...WithSimpleValue,
409
+ parameters: {
410
+ ...WithSimpleValue.parameters,
411
+ docs: {
412
+ description: {
413
+ story:
414
+ 'Renders the seeded "String Contains" expression, then switches the operation to "Matches Regular Expression" — the string operands carry over and the new "Regex Options" allowed-values operand appears.',
415
+ },
416
+ },
417
+ },
329
418
  play: async () => {
330
419
  // Both string operands of the seeded `contains` render as textareas.
331
420
  await waitFor(
@@ -344,6 +433,14 @@ export const NewGroupsCanBeCreated: Story = {
344
433
  ...WithSimpleValue.args,
345
434
  returnType: ['bool'],
346
435
  },
436
+ parameters: {
437
+ docs: {
438
+ description: {
439
+ story:
440
+ 'Renders the seeded "String Contains" expression, then clicks the AND and OR add-group actions — the tree grows from 1 to 3 expression cards as new grouping levels are added.',
441
+ },
442
+ },
443
+ },
347
444
  play: async () => {
348
445
  await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
349
446
 
@@ -357,6 +454,15 @@ export const NewGroupsCanBeCreated: Story = {
357
454
 
358
455
  export const GroupsCanBeDeleted: Story = {
359
456
  ...WithComplexValue,
457
+ parameters: {
458
+ ...WithComplexValue.parameters,
459
+ docs: {
460
+ description: {
461
+ story:
462
+ 'Renders the nested expression tree (6 cards) and removes one group — the tree shrinks to 5 cards after the delete.',
463
+ },
464
+ },
465
+ },
360
466
  play: async () => {
361
467
  await waitFor(() => expect(expressionCount()).toBe(6), { timeout: 10000 });
362
468
 
@@ -377,6 +483,14 @@ export const GroupsCanBeDeleted: Story = {
377
483
  * inline `AiAssistanceAction({ context: selectedExpression })` captured.
378
484
  */
379
485
  export const WithInjectedExtraActions: Story = {
486
+ parameters: {
487
+ docs: {
488
+ description: {
489
+ story:
490
+ 'Renders the nested expression tree with an extraActions factory that injects an AI-assist button per card. Hovering an expression reveals the injected action alongside the built-in ones.',
491
+ },
492
+ },
493
+ },
380
494
  args: {
381
495
  ...WithComplexValue.args,
382
496
  extraActions: ({ selectedExpression }) => [
@@ -428,6 +542,14 @@ export const ExpressionWithIntReturnType: Story = {
428
542
  is_expression: true,
429
543
  },
430
544
  },
545
+ parameters: {
546
+ docs: {
547
+ description: {
548
+ story:
549
+ 'Renders the ExpressionBuilder with a "+" (Addition) varargs expression holding four int operands — the three "rest" args each expose a remove-argument button.',
550
+ },
551
+ },
552
+ },
431
553
  play: async () => {
432
554
  await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
433
555
  // Three "rest" args → three remove-argument buttons.
@@ -438,6 +560,15 @@ export const ExpressionWithIntReturnType: Story = {
438
560
  /** Remove one variable argument — the remove-arg count drops from 3 to 2. */
439
561
  export const VariableArgumentsCanBeRemoved: Story = {
440
562
  ...ExpressionWithIntReturnType,
563
+ parameters: {
564
+ ...ExpressionWithIntReturnType.parameters,
565
+ docs: {
566
+ description: {
567
+ story:
568
+ 'Renders the "+" varargs expression and clicks one remove-argument button — one operand disappears and the remove-arg count drops from 3 to 2.',
569
+ },
570
+ },
571
+ },
441
572
  play: async (args) => {
442
573
  await ExpressionWithIntReturnType.play!(args);
443
574
 
@@ -450,6 +581,15 @@ export const VariableArgumentsCanBeRemoved: Story = {
450
581
  /** Remove one then add one back — the count returns to 3. */
451
582
  export const VariableArgumentsCanBeAdded: Story = {
452
583
  ...ExpressionWithIntReturnType,
584
+ parameters: {
585
+ ...ExpressionWithIntReturnType.parameters,
586
+ docs: {
587
+ description: {
588
+ story:
589
+ 'Renders the "+" varargs expression, removes one operand and then adds one back — the remove-arg count moves 3 → 2 → 3.',
590
+ },
591
+ },
592
+ },
453
593
  play: async (args) => {
454
594
  await ExpressionWithIntReturnType.play!(args);
455
595
 
@@ -487,34 +627,53 @@ export const ExpressionCanBeWrapped: Story = {
487
627
  returnType: ['string', 'int'],
488
628
  value: seededConvert,
489
629
  },
490
- play: async () => {
630
+ parameters: {
631
+ docs: {
632
+ description: {
633
+ story:
634
+ 'Renders a seeded "Convert to Boolean" expression, hovers the card and picks "Join List Elements" from the Wrap picker — the outer op mounts and the original expression becomes its first operand.',
635
+ },
636
+ },
637
+ },
638
+ play: async ({ canvasElement }) => {
491
639
  // Seeded base op + its operand render.
492
- await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
493
- await waitForText('Value To Convert');
640
+ await waitFor(() => expect(expressionCount(canvasElement)).toBe(1), { timeout: 10000 });
641
+ await waitForText('Value To Convert', canvasElement);
494
642
 
495
643
  // Hover the card to reveal the floating "Wrap" picker, then wrap it in
496
644
  // `Join List Elements` — the wrapped op becomes its first operand and the
497
645
  // outer card shows "List To Join". The card count goes 1 → 2.
498
- await userEvent.hover(document.querySelectorAll('.expression')[0]);
646
+ await userEvent.hover(canvasElement.querySelectorAll('.expression')[0]);
499
647
  await sleep(500);
500
- await selectOperation('Wrap', 'Join List Elements');
501
- await waitForText('List To Join');
502
- await waitFor(() => expect(expressionCount()).toBe(2), { timeout: 10000 });
648
+ await selectOperation('Wrap', 'Join List Elements', canvasElement.ownerDocument);
649
+ await waitForText('List To Join', canvasElement);
650
+ await waitFor(() => expect(expressionCount(canvasElement)).toBe(2), { timeout: 10000 });
503
651
  },
504
652
  };
505
653
 
506
654
  /** Wrap, then unwrap — back to a single expression card. */
507
655
  export const ExpressionCanBeUnwrapped: Story = {
508
656
  ...ExpressionCanBeWrapped,
657
+ parameters: {
658
+ ...ExpressionCanBeWrapped.parameters,
659
+ docs: {
660
+ description: {
661
+ story:
662
+ 'Renders the wrapped expression from ExpressionCanBeWrapped, then hovers and unwraps the outer op — the inner "Convert to Boolean" survives and the outer wrapper is removed.',
663
+ },
664
+ },
665
+ },
509
666
  play: async (args) => {
510
667
  await ExpressionCanBeWrapped.play!(args);
511
668
 
512
669
  // Unwrap the outer op (keep the child) — the `.expression-unwrap` action.
513
- await userEvent.hover(document.querySelectorAll('.expression')[0]);
670
+ await userEvent.hover(args.canvasElement.querySelectorAll('.expression')[0]);
514
671
  await sleep(500);
672
+ // The card's actions are ReQore *floating* actions, so they are portalled out
673
+ // of the canvas — this one lookup stays document-scoped on purpose.
515
674
  await clickSelector('.expression-unwrap');
516
675
 
517
- await waitFor(() => expect(expressionCount()).toBe(1), { timeout: 10000 });
676
+ await waitFor(() => expect(expressionCount(args.canvasElement)).toBe(1), { timeout: 10000 });
518
677
  },
519
678
  };
520
679
 
@@ -579,6 +738,14 @@ const SeededMismatchBase: Story = {
579
738
  * exact, so the builder flags it and the confirmation modal mounts.
580
739
  */
581
740
  export const FunctionArgsArePassedToNewFunctionAndNeedConfirmation: Story = {
741
+ parameters: {
742
+ docs: {
743
+ description: {
744
+ story:
745
+ 'Renders a valued "Format Date" expression and switches the operation to "Matches Regular Expression" — the carried date arg is accepted-but-not-exact for the new richtext operand and the mismatched-arguments confirmation modal mounts.',
746
+ },
747
+ },
748
+ },
582
749
  args: {
583
750
  returnType: 'string',
584
751
  value: {
@@ -616,6 +783,15 @@ export const FunctionArgsArePassedToNewFunctionAndNeedConfirmation: Story = {
616
783
  /** "Confirm selection" keeps the (still-selected) mismatched arg, transformed. */
617
784
  export const AcceptIncompatibleFunctionArgsSelection: Story = {
618
785
  ...SeededMismatchBase,
786
+ parameters: {
787
+ ...SeededMismatchBase.parameters,
788
+ docs: {
789
+ description: {
790
+ story:
791
+ 'Renders the seeded mismatch-flagged expression, then clicks "Confirm selection" on the mismatched-arguments modal — the (still-selected) argument is kept and transformed to the new expected type.',
792
+ },
793
+ },
794
+ },
619
795
  play: async (args) => {
620
796
  await SeededMismatchBase.play!(args);
621
797
 
@@ -636,6 +812,15 @@ export const AcceptIncompatibleFunctionArgsSelection: Story = {
636
812
  /** "Accept all" — every mismatched arg is transformed and kept. */
637
813
  export const AcceptAllIncompatibleFunctionArgs: Story = {
638
814
  ...SeededMismatchBase,
815
+ parameters: {
816
+ ...SeededMismatchBase.parameters,
817
+ docs: {
818
+ description: {
819
+ story:
820
+ 'Renders the seeded mismatch-flagged expression, then clicks "Accept all" on the mismatched-arguments modal — every flagged argument is transformed and kept.',
821
+ },
822
+ },
823
+ },
639
824
  play: async (args) => {
640
825
  await SeededMismatchBase.play!(args);
641
826
 
@@ -655,6 +840,15 @@ export const AcceptAllIncompatibleFunctionArgs: Story = {
655
840
  /** "Discard all" — every mismatched arg is cleared. */
656
841
  export const DiscardAllIncompatibleFunctionArgs: Story = {
657
842
  ...SeededMismatchBase,
843
+ parameters: {
844
+ ...SeededMismatchBase.parameters,
845
+ docs: {
846
+ description: {
847
+ story:
848
+ 'Renders the seeded mismatch-flagged expression, then clicks "Discard all" on the mismatched-arguments modal — every flagged argument is cleared.',
849
+ },
850
+ },
851
+ },
658
852
  play: async (args) => {
659
853
  await SeededMismatchBase.play!(args);
660
854
 
@@ -651,7 +651,10 @@ export const Expression = ({
651
651
  return value.value?.args?.some((arg) => arg?.types_mismatch);
652
652
  }, [JSON.stringify(value)]);
653
653
 
654
- if (expressions.loading || types.loading) {
654
+ // The type hook is seeded with the complete built-in catalogue and refreshes
655
+ // it in the background. Do not hide an otherwise usable expression behind
656
+ // a skeleton while that optional refresh is in flight.
657
+ if (expressions.loading || (types.loading && !size(types.value))) {
655
658
  return <ReqorePanelSkeleton size='small' />;
656
659
  }
657
660
 
@@ -687,6 +690,11 @@ export const Expression = ({
687
690
  fluid={false}
688
691
  fixed={true}
689
692
  flat
693
+ // The operation catalogue is long and every entry carries a description,
694
+ // so it belongs in the searchable collection modal rather than an inline
695
+ // dropdown. `SelectFormField` defaults `forceDropdown` to `true`, which
696
+ // would otherwise collapse this picker into the dropdown presentation.
697
+ forceDropdown={false}
690
698
  minimal
691
699
  items={defaultItems}
692
700
  onChange={handleOperatorChange}
@@ -732,6 +740,9 @@ export const Expression = ({
732
740
  transparent: false,
733
741
  fixed: true,
734
742
  minimal: false,
743
+ // Same catalogue as the operation selector above — keep the collection
744
+ // modal rather than the `forceDropdown` default's inline dropdown.
745
+ forceDropdown: false,
735
746
  items: defaultItems,
736
747
  hideItemCount: true,
737
748
  onChange: handleWrapExpressionClick,
@@ -84,7 +84,10 @@ export const useExpressions = (
84
84
 
85
85
  return {
86
86
  expressions,
87
- loading: system.loading || extra.loading,
87
+ // `extra` is deliberately not loaded without an expressions URL. The
88
+ // generic fetch hook keeps an unstarted request in its initial loading
89
+ // state, so only include it when that request is actually enabled.
90
+ loading: system.loading || (!!expressionsUrl && extra.loading),
88
91
  error: errorOverride ?? system.error ?? extra.error,
89
92
  reload: () => {
90
93
  system.load();
@@ -40,6 +40,14 @@ export const SoftInteger: Story = {
40
40
  type: 'softint',
41
41
  value: 5,
42
42
  },
43
+ parameters: {
44
+ docs: {
45
+ description: {
46
+ story:
47
+ 'Renders FormField for a softint value — the dispatcher resolves the soft type to int and mounts the numeric input.',
48
+ },
49
+ },
50
+ },
43
51
  async play({ canvasElement }) {
44
52
  // NumberFormField renders an input (a `softint` resolves to `int`).
45
53
  await expect(canvasElement.querySelector('input')).toBeInTheDocument();
@@ -52,6 +60,14 @@ export const Binary: Story = {
52
60
  type: 'binary',
53
61
  value: 'deadbeef',
54
62
  },
63
+ parameters: {
64
+ docs: {
65
+ description: {
66
+ story:
67
+ 'Renders FormField for a binary value — the dispatcher mounts a textarea holding the encoded content.',
68
+ },
69
+ },
70
+ },
55
71
  async play({ canvasElement }) {
56
72
  await expect(canvasElement.querySelector('textarea')).toBeInTheDocument();
57
73
  },
@@ -63,6 +79,14 @@ export const ByteSize: Story = {
63
79
  type: 'byte-size',
64
80
  value: '512MiB',
65
81
  },
82
+ parameters: {
83
+ docs: {
84
+ description: {
85
+ story:
86
+ 'Renders FormField for a byte-size value — the dispatcher mounts the amount input and the MiB unit selector, split from "512MiB".',
87
+ },
88
+ },
89
+ },
66
90
  async play({ canvasElement }) {
67
91
  const canvas = within(canvasElement);
68
92
  await expect(canvas.getByDisplayValue('512')).toBeInTheDocument();
@@ -76,6 +100,14 @@ export const Url: Story = {
76
100
  type: 'url',
77
101
  value: 'https://example.com',
78
102
  },
103
+ parameters: {
104
+ docs: {
105
+ description: {
106
+ story:
107
+ 'Renders FormField for a url value — the dispatcher mounts the https protocol selector and the example.com address input, split from "https://example.com".',
108
+ },
109
+ },
110
+ },
79
111
  async play({ canvasElement }) {
80
112
  const canvas = within(canvasElement);
81
113
  await expect(await canvas.findByDisplayValue('example.com')).toBeInTheDocument();
@@ -94,6 +126,14 @@ export const MultiSelect: Story = {
94
126
  ],
95
127
  value: ['red', 'blue'],
96
128
  },
129
+ parameters: {
130
+ docs: {
131
+ description: {
132
+ story:
133
+ 'Renders FormField for a multi-select value — the two picked values (Red and Blue) render as chips using their display_name labels.',
134
+ },
135
+ },
136
+ },
97
137
  async play({ canvasElement }) {
98
138
  const canvas = within(canvasElement);
99
139
  // The two selected values render as chips (by their display_name).
@@ -25,6 +25,7 @@ import NumberFormField from './number/Number';
25
25
  import { ReqraftObjectFormField } from './object/Object';
26
26
  import { RichTextFormField } from './rich-text/RichText';
27
27
  import { SelectFormField } from './select/Select';
28
+ import { getSelectItemShortDescription } from './select/SelectCollection';
28
29
  import { StringFormField } from './string/String';
29
30
  import { ArrayAutoField } from './array/ArrayAutoField';
30
31
  import { AutoFormField } from './auto/AutoFormField';
@@ -538,6 +539,10 @@ export const FormField = <T extends TFormFieldType>({
538
539
  icon='SaveFill'
539
540
  fluid
540
541
  hideItemCount
542
+ forceDropdown={
543
+ (fieldProps as { forceDropdown?: boolean } | undefined)?.forceDropdown ??
544
+ (rest as { forceDropdown?: boolean }).forceDropdown
545
+ }
541
546
  />
542
547
  );
543
548
  }
@@ -557,7 +562,7 @@ export const FormField = <T extends TFormFieldType>({
557
562
  margin='right'
558
563
  key={index}
559
564
  label={item.display_name ?? JSON.stringify(itemValue)}
560
- tooltip={item.short_desc || item.desc}
565
+ tooltip={getSelectItemShortDescription(mapAllowedValue(item))}
561
566
  disabled={item.disabled}
562
567
  checked={checked}
563
568
  intent={checked ? 'info' : undefined}
@@ -578,6 +583,10 @@ export const FormField = <T extends TFormFieldType>({
578
583
  value={value}
579
584
  onChange={(val) => handleChange(val as TFormFieldValueType<T>)}
580
585
  fluid
586
+ forceDropdown={
587
+ (fieldProps as { forceDropdown?: boolean } | undefined)?.forceDropdown ??
588
+ (rest as { forceDropdown?: boolean }).forceDropdown
589
+ }
581
590
  />
582
591
  );
583
592
  };