@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
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Shared rendering parts for the FormEngine compact VARIANTS playground.
3
+ * Value rendering is shared so every variant shows identical data; the `tone`
4
+ * prop lets a variant choose a calm (desaturated) or vivid chip treatment.
5
+ */
6
+ import {
7
+ ReqoreButton,
8
+ ReqoreCollapsibleContent,
9
+ ReqoreControlGroup,
10
+ ReqoreIcon,
11
+ ReqoreInput,
12
+ ReqoreTag,
13
+ } from '@qoretechnologies/reqore';
14
+ import { useReqoreTheme } from '@qoretechnologies/reqore/dist/hooks/useTheme';
15
+ import React from 'react';
16
+ import { AutoFormField } from '../../fields/auto/AutoFormField';
17
+ import { StructuredDataView } from '../_structuredData/StructuredDataView';
18
+ import {
19
+ buildVariantGroups,
20
+ summarize,
21
+ IVariantGroup,
22
+ IVariantRow,
23
+ IVariantValue,
24
+ TVariantStatus,
25
+ } from './variantModel';
26
+
27
+ export function useVariantColors() {
28
+ const theme = useReqoreTheme();
29
+ const intents = (theme.intents || {}) as Record<string, string>;
30
+ return {
31
+ main: theme.main as string,
32
+ text: (theme.text?.color as string) || '#e8e8e8',
33
+ muted: `${(theme.text?.color as string) || '#e8e8e8'}99`,
34
+ faint: `${(theme.text?.color as string) || '#e8e8e8'}55`,
35
+ line: `${(theme.text?.color as string) || '#ffffff'}14`,
36
+ hover: `${(theme.text?.color as string) || '#ffffff'}0c`,
37
+ surface: `${(theme.text?.color as string) || '#ffffff'}08`,
38
+ danger: intents.danger || '#a82a2a',
39
+ warning: intents.warning || '#d17c29',
40
+ success: intents.success || '#4a7110',
41
+ info: intents.info || '#3b7bbf',
42
+ custom1: intents.custom1 || '#762f7e',
43
+ };
44
+ }
45
+
46
+ export const STATUS_COLOR = (
47
+ status: TVariantStatus,
48
+ c: ReturnType<typeof useVariantColors>
49
+ ) =>
50
+ status === 'invalid' ? c.danger
51
+ : status === 'todo' ? c.warning
52
+ : status === 'set' ? c.success
53
+ : c.faint;
54
+
55
+ /** A single status mark — one dot, color = severity. Replaces stripe+box+icon. */
56
+ export const StatusDot = ({
57
+ status,
58
+ size = 7,
59
+ }: {
60
+ status: TVariantStatus;
61
+ size?: number;
62
+ }) => {
63
+ const c = useVariantColors();
64
+ if (status === 'unset') return null;
65
+ return (
66
+ <span
67
+ aria-hidden
68
+ style={{
69
+ width: size,
70
+ height: size,
71
+ borderRadius: '50%',
72
+ flex: '0 0 auto',
73
+ background: STATUS_COLOR(status, c),
74
+ boxShadow: status !== 'set' ? `0 0 0 3px ${STATUS_COLOR(status, c)}22` : undefined,
75
+ }}
76
+ />
77
+ );
78
+ };
79
+
80
+ /** The value summary. `tone='calm'` desaturates template/richtext chips. */
81
+ export const ValueView = ({
82
+ value,
83
+ tone = 'calm',
84
+ }: {
85
+ value: IVariantValue;
86
+ tone?: 'calm' | 'vivid';
87
+ }) => {
88
+ const c = useVariantColors();
89
+ const ellipsis: React.CSSProperties = {
90
+ overflow: 'hidden',
91
+ textOverflow: 'ellipsis',
92
+ whiteSpace: 'nowrap',
93
+ minWidth: 0,
94
+ };
95
+
96
+ switch (value.kind) {
97
+ case 'empty':
98
+ // A quiet dash reads as "no value" without shouting "Not set" on every row.
99
+ return <span style={{ color: c.faint }}>—</span>;
100
+
101
+ case 'color':
102
+ return (
103
+ <span style={{ display: 'inline-flex', alignItems: 'center', gap: 7, minWidth: 0 }}>
104
+ <span
105
+ aria-hidden
106
+ style={{
107
+ width: 12,
108
+ height: 12,
109
+ borderRadius: 3,
110
+ flex: '0 0 auto',
111
+ background: value.extra,
112
+ border: `1px solid ${c.line}`,
113
+ }}
114
+ />
115
+ <span style={ellipsis}>{value.display}</span>
116
+ </span>
117
+ );
118
+
119
+ case 'file':
120
+ return (
121
+ <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, minWidth: 0 }}>
122
+ <ReqoreIcon icon='FileLine' size='13px' style={{ color: c.muted, flexShrink: 0 }} />
123
+ <span style={ellipsis}>{value.display}</span>
124
+ {value.extra ?
125
+ <span style={{ color: c.faint, fontSize: 11, flexShrink: 0 }}>{value.extra}</span>
126
+ : null}
127
+ </span>
128
+ );
129
+
130
+ case 'bool':
131
+ return <span>{value.display}</span>;
132
+
133
+ case 'hash':
134
+ return (
135
+ <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, color: c.muted }}>
136
+ <ReqoreIcon icon='BracesLine' size='12px' style={{ color: c.faint }} />
137
+ <span>{value.display}</span>
138
+ </span>
139
+ );
140
+
141
+ case 'template':
142
+ return tone === 'vivid' ?
143
+ <ReqoreTag size='small' intent='info' icon='ExchangeDollarLine' label={value.display} />
144
+ : <span
145
+ style={{
146
+ display: 'inline-flex',
147
+ alignItems: 'center',
148
+ gap: 5,
149
+ padding: '1px 7px',
150
+ borderRadius: 4,
151
+ background: c.surface,
152
+ border: `1px solid ${c.line}`,
153
+ color: c.text,
154
+ fontSize: 12,
155
+ maxWidth: '100%',
156
+ ...ellipsis,
157
+ }}
158
+ >
159
+ <ReqoreIcon icon='ExchangeDollarLine' size='11px' style={{ color: c.custom1, flexShrink: 0 }} />
160
+ <span style={ellipsis}>{value.display}</span>
161
+ </span>;
162
+
163
+ case 'richtext':
164
+ return <span style={ellipsis}>{value.display}</span>;
165
+
166
+ default:
167
+ return <span style={ellipsis}>{value.display}</span>;
168
+ }
169
+ };
170
+
171
+ /** A reusable description disclosure used by every variant (tap-friendly).
172
+ * Unifies short_desc (inline) + long desc into ONE control. */
173
+ export const useDisclosure = () => {
174
+ const [open, setOpen] = React.useState<Record<string, boolean>>({});
175
+ return {
176
+ isOpen: (id: string) => !!open[id],
177
+ toggle: (id: string) => setOpen((p) => ({ ...p, [id]: !p[id] })),
178
+ };
179
+ };
180
+
181
+ // ---------------------------------------------------------------------------
182
+ // Shared form state: filter (all / needs-attention), add-field, inline editing.
183
+ // Each variant calls useVariantForm and renders <VariantToolbar> + <InlineEdit>.
184
+ // ---------------------------------------------------------------------------
185
+ export type TVariantFilter = 'all' | 'attention';
186
+
187
+ export function useVariantForm(options: any, values: any, config?: any) {
188
+ const [filter, setFilter] = React.useState<TVariantFilter>('all');
189
+ const [query, setQuery] = React.useState('');
190
+ const [showDescriptions, setShowDescriptions] = React.useState(false);
191
+ const [editing, setEditing] = React.useState<string | null>(null);
192
+
193
+ const { groups, requiredGroups } = React.useMemo(
194
+ () => buildVariantGroups(options, values, config),
195
+ [options, values, config]
196
+ );
197
+ const summary = React.useMemo(() => summarize(groups), [groups]);
198
+
199
+ // Filtered view: text query (label match) + 'attention' (todo/invalid only).
200
+ const visibleGroups: IVariantGroup[] = React.useMemo(() => {
201
+ const q = query.trim().toLowerCase();
202
+ return groups
203
+ .map((g) => ({
204
+ ...g,
205
+ rows: g.rows.filter(
206
+ (r) =>
207
+ (filter === 'all' || r.status === 'todo' || r.status === 'invalid') &&
208
+ (!q || r.label.toLowerCase().includes(q) || r.name.toLowerCase().includes(q))
209
+ ),
210
+ }))
211
+ .filter((g) => g.rows.length);
212
+ }, [groups, filter, query]);
213
+
214
+ return {
215
+ groups,
216
+ visibleGroups,
217
+ requiredGroups,
218
+ summary,
219
+ filter,
220
+ setFilter,
221
+ toggleAttention: () => setFilter((f) => (f === 'attention' ? 'all' : 'attention')),
222
+ query,
223
+ setQuery,
224
+ showDescriptions,
225
+ toggleDescriptions: () => setShowDescriptions((v) => !v),
226
+ editing,
227
+ startEdit: (name: string) => setEditing((cur) => (cur === name ? null : name)),
228
+ stopEdit: () => setEditing(null),
229
+ };
230
+ }
231
+
232
+ export type TVariantForm = ReturnType<typeof useVariantForm>;
233
+
234
+ /** Compact toolbar: just a prominent filter field. The "needs attention" control
235
+ * lives in each variant's header (the count line is the link); all optional
236
+ * fields render inline in the Optional group, so there's no "add field" step. */
237
+ export const VariantToolbar = ({ form }: { form: TVariantForm }) => {
238
+ const c = useVariantColors();
239
+ const { summary, query, setQuery, showDescriptions, toggleDescriptions } = form;
240
+ return (
241
+ <ReqoreControlGroup verticalAlign='center' fluid>
242
+ <ReqoreInput
243
+ placeholder='Filter fields…'
244
+ icon='Search2Line'
245
+ iconColor='muted'
246
+ pill
247
+ fluid
248
+ value={query}
249
+ onChange={(e: any) => setQuery(e.currentTarget.value)}
250
+ onClearClick={() => setQuery('')}
251
+ />
252
+ {/* Show short descriptions under every field — like the compact engine's
253
+ "Show all descriptions" toggle. Icon-only; info-intent when active. */}
254
+ <ReqoreButton
255
+ fixed
256
+ flat
257
+ minimal
258
+ intent={showDescriptions ? 'info' : undefined}
259
+ active={showDescriptions}
260
+ icon={showDescriptions ? 'InformationFill' : 'InformationLine'}
261
+ tooltip={showDescriptions ? 'Hide field descriptions' : 'Show field descriptions'}
262
+ onClick={toggleDescriptions}
263
+ />
264
+ <span style={{ color: c.faint, fontSize: 12, paddingLeft: 4, whiteSpace: 'nowrap' }}>
265
+ {summary.set}/{summary.total} set
266
+ </span>
267
+ </ReqoreControlGroup>
268
+ );
269
+ };
270
+
271
+ /** Complex value preview — the SAME nested tree + "Show more" fade the compact
272
+ * engine uses, so hash/list fields show their contents immediately. */
273
+ export const ComplexPreview = ({ value, onOpen }: { value: unknown; onOpen?: () => void }) => (
274
+ <ReqoreCollapsibleContent maxCollapsedHeight={120}>
275
+ <div onClick={(e) => e.stopPropagation()}>
276
+ <StructuredDataView
277
+ value={value}
278
+ collapsibleRoot={false}
279
+ defaultExpandDepth={2}
280
+ onItemClick={onOpen}
281
+ />
282
+ </div>
283
+ </ReqoreCollapsibleContent>
284
+ );
285
+
286
+ /** Inline editor: mounts the REAL field editor (AutoFormField) for the row's
287
+ * schema + value, so clicking a field edits it for real (string, number, bool,
288
+ * colour, file, richtext, list, date, …). Local state only — the prototype
289
+ * doesn't persist; in the engine this flows through handleValueChange. */
290
+ export const InlineEdit = ({ row, onDone }: { row: IVariantRow; onDone: () => void }) => {
291
+ const [value, setValue] = React.useState(row.field?.value);
292
+ return (
293
+ <div
294
+ style={{ gridColumn: '1 / -1', display: 'flex', flexFlow: 'column', gap: 8, padding: '10px 0 12px' }}
295
+ onClick={(e) => e.stopPropagation()}
296
+ >
297
+ <AutoFormField
298
+ {...(row.schema || {})}
299
+ name={row.name}
300
+ value={value}
301
+ default_value={row.schema?.default_value}
302
+ onChange={(_n: string, v: any) => setValue(v)}
303
+ fluid
304
+ size='small'
305
+ />
306
+ <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
307
+ <ReqoreButton size='small' intent='success' icon='CheckLine' fixed onClick={onDone}>
308
+ Done
309
+ </ReqoreButton>
310
+ </div>
311
+ </div>
312
+ );
313
+ };
@@ -23,6 +23,16 @@ const SAMPLE: IExpression = {
23
23
  const meta = {
24
24
  component: ExpressionField,
25
25
  title: 'Components/Form/Expressions/ExpressionField',
26
+ parameters: {
27
+ mockData: [
28
+ {
29
+ url: 'https://hq.qoretechnologies.com:8092/api/latest/system?action=expressions&context=ui',
30
+ method: 'GET',
31
+ status: 200,
32
+ response: mockExpressions,
33
+ },
34
+ ],
35
+ },
26
36
  args: {
27
37
  onChange: fn(),
28
38
  expressions: mockExpressions,
@@ -50,6 +60,14 @@ export const Default: Story = {
50
60
  args: {
51
61
  value: SAMPLE,
52
62
  },
63
+ parameters: {
64
+ docs: {
65
+ description: {
66
+ story:
67
+ 'Renders ExpressionField holding a "$local:name == John" expression — the Visual builder shows the Logical Equals operator with its two operands and the Visual/Text mode toggle.',
68
+ },
69
+ },
70
+ },
53
71
  async play({ canvasElement }) {
54
72
  const canvas = within(canvasElement);
55
73
 
@@ -73,6 +91,14 @@ export const Empty: Story = {
73
91
  value: { is_expression: true, value: { args: [] } },
74
92
  defaultMode: 'text',
75
93
  },
94
+ parameters: {
95
+ docs: {
96
+ description: {
97
+ story:
98
+ 'Renders ExpressionField in Text mode with an empty expression AST — the "Parsed" preview shows the "(empty)" placeholder for an empty expression.',
99
+ },
100
+ },
101
+ },
76
102
  async beforeEach() {
77
103
  const stop = startDpqlMockLsp();
78
104
  return () => stop();
@@ -102,6 +128,14 @@ export const Empty: Story = {
102
128
  * builder, and the Visual/Text toggle is present.
103
129
  */
104
130
  export const ViaFormEngine: Story = {
131
+ parameters: {
132
+ docs: {
133
+ description: {
134
+ story:
135
+ 'Renders a FormEngine schema with a bool option that carries supports_expressions and a stored expression value — the engine routes through TemplateField and mounts the ExpressionField shell with the Visual builder and the Visual/Text toggle.',
136
+ },
137
+ },
138
+ },
105
139
  render: () => {
106
140
  const [value, setValue] = useState<any>({
107
141
  condition: { type: 'bool', value: SAMPLE.value, is_expression: true },
@@ -150,6 +184,14 @@ export const ViaFormEngine: Story = {
150
184
  * renders the same AST.
151
185
  */
152
186
  export const ViaFormEngineTextMode: Story = {
187
+ parameters: {
188
+ docs: {
189
+ description: {
190
+ story:
191
+ 'Renders the FormEngine expression field, then switches to Text mode — the DPQL editor seeds from the stored AST via the mock LSP\'s dpql/serialize call and the "Parsed" preview mirrors it.',
192
+ },
193
+ },
194
+ },
153
195
  render: ViaFormEngine.render,
154
196
  async beforeEach() {
155
197
  const stop = startDpqlMockLsp();
@@ -200,6 +242,14 @@ export const ViaFormEngineTextMode: Story = {
200
242
  * the seeded direction is covered by `ViaFormEngineTextMode` above.)
201
243
  */
202
244
  export const ViaFormEngineTextTyping: Story = {
245
+ parameters: {
246
+ docs: {
247
+ description: {
248
+ story:
249
+ 'Renders the FormEngine expression field with an empty AST in Text mode. Typing DPQL text triggers the mock LSP\'s dpql/parse and the parsed expression lands in the form value with is_expression set.',
250
+ },
251
+ },
252
+ },
203
253
  render: (args) => {
204
254
  const [value, setValue] = useState<any>({
205
255
  condition: { type: 'bool', value: { args: [] }, is_expression: true },
@@ -277,6 +327,14 @@ export const TextMode: Story = {
277
327
  value: { is_expression: true, value: { args: [] } },
278
328
  defaultMode: 'text',
279
329
  },
330
+ parameters: {
331
+ docs: {
332
+ description: {
333
+ story:
334
+ 'Renders ExpressionField in Text (DPQL) mode over a mock-socket LSP. Typing DPQL text triggers dpql/parse and the "Parsed" preview reflects the resulting AST.',
335
+ },
336
+ },
337
+ },
280
338
  async beforeEach() {
281
339
  const stop = startDpqlMockLsp();
282
340
  return () => stop();
@@ -309,6 +367,14 @@ export const TextMode: Story = {
309
367
  * Driven live for the toggle interaction.
310
368
  */
311
369
  export const ToggleInFormEngine: Story = {
370
+ parameters: {
371
+ docs: {
372
+ description: {
373
+ story:
374
+ 'Renders a FormEngine schema with a plain bool option (supports_expressions, no value). Clicking More then "Use Expression" flips the field to expression mode and the ExpressionField shell with the Visual builder mounts in place of the checkbox.',
375
+ },
376
+ },
377
+ },
312
378
  render: () => {
313
379
  const [value, setValue] = useState<any>({});
314
380
  return (
@@ -380,7 +446,15 @@ export const Live: Story = {
380
446
  // (network/auth), still snapshotted by Chromatic. Mirrors the DpqlEditor
381
447
  // live stories.
382
448
  tags: ['!test'],
383
- parameters: { live: true },
449
+ parameters: {
450
+ live: true,
451
+ docs: {
452
+ description: {
453
+ story:
454
+ 'Renders ExpressionField against a live Qorus instance — the picker fetches the real ~121-function catalogue rather than the mock, and the seeded "contains" expression exercises the schema-driven operators and operands.',
455
+ },
456
+ },
457
+ },
384
458
  args: {
385
459
  type: 'bool',
386
460
  value: {
@@ -423,7 +497,15 @@ export const Live: Story = {
423
497
  */
424
498
  export const LiveExplain: Story = {
425
499
  tags: ['!test'],
426
- parameters: { live: true },
500
+ parameters: {
501
+ live: true,
502
+ docs: {
503
+ description: {
504
+ story:
505
+ 'Renders ExpressionField in Text mode against a live Qorus instance — the "Parsed" preview uses the server-rendered form via dpql/renderExpression rather than the client-side approximation.',
506
+ },
507
+ },
508
+ },
427
509
  args: {
428
510
  value: {
429
511
  is_expression: true,