@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
package/.claude/CLAUDE.md CHANGED
@@ -1,4 +1,36 @@
1
- # ReQraft AI Coding Agent Instructions
1
+ @~/Projects/instruction-files/CLAUDE.md
2
+ @~/Projects/instruction-files/stacks/frontend/FRONTEND.md
3
+
4
+ # ReQraft (toolkit-react) — Claude entry point
5
+
6
+ ## Shared Qore rules (READ FIRST)
7
+
8
+ The two `@`-imports above load the shared rules from the **instruction-files**
9
+ repo: the org-wide baseline (`CLAUDE.md`) and the frontend ruleset
10
+ (`stacks/frontend/FRONTEND.md`) — git safety, commit conventions, CI
11
+ monitoring, `/audit`, the Reqore-first rule, the Storybook + Qlip visual-change
12
+ flow, story descriptions, and more. Those files point on to
13
+ `stacks/frontend/BRAND_DESIGN.md` for brand / UI-design decisions (read it
14
+ before building any visual surface). **Everything below this section is
15
+ specific to ReQraft (toolkit-react).**
16
+
17
+ **If the imports above did not load** — you don't see the shared rules because
18
+ this repo is cloned somewhere other than `~/Projects/instruction-files` — find
19
+ the shared repo before doing any frontend work:
20
+
21
+ 1. Check for a gitignored **`.instruction-files-path`** file at this repo's
22
+ root. If it exists, read the path `P` from it, then read `P/CLAUDE.md` and
23
+ `P/stacks/frontend/FRONTEND.md` (+ `P/stacks/frontend/BRAND_DESIGN.md` for
24
+ UI work) and follow them.
25
+ 2. Otherwise locate the `instruction-files` repo on disk (try
26
+ `~/Projects/instruction-files`, then your other project roots). If found at
27
+ `P`, write `P` into `.instruction-files-path` (create it — it's gitignored)
28
+ so future sessions skip the search, then read the files above.
29
+ 3. If it isn't cloned anywhere, **STOP and ask the user to clone it**:
30
+ `git clone git@github.com:qoretechnologies/instruction-files.git ~/Projects/instruction-files`
31
+ Do not proceed with frontend work until the shared rules are loaded.
32
+
33
+ # ReQraft (toolkit-react) — project-specific rules
2
34
 
3
35
  ## Project Overview
4
36
 
@@ -12,22 +44,12 @@ ReQraft (`@qoretechnologies/reqraft`) is a **React hooks and components toolkit*
12
44
  - **Styling:** styled-components (inherited from ReQore); no CSS modules
13
45
  - **State Management:** zustand (stores) + React Context (`use-context-selector`)
14
46
  - **Data Fetching:** `@tanstack/react-query` v4 (via `query()` util + `useFetch` hook)
15
- - **Testing:** Jest + React Testing Library (tests in `__tests__/`)
47
+ - **Testing:** Vitest a `unit` project (jsdom, tests in `__tests__/`) + a `storybook` project (every story run in a real Chromium browser via Playwright); React Testing Library for component assertions
16
48
  - **Documentation:** Storybook (stories co-located in `src/` with `.stories.tsx` suffix)
17
49
  - **Storybook port:** `6008` (not 6007 — that's reqore)
18
50
 
19
51
  ## Architecture Essentials
20
52
 
21
- ### General Development Practices
22
-
23
- - Focus on user experience and performance first; complexity and tech debt are secondary
24
- - Follow existing code patterns; refer to similar hooks/components for guidance
25
- - Check if a helper or utility already exists before writing a new one
26
- - Use TypeScript with strict typing; prefix interfaces with `I` and types with `T`
27
- - Always use named exports for React components and hooks
28
- - Use functional components with React hooks; wrap in `memo()` unless there's a reason not to
29
- - Wrap callbacks in `useCallback()` and computed values in `useMemo()` unless there's a reason not to
30
-
31
53
  ### Provider Stack (`src/providers/`)
32
54
 
33
55
  The app must be wrapped in `ReqraftProvider` (or initialized via `initializeReqraft()`):
@@ -133,7 +155,9 @@ A generic `<Field>` component dispatches to the appropriate field by type.
133
155
  ```bash
134
156
  yarn install
135
157
  yarn storybook # Dev mode on http://localhost:6008
136
- yarn test:watch # Jest watch mode
158
+ yarn test # Vitest unit tests (jsdom)
159
+ yarn test:watch # Vitest unit watch mode
160
+ yarn test:stories # Story / interaction tests in a real browser (+ Qlip capture)
137
161
  yarn lint # ESLint check
138
162
  yarn build # TypeScript compilation (tsconfig.prod.json)
139
163
  yarn build:test # Type-check without emit
@@ -145,25 +169,32 @@ yarn build:test # Type-check without emit
145
169
  - `pre-push` hook enforces: `build:test:prod`, `lint`, `test`
146
170
  - Branch naming: always start with the issue number, e.g. `feature/49_pooled-connections`
147
171
 
172
+ ### Versioning — every PR to `develop` MUST bump the version
173
+
174
+ `.github/workflows/beta_release.yml` runs on **every push to `develop`** and publishes to NPM using whatever `version` is in `package.json` at push time. A merge without a bump therefore tries to re-publish an already-published version and **fails** (NPM refuses to re-publish). This applies to **every** PR — features, fixes, chores, and docs-only changes alike. There is no exception.
175
+
176
+ - Bump the **patch** for an ordinary PR while in beta (pre-1.0) — e.g. `0.10.9` → `0.10.10`. Do NOT bump minor/major for ordinary feature/fix PRs.
177
+ - Bump in `package.json` only (no git tag): `npm version patch --no-git-tag-version`, and include the bump in the PR's commit.
178
+ - If another PR bumps to the same version before yours merges, rebase and bump again — the version at merge time must be strictly greater than the last published one.
179
+
148
180
  ### Testing Patterns
149
181
 
150
- - Tests live in `__tests__/` (mirror `src/` structure)
151
- - Wrap tests with `ReqraftProvider` (or at minimum `QueryClientProvider`)
182
+ - Two Vitest projects (see `vitest.config.ts`): **unit** (jsdom; tests in `__tests__/`, mirroring `src/`) and **storybook** (every `*.stories.tsx` run in a real Chromium browser via Playwright). There is no Jest.
183
+ - Wrap unit tests with `ReqraftProvider` (or at minimum `QueryClientProvider`)
152
184
  - Use `mock-socket` for WebSocket testing
153
- - Run: `./node_modules/.bin/jest --passWithNoTests`
185
+ - Run: `yarn test` (unit) · `yarn test:stories [file-substring]` (stories) · `yarn precheck` (lint + unit + `build:test:prod`)
154
186
 
155
- ### Storybook Stories
187
+ ### Storybook Stories & visual testing
156
188
 
157
189
  - Stories are co-located alongside source: `src/hooks/useFetch/useFetch.stories.tsx`
158
190
  - Storybook port: **6008**
159
- - Visual testing via Chromatic (`yarn chromatic`)
191
+ - Story + interaction tests run on **Vitest browser mode** (Playwright/Chromium): `yarn test:stories [file-substring]`. Run `yarn install-playwright` once first.
192
+ - **Visual regression via Qlip** (not Chromatic): the story run captures snapshots through the `qlip` Vitest plugin. Upload is gated on `QLIP_UPLOAD_TOKEN` (`vitest.config.ts`), so **local runs capture but never upload** — PNGs land in `qlip/screenshots/<ts>/stories/auto/<StoryId>.png` (gitignored); read the PNG to verify a visual change. CI (`.github/workflows/tests.yml`) sets the token and uploads a build for dashboard review. The full visual-change flow + the `qlip` MCP review skill live in the imported `stacks/frontend/FRONTEND.md`.
160
193
 
161
194
  ## Code Patterns & Conventions
162
195
 
163
196
  ### Naming
164
197
 
165
- - Interfaces: `I` prefix (e.g., `IReqraftUseFetch`)
166
- - Types: `T` prefix (e.g., `TReqraftMenu`)
167
198
  - Enums: PascalCase (e.g., `ReqraftWebSocketStatus`)
168
199
  - Hooks: `useReqraft*` prefix
169
200
  - Providers: `Reqraft*Provider`
@@ -240,11 +271,9 @@ yarn build:test # Type-check without emit
240
271
  | `src/components/log/` | Log display component |
241
272
  | `src/components/menu/` | Navigation menu component |
242
273
  | `src/types/` | Shared TypeScript types |
243
- | `__tests__/` | Jest tests |
274
+ | `__tests__/` | Vitest unit tests (jsdom) |
244
275
 
245
276
  ## Other
246
277
 
247
- - You may need to source zsh to get some commands (like `gh`) working: `source ~/.zshrc`
248
- - Branch naming convention: `feature/<issue-number>_<short-description>` (e.g., `feature/49_pooled-connections`)
249
278
  - This library is a **peer-dependency consumer** of ReQore — do not copy ReQore internals here; import from `@qoretechnologies/reqore` instead
250
279
  - `yarn update-reqore` updates ReQore to the latest beta
@@ -0,0 +1,156 @@
1
+ # Compact FormEngine → "Focus" redesign — migration plan
2
+
3
+ **Goal:** make the real Compact FormEngine *look* like the `Focus` variant
4
+ prototype (`src/components/form/engine/variants/VariantFocus.tsx`) while keeping
5
+ **100% of its current functionality** and a **green story/test suite**.
6
+
7
+ **Principle (the user's, and the right one):** _bring our design to the engine,
8
+ not the engine's functionality to our design._ We re-skin the working engine. We
9
+ do **not** rebuild validation, dependent-reset, templates/`on_change`, operators,
10
+ `arg_schema` nesting, focused editing, or draft/commit into the prototype.
11
+
12
+ The engine is already visually sophisticated and already owns every hard piece:
13
+
14
+ | Capability | Where it already lives |
15
+ |---|---|
16
+ | Status/intent per row | `CompactRow.tsx` `worstIntent` / `intentColor` / `rowStripeColor` (≈L533, L996) → painted via `--readfirst-stripe` |
17
+ | Sticky glass header | `compactRowStyles.ts` `StyledCompactPanel` + FormEngine scroll-wrap `position: sticky` (≈L193) |
18
+ | Revert-to-loaded | `CompactRow` `revertButton` `.options-readfirst-revert` (L423) |
19
+ | Clear value | `CompactRow` `clearValueButton` `.options-readfirst-clear` (L460) |
20
+ | Focused (fullscreen) editing | `CompactRow` `.options-readfirst-fullscreen` → `setFocusedEditing` → `<FocusedEditing>` (L820, L852) |
21
+ | Dependency lock + nav | `CompactRow` `dependsOnChip` `.options-readfirst-lock-deps` (L922) |
22
+ | Required one-of groups | rail + cluster nodes (`readfirst-cluster-*`, `.options-readfirst-node`) |
23
+ | short_desc inline | `.options-readfirst-label-desc` (revealed by ⓘ `.options-readfirst-info-toggle`) |
24
+ | long desc | `?` help `.options-readfirst-help` + `<Description>` inside `FocusedEditing` |
25
+
26
+ So this redesign is mostly **subtractive** (flatten the recessed value surface +
27
+ intent stripe → calm flat rows) plus **one structural move** (re-group fields
28
+ into the Needs-attention / Set / Optional boxes, each carrying thin schema-group
29
+ labels) plus **one viz swap** (the required-group rail → the "One of the below is
30
+ required" cluster box).
31
+
32
+ ---
33
+
34
+ ## Answers to the five questions
35
+
36
+ ### 1. How do we show `desc` (long description)?
37
+ Unify the two existing description affordances:
38
+
39
+ - **`short_desc`** → the toolbar **Descriptions toggle** (icon-only, `info`
40
+ intent when active — exactly the prototype's button), mapped to the engine's
41
+ existing `showAllDescriptions`. Renders inline under the field name via
42
+ `.options-readfirst-label-desc`. The per-field ⓘ stays as a local override.
43
+ - **`desc` (long, markdown)** → stays where you actually read/edit the field:
44
+ rendered by `<Description longDescriptionShownByDefault>` inside
45
+ **FocusedEditing**, plus the quick `?` help (`.options-readfirst-help`). No
46
+ second always-on description button in the row.
47
+
48
+ ### 2. Dependent fields / fields with dependents?
49
+ Engine already models both — we restyle, not rebuild:
50
+
51
+ - **Disabled-by-dependency** (`depends_on` unmet): keep the **lock + "Depends on"
52
+ navigable chip** (`.options-readfirst-lock-deps`); clicking a blocker flashes
53
+ it (`readfirst-row-flash`). These are a distinct **blocked** state — neither
54
+ todo/set/optional — so they render **dimmed in place in their schema group**
55
+ (not pulled into Needs-attention; you can't act on them yet).
56
+ - **Fields with dependents**: no read-first badge needed (the engine resets
57
+ dependents on change). Optional later nicety: an "affects N fields" hint while
58
+ editing.
59
+
60
+ ### 3. Optional fields wrapper (basic dark)
61
+ The `optional` group (everything `getOptionGroup` routes there — non-preselected,
62
+ non-required, unset) renders in a **collapsible box like the others but a neutral
63
+ / dark tint** (not amber/green), collapsed by default. Same `ReqorePanel`
64
+ treatment as Set, different intent.
65
+
66
+ ### 4. Focused editing / reset-to-default / clear
67
+ Keep the engine's existing edit-card actions, restyled to match:
68
+ - **Focused editing** (`.options-readfirst-fullscreen` → `<FocusedEditing>`) — unchanged.
69
+ - **Clear value** (`.options-readfirst-clear`) — unchanged.
70
+ - **Revert** (`.options-readfirst-revert`) reverts to the *loaded* value.
71
+ - **NEW: reset-to-default** — `handleValueChange(name, schema.default_value)`,
72
+ shown only when `default_value` exists and differs. Small addition.
73
+
74
+ ### 5. Sticky header (search + progress)
75
+ Already sticky (`StyledCompactPanel` + the owned scroll context). The redesign
76
+ keeps it; the `CompactToolbar` (completion meter + filter + Descriptions toggle +
77
+ Fields menu) stays pinned. Only its contents/skin change.
78
+
79
+ ---
80
+
81
+ ## Visual-delta map (Focus feature → engine change → test impact)
82
+
83
+ Legend: **🟢 safe** = CSS-only / additive, no tested DOM·text·interaction change.
84
+ **🟡 needs test updates** = changes asserted text/structure; update listed play
85
+ functions and re-run `test:stories`.
86
+
87
+ | # | Focus feature | Engine change | File · symbol | Impact |
88
+ |---|---|---|---|---|
89
+ | 1 | Calm flat rows (no recessed surface, no intent stripe) | drop/soften the value-surface `::before` + `border-left` stripe | `compactRowStyles.ts` `StyledGroupBody > *::before` | 🟢 safe |
90
+ | 2 | Status **dot** (one mark, colour = severity) | render a dot from `rowStripeColor`/`worstIntent`; additive element | `CompactRow.tsx` (row label cell) + styles | 🟢 safe (additive class, no removed hooks) |
91
+ | 3 | Thin uppercase group labels | restyle the group header (name → 10px/upper/letter-spaced; drop hairline+chip or calm them) | `FormEngine.tsx` group render + `StyledGroupHeader`/`StyledGroupHeaderLine` | 🟢 mostly (verify no story asserts the chip text) |
92
+ | 4 | Empty value shows `—` not "Not set" | swap the empty-value copy | `CompactRow.tsx` value render | 🟡 7 assertions use `Not set` |
93
+ | 5 | Needs-attention / Set / Optional **boxes** (status grouping, schema labels inside) | regroup: bucket rows by status across schema groups; render 3 `ReqorePanel`s; thin schema labels within | `FormEngine.tsx` group-render loop | 🟡 group-structure & badge ("N to resolve") assertions |
94
+ | 6 | "One of the below is required" **cluster box** | replace rail + cluster nodes with the cluster box | `CompactRow.tsx` cluster nodes/rail + `compactRowStyles.ts` `readfirst-cluster-*`, `StyledClusterNode` | 🟡 `Covered by` / `Covers` / `One of` assertions |
95
+ | 7 | Neutral/dark Optional wrapper | intent/skin on the optional `ReqorePanel` | `FormEngine.tsx` | 🟢 safe |
96
+ | 8 | reset-to-default action | new button calling `handleValueChange(name, default_value)` | `CompactRow.tsx` | 🟢 additive |
97
+
98
+ **Use Reqore throughout** — `ReqorePanel` (boxes/collapsible), `ReqoreControlGroup`,
99
+ `ReqoreInput`, `ReqoreButton`, `ReqoreTag`, `ReqoreIcon`, `ReqoreCollapsibleContent`,
100
+ `useReqoreTheme` for every colour. No bespoke widgets where a Reqore one fits.
101
+
102
+ ---
103
+
104
+ ## Phased plan (each phase ends green)
105
+
106
+ - **P1 — Calm re-skin. ✅ DONE + validated.** Flattened the recessed value
107
+ surface + intent stripe (`StyledGroupBody > *::before` now transparent) and
108
+ added the trailing **status dot** (`StyledStatusDot`, derived from
109
+ `worstIntent`/`empty`/`required`/`coveredByLabel`/`groupResolved`). CSS +
110
+ additive DOM only — every test hook preserved. **Validated: `FormEngine.stories.tsx`
111
+ = 68 pass / 1 pre-existing fail ("Option With Any Type"), no new failures;**
112
+ `build:test` + `eslint` green; visually confirmed on :6008. *(Thin group labels
113
+ deferred to P3, where the group headers change anyway.)*
114
+
115
+ > **Validation harness (important):** `vitest run --project storybook <file>`
116
+ > runs stories in headless chromium and does **NOT** spawn a server on :6008 —
117
+ > a live `yarn storybook` is untouched. So every phase below is validatable
118
+ > without disturbing a running Storybook.
119
+ - **P3 — Status boxes. ✅ DONE + validated.** Regrouped into **Needs attention /
120
+ Set / Optional** boxes (intent-tinted `ReqorePanel`s), each with thin schema
121
+ sub-labels (`StyledStatusBoxGroupLabel`); neutral Optional. Key decisions:
122
+ - **One shared status helper** (`getReadFirstStatus`/`getReadFirstBucket` in
123
+ `readFirst.ts`) drives BOTH the row dot and the box bucket — they can't disagree.
124
+ - **One-of required-group members travel together** (bucket the whole group by
125
+ its satisfaction) so the existing rail + "One of"/"Covers"/"Covered by" chips
126
+ stay intact. Rail→cluster-box swap deferred to P4.
127
+ - **Freeze-while-editing** (`settledBucket` ref keyed by option, gated on
128
+ `expandedOptions`): an edited field — or any member of an edited one-of group —
129
+ keeps its box until the edit ends, so a status flip can't remount it mid-edit
130
+ and steal focus. (This fixed a real regression the suite guards.)
131
+ - Only **one** test legitimately changed (sort order is now status-first).
132
+ - **Validated: 68 pass / 1 pre-existing fail.** Visually confirmed on :6008.
133
+ - **P2 — Copy + empty state (🟡).** `Not set` → `— <reason>`. Update the ~10
134
+ assertions (`Not set` ×7, `Required — not set`, `Not in form — add`, covered-by).
135
+ - **P4 — Required cluster (🟡).** Rail → cluster box. Update `Covered by`/`Covers`/
136
+ `One of` assertions.
137
+ - **P5 — Polish.** reset-to-default action, depends-on dimmed-in-place styling,
138
+ responsive pass, qlip/Chromatic re-baseline.
139
+
140
+ ---
141
+
142
+ ## Test-impact appendix (the audit)
143
+
144
+ `test:stories` runs `vitest run --project storybook`, and the storybook-vitest
145
+ plugin's `storybookScript` is `yarn storybook --no-open` → it wants **:6008**,
146
+ which collides with a running `yarn storybook`. **To validate without disturbing a
147
+ live :6008**, run the suite against a separate port (temporarily point the dev
148
+ script / `storybookScript` at e.g. :6010, or stop the live instance first).
149
+
150
+ Asserted strings that constrain changes (must be preserved, or the test updated):
151
+ `Not set` (×7), `Required — not set`, `Covered by "…"`, `Covers`, `Draft`,
152
+ `Focused Editing`, `Description`, type labels (`<string>`, `<rgbcolor>`),
153
+ `N to resolve` group badges, `1 unsaved change`, plus the class/`data-field`
154
+ hooks listed in the table above. Preserve every `options-readfirst-*` /
155
+ `readfirst-*` class that a play function queries; restyle via CSS rather than
156
+ renaming.
@@ -0,0 +1,353 @@
1
+ # FormEngine Compact — UX Improvement Plan
2
+
3
+ > Status: **proposal / for review.** Nothing here is implemented yet.
4
+ > Scope: the compact ("read-first") `FormEngine` that will replace the classic
5
+ > engine in the IDE. Goal: keep its density but make it feel **calm, scannable,
6
+ > and guiding** instead of crowded and alarming.
7
+
8
+ ---
9
+
10
+ ## 0. TL;DR
11
+
12
+ The compact engine's *information architecture is right* (read-first rows you
13
+ drill into). What's wrong is **visual signal management**: it currently runs
14
+ **five overlapping status systems at once** and treats *untouched draft fields*
15
+ as **hard red errors**. The result reads like a form that's on fire when it's
16
+ actually just unfinished.
17
+
18
+ Three changes do ~80% of the work:
19
+
20
+ 1. **Collapse the 5 status systems into 1.** One global completion signal at the
21
+ top; demote/remove the redundant red banner and the per-group/per-row status
22
+ pills.
23
+ 2. **Reframe "errors" as "to-dos."** Don't show red validation errors on fields
24
+ the user hasn't touched. *Unset ≠ error.* Validate on interaction/submit.
25
+ 3. **Lock a strict one-line row template** and push everything variable
26
+ (descriptions, error reasons, nested previews, default hints) **behind
27
+ progressive disclosure**. One scannable line per field by default.
28
+
29
+ Everything else (calmer value chips, less chrome, smarter ordering, a "what's
30
+ next" path) compounds these.
31
+
32
+ ---
33
+
34
+ ## 1. North star
35
+
36
+ > A configuration **summary you can read top-to-bottom in seconds**, that quietly
37
+ > tells you *what's done, what's left, and what to do next* — and gets out of the
38
+ > way when you're just scanning.
39
+
40
+ The audience is technical (developers configuring Qorus interfaces). They *want*
41
+ density — the model is a **good data table / code editor**, not a consumer
42
+ wizard. So the goal is **"calm density,"** not fewer fields. Think: the
43
+ difference between a well-set spreadsheet and a ransom note.
44
+
45
+ ---
46
+
47
+ ## 2. What's wrong today (diagnosis)
48
+
49
+ Grounded in the screenshots + the implementation
50
+ ([`CompactToolbar.tsx`](../src/components/form/engine/CompactToolbar.tsx),
51
+ [`CompactRow.tsx`](../src/components/form/engine/CompactRow.tsx),
52
+ [`FormEngine.tsx`](../src/components/form/engine/FormEngine.tsx),
53
+ [`compactRowStyles.ts`](../src/components/form/engine/compactRowStyles.ts)).
54
+
55
+ ### 2.1 Five competing status systems
56
+ At one glance the user is shown completeness/validity **five different ways**:
57
+
58
+ | # | System | Where | Code |
59
+ |---|--------|-------|------|
60
+ | 1 | Draft badge + `12/21 fields set` + progress bar + `57%` | header | `CompactToolbar` `StyledCompletion` |
61
+ | 2 | Red banner: "6 fields are not valid… click to only show invalid" | header | `CompactToolbar` invalid banner |
62
+ | 3 | Per-group pills: `4 OPTIONAL`, `5 TO RESOLVE` | group headers | `FormEngine.tsx:1973` |
63
+ | 4 | Per-row red stripe + red ⓘ button + inline red message box | each invalid row | `CompactRow` tier-1 `StyledInfoPanel` |
64
+ | 5 | Per-row Draft chip / required asterisk / ⓘ toggle | each row | `CompactRow` `draftChip`, asterisk |
65
+
66
+ These don't reinforce — they **compete**. The user can't tell which is the
67
+ "real" status, so the whole UI reads as urgent. (NN/g *Aesthetic & minimalist
68
+ design*: every extra unit of status dilutes the rest.)
69
+
70
+ ### 2.2 Premature, alarmist validation
71
+ The form is in **DRAFT**, yet untouched fields show **hard red errors** —
72
+ "Text value is empty," "Hash arguments are invalid," "Required — not set." Two
73
+ problems:
74
+
75
+ - **Unset is not an error.** Showing red on fields the user hasn't even reached
76
+ punishes them for not-yet-doing-something. This is the single biggest driver
77
+ of the "overwhelming" feeling. (Baymard / NN/g on inline validation: validate
78
+ **on blur or on submit**, not aggressively on load; reserve red for *wrong*,
79
+ not *empty*.)
80
+ - **The error chrome is layout-disruptive.** Full-width dark-red `ReqoreMessage`
81
+ boxes render *between rows*, shoving content down and shattering the table
82
+ rhythm that makes the form scannable. Six of them = a wall of red.
83
+
84
+ ### 2.3 No focal point / flat hierarchy
85
+ Every row carries roughly equal visual weight; labels, values, blue chips,
86
+ swatches, nested trees and error boxes all shout at the same volume. There's no
87
+ "look here first," no obvious **next action**. The eye bounces. (Visual
88
+ hierarchy via size/weight/colour/space is absent within the row grid.)
89
+
90
+ ### 2.4 Inconsistent row anatomy breaks scannability
91
+ Rows are one line (`Option with value · 123`), or two (label + sub-description),
92
+ or three+ (label + value + inline error box), or have an embedded object tree
93
+ with "Show more." The **grid rhythm** — the thing that makes a dense list
94
+ scannable — is constantly broken by inline variants rendered **by default**.
95
+
96
+ ### 2.5 The value column has no consistent visual language
97
+ Plain text, **saturated-blue template chips** (`Test (local)`, `Richtext
98
+ Template`), colour swatch + hex, file pill, nested data tree — each a different
99
+ weight and colour. The blue chips in particular are *louder than the field
100
+ labels*, so decoration outshouts meaning. (Tufte: colour should encode data, not
101
+ ornament.)
102
+
103
+ ### 2.6 Heavy non-data "chrome"
104
+ Recessed value surfaces, intent stripes, group spines, required-group rails,
105
+ dividers, hover fills — a lot of subtle lines/fills create a **busy texture**
106
+ before any content is read. (Tufte *data-ink ratio*: most separators could be
107
+ whitespace.)
108
+
109
+ ### 2.7 Weak grouping semantics
110
+ "General" is a vague catch-all; "Optional/General" isn't a meaning the user
111
+ reasons with. 21 fields in 2 buckets, ordered by schema, with no
112
+ prioritisation. Findability relies on the filter box.
113
+
114
+ ---
115
+
116
+ ## 3. Principles we'll design to
117
+
118
+ | Principle | Source | Applied here |
119
+ |---|---|---|
120
+ | **One primary status channel** | NN/g *Visibility of system status* + *Minimalist design* | Collapse 5 status systems → 1 meter |
121
+ | **Validate at the right time** | Baymard; NN/g *Error prevention* | Unset ≠ error; validate on blur/submit |
122
+ | **Severity = colour, not area** | Tufte; Material/Carbon error patterns | Replace red boxes with a dot/accent |
123
+ | **Progressive disclosure** | NN/g | One line per row; reveal the rest on demand |
124
+ | **Data-ink ratio** | Tufte | Whitespace > borders for separation |
125
+ | **Recognition over recall** | NN/g | Read-first rows (already good) — keep |
126
+ | **Chunking ~5–7** | Miller's law | Smaller, purpose-named groups |
127
+ | **Ask only what's needed** | GOV.UK *question protocol* | Defer/hide rarely-used optional fields |
128
+ | **Error summary + adjacent message** | GOV.UK Design System | A navigable "needs attention" section, not a red bar |
129
+
130
+ The throughline: **the IDE audience tolerates density but not noise.** Cut
131
+ *ink*, not *information*.
132
+
133
+ ---
134
+
135
+ ## 4. The redesign — concrete moves
136
+
137
+ ### 4.1 Collapse 5 status systems into 1
138
+
139
+ **Keep** the top completion strip as the *single* global status. **Evolve it** so
140
+ it carries everything the other four systems were saying:
141
+
142
+ - Segment the bar into **set-&-valid / needs-attention / unset** (e.g. green /
143
+ amber / track), so "57% done, 6 need attention" is legible in one glance —
144
+ no separate red banner needed.
145
+ - The **"6 need attention"** count becomes a quiet, clickable affordance *on the
146
+ meter* ("→ 6 to resolve") that filters to those fields. This replaces the
147
+ red banner (system #2) with a calm, constructive control.
148
+ - **Drop the per-group `4 OPTIONAL` pill entirely** (the group is already
149
+ labelled "Optional"). Keep a per-group "N to resolve" **only when > 0**, muted
150
+ and right-aligned — or better, a thin per-group progress underline.
151
+ - **Demote the per-row Draft chip**: the *global* Draft state is enough; per-row,
152
+ "changed" is better shown by the revert ↺ affordance alone.
153
+
154
+ Net: the user has **one** place to read status, and **one** click to act on it.
155
+
156
+ ### 4.2 Errors → To-dos (validation timing & severity)
157
+
158
+ Introduce a 3-state model for a field's status, and **stop conflating them**:
159
+
160
+ | State | Meaning | Default treatment |
161
+ |---|---|---|
162
+ | **Unset** | No value, not required | Muted `—` / "Not set". **No alarm.** |
163
+ | **To-do** | Required (or required-group) but unset, untouched | **Quiet amber** dot + "Needs a value". Not red, not a box. |
164
+ | **Invalid** | User entered something that fails validation | **Red**, but only **after the field is touched** or **after a submit attempt**. |
165
+
166
+ Rules:
167
+ - **Untouched required fields are to-dos, not errors.** In a DRAFT, "Required —
168
+ not set" should be a calm amber hint, not a red error with a full-width box.
169
+ - **Validation fires on blur / on submit**, not on load. Track a per-field
170
+ `touched` flag (or a form-level `submitAttempted`).
171
+ - **The error reason moves off the default row.** Show at most a 1-word/short
172
+ inline hint after the value ("empty", "invalid"); the full message appears
173
+ **only when the row is focused/expanded** (where the editor's own message strip
174
+ already lives) or in the "needs attention" summary.
175
+
176
+ This one change removes the wall of red in the screenshot: those six boxes become
177
+ calm amber to-dos until the user engages or hits Submit.
178
+
179
+ ### 4.3 The row: one strict template + progressive disclosure
180
+
181
+ Lock a **constant 3-zone row** and keep it one line by default:
182
+
183
+ ```
184
+ [ icon? · Label · req-dot ] [ value summary ……………… ] [ status · actions ]
185
+ label col value col (ellipsis) fixed right
186
+ ```
187
+
188
+ - **Constant height, constant alignment, constant zones.** The current grid is
189
+ already close (`StyledGroupBody .readfirst-row`); the fix is *what we allow to
190
+ break it.*
191
+ - **Move out of the default row, behind disclosure (ⓘ / focus / expand):**
192
+ - field **descriptions / subtitles** (currently inline under the label),
193
+ - **error/validation messages** (currently full-width boxes),
194
+ - **default-value hints**,
195
+ - **nested object/hash previews** (the `schemaOption2 → Show more` tree) →
196
+ collapse to the "Object · 1 field" summary; reveal the tree only on expand.
197
+ - Result: a 21-field form is **21 scannable lines**, each of which *can* expand —
198
+ rather than a variable-height stack you have to parse.
199
+
200
+ ### 4.4 Value language: calm & consistent
201
+
202
+ - **Desaturate the template chips.** `Test (local)` / `Richtext Template`
203
+ currently use saturated blue and outshout the labels. Use a quiet, low-contrast
204
+ chip (subtle surface + the `$` template glyph) so the **label leads** and the
205
+ value supports. Reserve saturated colour for *state* (to-do/invalid), not for
206
+ *value type*.
207
+ - **One muted weight for all "set" values** (text, hex, filename, count). The
208
+ swatch/file-icon/`$`-glyph carry the type; the text stays uniform.
209
+ - **"Not set" gets the lightest possible treatment** (muted, no italics arms-race
210
+ with errors) so empty rows visually *recede* rather than read as problems.
211
+
212
+ ### 4.5 Reduce chrome (data-ink)
213
+
214
+ - Replace the **red left stripe + red box + red ⓘ** trio with a **single status
215
+ dot** in the right-hand status slot (colour = severity). One mark, not three.
216
+ - **Whitespace over borders.** Drop the recessed value-surface fill and the
217
+ group spine where they don't encode meaning; let alignment + a little more
218
+ vertical rhythm do the grouping. (Keep the **required-group rail** — that one
219
+ *does* encode a real relationship.)
220
+ - Audit every line/fill in `compactRowStyles.ts` against "does this encode data?"
221
+ If not, it's a candidate for removal.
222
+
223
+ ### 4.6 Grouping, ordering, findability
224
+
225
+ - **Default sort within a group = needs-attention → set → optional-unset.** Put
226
+ what the user must act on at the top of each group automatically (the existing
227
+ `invalid`/`unset` sort modes, but as the smart default for a draft).
228
+ - **Name groups by purpose.** "General" is a non-answer; if the schema gives no
229
+ meaningful group, prefer a single **Required / Optional** split over a vague
230
+ "General" bucket.
231
+ - **A pinned "Needs attention (6)" section** at the very top when there are
232
+ unresolved fields — the form's built-in answer to "what do I do next," and the
233
+ constructive replacement for the red banner (GOV.UK error-summary pattern, but
234
+ calm and always-navigable).
235
+ - Keep optional-but-unset fields **collapsed by default** behind the existing
236
+ "Optional (N)" disclosure, so the default view is "what's set + what's needed."
237
+
238
+ ### 4.7 The "what's next" path
239
+
240
+ The form should always answer *what's left?* and make it one click to get there:
241
+
242
+ - Meter → click "6 to resolve" → filter to unresolved (reuse `showInvalidOnly`,
243
+ but renamed to *"needs attention"* and including required-unset to-dos).
244
+ - On **Submit** with unresolved fields: scroll-to + focus the first, and *now*
245
+ promote to-dos to errors (the flash machinery already exists).
246
+ - Optional niceties: keyboard `n`/`p` to jump between unresolved fields; a sticky
247
+ "Next: <field> →" hint while editing.
248
+
249
+ ---
250
+
251
+ ## 5. Phased roadmap (impact × effort)
252
+
253
+ ### P0 — quick wins (high impact, low effort): "stop shouting"
254
+ 1. **Unset ≠ error.** Don't render red boxes/stripes for untouched required/empty
255
+ fields; downgrade to quiet amber to-dos. *(biggest single win)*
256
+ 2. **Remove the red invalid banner**; fold the count into the meter as a quiet
257
+ "→ N to resolve" control.
258
+ 3. **Drop the `N OPTIONAL` group pill**; show "N to resolve" only when > 0, muted.
259
+ 4. **Move field descriptions + error messages off the default row** (behind ⓘ /
260
+ focus). One line per row.
261
+ 5. **Desaturate template chips.**
262
+
263
+ > P0 alone should resolve "crowded and overwhelming" for the screenshot case.
264
+
265
+ ### P1 — structural (medium effort): "calm density"
266
+ 6. Segmented completion meter (set / to-do / unset).
267
+ 7. Strict row template + collapse nested previews to summaries by default.
268
+ 8. Single status-dot system; remove redundant stripes/boxes/ⓘ-buttons.
269
+ 9. Validation timing: per-field `touched` + `submitAttempted`.
270
+ 10. Smart default ordering (needs-attention first) + purpose-named groups.
271
+
272
+ ### P2 — ambition (higher effort): "truly great"
273
+ 11. Pinned **"Needs attention"** navigator section + keyboard jump.
274
+ 12. Reduce the "edit card" modality — inline-first editing everywhere it fits.
275
+ 13. **Density toggle** (comfortable / compact) for newcomers vs power users.
276
+ 14. Per-group progress underline; section-level "all set" collapse.
277
+ 15. Telemetry-driven defaults (collapse rarely-touched optional fields).
278
+
279
+ ---
280
+
281
+ ## 6. Component-level change list (where the work lands)
282
+
283
+ | Area | File | Change |
284
+ |---|---|---|
285
+ | Status consolidation | `CompactToolbar.tsx` | Segmented meter; remove invalid banner; "N to resolve" control |
286
+ | Group header | `FormEngine.tsx:1968` `StyledGroupHeader` | Drop `N OPTIONAL`; muted "to resolve"; optional progress underline |
287
+ | Row template & disclosure | `CompactRow.tsx` | Move desc/error/default-hint behind disclosure; single status dot; calm chips |
288
+ | Validation model | `FormEngine.tsx` validity data + `CompactRow` | `touched`/`submitAttempted`; unset→to-do vs invalid |
289
+ | Visual chrome | `compactRowStyles.ts` | Remove non-data stripes/fills; whitespace rhythm; keep required rail |
290
+ | Ordering / sections | `FormEngine.tsx` group + sort | Needs-attention-first default; "Needs attention" section |
291
+ | Value language | `readFirst.ts` + `CompactRow` `renderReadFirstValue` | Uniform muted weight; desaturated template/richtext chips |
292
+
293
+ None of this changes the schema/value/`onChange` contract — it's all
294
+ presentation, consistent with the compact mode's existing "purely presentational"
295
+ design.
296
+
297
+ ---
298
+
299
+ ## 7. Open questions (to decide / validate with users)
300
+
301
+ 1. **Validation timing**: blur-only, or also a gentle "you skipped a required
302
+ field" on navigate-away? (Lean: blur + submit.)
303
+ 2. Is **"General"** a real schema group or a fallback bucket? If fallback, can we
304
+ suppress the group chrome entirely for single-group schemas?
305
+ 3. How often are the **nested object/hash previews** actually read at a glance vs
306
+ noise? (Telemetry / quick user check before investing in them.)
307
+ 4. Do power users want the **density toggle**, or should we just ship one
308
+ well-tuned density?
309
+ 5. Should **optional-unset** fields be collapsed by default (cleaner) or visible
310
+ (discoverable)? Likely collapsed with a strong "+ N optional" affordance.
311
+
312
+ ---
313
+
314
+ ## 8. How we'll know it worked
315
+
316
+ - **Time-to-first-meaningful-scan** (qual): can a new user say "what's left?" in
317
+ < 5s?
318
+ - **Perceived calm** (5-pt survey before/after on the same schema).
319
+ - **Error-recovery**: time from Submit-blocked to all-resolved.
320
+ - **Eye-bounce** (optional): fewer fixations to locate the next action.
321
+ - Objective: **default view height** for the screenshot schema should drop
322
+ substantially once errors/descriptions move behind disclosure.
323
+
324
+ ---
325
+
326
+ ## 9. References
327
+
328
+ - Nielsen Norman Group — *10 Usability Heuristics* (esp. Aesthetic & minimalist
329
+ design, Visibility of system status, Error prevention); *Progressive
330
+ Disclosure*; *Inline Validation in Web Forms*.
331
+ - Baymard Institute — form usability research (inline validation timing;
332
+ required vs optional).
333
+ - GOV.UK Design System — *Error summary* + *error message* patterns; *question
334
+ protocol* ("only ask what you need").
335
+ - Edward Tufte — *The Visual Display of Quantitative Information* (data-ink
336
+ ratio).
337
+ - Miller (1956) — chunking (~7±2).
338
+ - Design-system form guidance: Material 3, IBM Carbon, Shopify Polaris
339
+ (error/state colour conventions, one-column dense forms).
340
+
341
+ ---
342
+
343
+ ### Appendix — mapping the screenshot to the fixes
344
+
345
+ | In the screenshot | Why it feels heavy | Fix (section) |
346
+ |---|---|---|
347
+ | Red banner "6 fields are not valid…" | System #2, alarmist | 4.1 / P0-2 |
348
+ | `4 OPTIONAL` / `5 TO RESOLVE` pills | System #3, competes with titles | 4.1 / P0-3 |
349
+ | Red box "Text value is empty" (untouched) | Premature error | 4.2 / P0-1 |
350
+ | Red box "Hash arguments are invalid" inline | Layout-disruptive error | 4.2 / 4.3 |
351
+ | Saturated blue `Test (local)` chip | Decoration outshouts label | 4.4 / P0-5 |
352
+ | `schemaOption2 → Show more` tree inline | Breaks row rhythm | 4.3 / P1-7 |
353
+ | Per-row red stripe + red ⓘ + red box | Three marks for one state | 4.5 / P1-8 |
@@ -1,6 +1,14 @@
1
1
  /// <reference types="react" />
2
2
  import { IReqoreModalProps } from '@qoretechnologies/reqore/dist/components/Modal';
3
- export declare const FocusedEditing: import("react").MemoExoticComponent<({ children, isFullscreen, ...rest }: IReqoreModalProps & {
3
+ export declare const FocusedEditing: import("react").MemoExoticComponent<({ children, isFullscreen, modalOnly, ...rest }: IReqoreModalProps & {
4
4
  isFullscreen?: boolean;
5
+ /**
6
+ * Render ONLY the modal, not the in-place copy of `children`. For call
7
+ * sites that already render the field themselves and just need the focused
8
+ * overlay on top — e.g. the compact row's inline editor, which lives in the
9
+ * row grid and must stay there. Default (`false`) renders children in place
10
+ * as well, which is what the classic and card layouts wrap themselves in.
11
+ */
12
+ modalOnly?: boolean;
5
13
  }) => import("react/jsx-runtime").JSX.Element>;
6
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FocusedEditing/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAe,MAAM,gDAAgD,CAAC;AAGhG,eAAO,MAAM,cAAc,4EACa,iBAAiB,GAAG;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,6CA8BrF,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FocusedEditing/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAe,MAAM,gDAAgD,CAAC;AAGhG,eAAO,MAAM,cAAc,uFAMtB,iBAAiB,GAAG;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,6CA8BF,CAAC"}